diff --git a/lib/features/iptv/widgets/mobile_live_tv_tab.dart b/lib/features/iptv/widgets/mobile_live_tv_tab.dart index 8d9ef75..c024c32 100644 --- a/lib/features/iptv/widgets/mobile_live_tv_tab.dart +++ b/lib/features/iptv/widgets/mobile_live_tv_tab.dart @@ -197,10 +197,10 @@ class _MobileLiveTVTabState extends ConsumerState slivers: [ // Floating Header (Search + Navigation) SliverAppBar( - floating: true, - pinned: false, - snap: true, - backgroundColor: Colors.transparent, // Minimal background + floating: false, + pinned: true, + snap: false, + backgroundColor: const Color(0xFF000000), // Opaque black elevation: 0, scrolledUnderElevation: 0, automaticallyImplyLeading: false, diff --git a/lib/mobile/widgets/mobile_poster_card.dart b/lib/mobile/widgets/mobile_poster_card.dart index f41850a..4a12b12 100644 --- a/lib/mobile/widgets/mobile_poster_card.dart +++ b/lib/mobile/widgets/mobile_poster_card.dart @@ -30,8 +30,9 @@ class MobilePosterCard extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - // Shadow lives on this outer Container so ClipRRect doesn't swallow it - Expanded( + // FIXED Aspect Ratio for the image part to avoid stretching + AspectRatio( + aspectRatio: 2 / 3, child: Container( decoration: AppDecorations.glossyCard(context, radius: 12), child: TVFocusable( @@ -48,97 +49,32 @@ class MobilePosterCard extends StatelessWidget { ? CachedNetworkImage( imageUrl: imageUrl!, fit: BoxFit.cover, - memCacheWidth: 120, - memCacheHeight: 180, - maxWidthDiskCache: 120, - maxHeightDiskCache: 180, + alignment: Alignment.center, + memCacheWidth: 200, // Increased for better quality + memCacheHeight: 300, + maxWidthDiskCache: 400, + maxHeightDiskCache: 600, cacheManager: AppCacheManager.instance, - errorWidget: (_, __, ___) => Container( - decoration: - AppDecorations.channelCardBase(context), - child: Icon( - placeholderIcon, - color: AppDecorations.iconMuted(context), - ), - ), - placeholder: (_, __) => Container( - decoration: - AppDecorations.channelCardBase(context), - child: Icon( - placeholderIcon, - color: AppDecorations.iconMuted(context), - ), - ), + errorWidget: (_, __, ___) => _buildPlaceholder(context), + placeholder: (_, __) => _buildPlaceholder(context), ) - : Container( - decoration: AppDecorations.channelCardBase(context), - child: Icon( - placeholderIcon, - color: AppDecorations.iconMuted(context), - ), - ), + : _buildPlaceholder(context), ), // Rating badge - if (rating != null) - Positioned( - top: 6, - left: 6, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 4, - vertical: 2, - ), - decoration: BoxDecoration( - color: Colors.black87, - borderRadius: BorderRadius.circular(4), - ), - child: Row( - children: [ - const Icon( - Icons.star, - color: Colors.amber, - size: 10, - ), - const SizedBox(width: 2), - Text( - rating!, - style: const TextStyle( - color: Colors.white, - fontSize: 10, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - ), + if (rating != null && rating!.isNotEmpty) + _buildRatingBadge(), // Watched badge if (isWatched) - Positioned( - top: 6, - right: 6, - child: Container( - padding: const EdgeInsets.all(4), - decoration: const BoxDecoration( - color: Color(0xFF30D158), - shape: BoxShape.circle, - ), - child: const Icon( - Icons.check, - size: 10, - color: Colors.white, - ), - ), - ), + _buildWatchedBadge(), // Glossy highlight overlay (top shimmer) Positioned( top: 0, left: 0, right: 0, - height: 80, // Taller for posters + height: 60, child: IgnorePointer( child: Container( decoration: AppDecorations.glossShimmer(context, radius: 12), @@ -151,24 +87,85 @@ class MobilePosterCard extends StatelessWidget { ), ), - const SizedBox(height: 6), + const SizedBox(height: 4), - // Title - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Text( - title, - textAlign: TextAlign.center, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: AppDecorations.textPrimary(context), - fontSize: 12, - fontWeight: FontWeight.w500, + // Title with fixed height to avoid pushing the image + SizedBox( + height: 16, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Text( + title, + textAlign: TextAlign.center, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: AppDecorations.textPrimary(context), + fontSize: 11, + fontWeight: FontWeight.w500, + ), ), ), ), ], ); } + + Widget _buildPlaceholder(BuildContext context) { + return Container( + decoration: AppDecorations.channelCardBase(context), + child: Icon( + placeholderIcon, + color: AppDecorations.iconMuted(context), + ), + ); + } + + Widget _buildRatingBadge() { + return Positioned( + top: 6, + left: 6, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2), + decoration: BoxDecoration( + color: Colors.black87, + borderRadius: BorderRadius.circular(4), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.star, color: Colors.amber, size: 10), + const SizedBox(width: 2), + Text( + rating!, + style: const TextStyle( + color: Colors.white, + fontSize: 10, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ); + } + + Widget _buildWatchedBadge() { + return Positioned( + top: 6, + right: 6, + child: Container( + padding: const EdgeInsets.all(4), + decoration: const BoxDecoration( + color: Color(0xFF30D158), + shape: BoxShape.circle, + ), + child: const Icon( + Icons.check, + size: 10, + color: Colors.white, + ), + ), + ); + } }