Spaces:
Runtime error
Runtime error
| import 'package:flutter/material.dart'; | |
| import 'package:shimmer/shimmer.dart'; | |
| import '../main.dart'; | |
| /// A reusable skeleton loader that uses the app's theme colors. | |
| class SkeletonLoader extends StatelessWidget { | |
| final double width; | |
| final double height; | |
| final double borderRadius; | |
| const SkeletonLoader({ | |
| super.key, | |
| required this.width, | |
| required this.height, | |
| this.borderRadius = 8.0, | |
| }); | |
| Widget build(BuildContext context) { | |
| return Shimmer.fromColors( | |
| baseColor: AppColors.shimmerBase, | |
| highlightColor: AppColors.shimmerHighlight, | |
| child: Container( | |
| width: width, | |
| height: height, | |
| decoration: BoxDecoration( | |
| color: AppColors.shimmerBase, | |
| borderRadius: BorderRadius.circular(borderRadius), | |
| ), | |
| ), | |
| ); | |
| } | |
| } | |
| /// A standard multi-line text skeleton | |
| class TextSkeleton extends StatelessWidget { | |
| final int lines; | |
| final double width; | |
| final double lineHeight; | |
| const TextSkeleton({ | |
| super.key, | |
| this.lines = 3, | |
| this.width = double.infinity, | |
| this.lineHeight = 12.0, | |
| }); | |
| Widget build(BuildContext context) { | |
| return Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| mainAxisSize: MainAxisSize.min, | |
| children: List.generate(lines, (index) { | |
| // Make the last line slightly shorter for realism | |
| double lineWidth = width; | |
| if (index == lines - 1 && width == double.infinity) { | |
| lineWidth = MediaQuery.of(context).size.width * 0.6; | |
| } | |
| return Padding( | |
| padding: EdgeInsets.only(bottom: index == lines - 1 ? 0 : 8.0), | |
| child: SkeletonLoader( | |
| width: lineWidth, | |
| height: lineHeight, | |
| borderRadius: 6.0, | |
| ), | |
| ); | |
| }), | |
| ); | |
| } | |
| } | |
| /// A skeleton loader styled like a news/result card | |
| class CardSkeleton extends StatelessWidget { | |
| const CardSkeleton({super.key}); | |
| Widget build(BuildContext context) { | |
| return Container( | |
| padding: const EdgeInsets.all(20), | |
| decoration: BoxDecoration( | |
| color: AppColors.cardBg, | |
| borderRadius: BorderRadius.circular(16), | |
| border: Border.all(color: AppColors.divider), | |
| ), | |
| child: Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| Row( | |
| children: [ | |
| const SkeletonLoader(width: 48, height: 48, borderRadius: 24), | |
| const SizedBox(width: 16), | |
| Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: const [ | |
| SkeletonLoader(width: 140, height: 16), | |
| SizedBox(height: 8), | |
| SkeletonLoader(width: 80, height: 12), | |
| ], | |
| ), | |
| ], | |
| ), | |
| const SizedBox(height: 24), | |
| const TextSkeleton(lines: 4), | |
| const SizedBox(height: 24), | |
| Row( | |
| children: const [ | |
| SkeletonLoader(width: 100, height: 36, borderRadius: 18), | |
| SizedBox(width: 12), | |
| SkeletonLoader(width: 80, height: 36, borderRadius: 18), | |
| ], | |
| ), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |