diff --git a/lib/core/theme/app_colors.dart b/lib/core/theme/app_colors.dart index fe056e1..a5c44ba 100644 --- a/lib/core/theme/app_colors.dart +++ b/lib/core/theme/app_colors.dart @@ -15,7 +15,7 @@ class AppColors { static const Color background = Color(0xFF000000); /// Very deep grey for surfaces that need to be distinct but subtle (Apple Dark Grey) - static const Color surface = Color(0xFF2C2C2E); + static const Color surface = Color(0xFF1C1C1E); /// Slightly lighter grey for secondary surfaces or hover states static const Color surfaceVariant = Color(0xFF3A3A3C); diff --git a/lib/features/iptv/screens/dashboard_screen.dart b/lib/features/iptv/screens/dashboard_screen.dart index 95f695b..9c69c10 100644 --- a/lib/features/iptv/screens/dashboard_screen.dart +++ b/lib/features/iptv/screens/dashboard_screen.dart @@ -48,7 +48,7 @@ class _DashboardScreenState extends ConsumerState with SingleTi // Glassmorphism Top Bar return Scaffold( extendBodyBehindAppBar: true, // Content behind app bar - backgroundColor: AppColors.background, + backgroundColor: Colors.transparent, // Transparent to show gradient appBar: PreferredSize( preferredSize: const Size.fromHeight(80), child: Container( @@ -58,19 +58,43 @@ class _DashboardScreenState extends ConsumerState with SingleTi begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - Colors.black.withOpacity(0.9), // Darker at top + Colors.black.withOpacity(0.6), // Subtler top shadow Colors.transparent, ], ), ), - child: Row( + child: Stack( + alignment: Alignment.center, children: [ - // Logo Area - _buildLogo(), + // 1. Side Elements (Logo & Profile) - Pushed to edges + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Logo Area + _buildLogo(), + + // Search / Profile (Right Side) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: const Icon(Icons.search, color: Colors.white), + onPressed: () { + // Global search trigger + }, + ), + const SizedBox(width: 8), + const CircleAvatar( + radius: 16, + backgroundColor: Colors.white24, + child: Icon(Icons.person, size: 18, color: Colors.white), + ), + ], + ), + ], + ), - const Spacer(), - - // Centered Navigation Tabs (Pills) + // 2. Centered Navigation Tabs (Pills) Container( height: 50, decoration: BoxDecoration( @@ -108,35 +132,39 @@ class _DashboardScreenState extends ConsumerState with SingleTi }), ), ), - - const Spacer(), - - // Search / Profile (Right Side) - IconButton( - icon: const Icon(Icons.search, color: Colors.white), - onPressed: () { - // Global search trigger - }, - ), - const SizedBox(width: 8), - const CircleAvatar( - radius: 16, - backgroundColor: Colors.white24, - child: Icon(Icons.person, size: 18, color: Colors.white), - ), ], ), ), ), - body: TabBarView( - controller: _tabController, - physics: const NeverScrollableScrollPhysics(), // Disable swipe to avoid gesture conflicts + body: Stack( children: [ - // Padding top to account for the transparent AppBar - Padding(padding: const EdgeInsets.only(top: 80), child: LiveTVTab(playlist: widget.playlist)), - Padding(padding: const EdgeInsets.only(top: 80), child: MoviesTab(playlist: widget.playlist)), - Padding(padding: const EdgeInsets.only(top: 80), child: SeriesTab(playlist: widget.playlist)), - const Padding(padding: EdgeInsets.only(top: 80), child: SettingsTab()), + // Background Gradient (Apple TV Depth Effect) + Container( + decoration: const BoxDecoration( + gradient: RadialGradient( + center: Alignment(0, -0.2), // Slightly above center + radius: 1.5, + colors: [ + Color(0xFF2C2C2E), // Dark Grey center (Light Source) + Color(0xFF000000), // Pure Black edges + ], + stops: [0.0, 1.0], + ), + ), + ), + + // Content + TabBarView( + controller: _tabController, + physics: const NeverScrollableScrollPhysics(), // Disable swipe to avoid gesture conflicts + children: [ + // Padding top to account for the transparent AppBar + Padding(padding: const EdgeInsets.only(top: 80), child: LiveTVTab(playlist: widget.playlist)), + Padding(padding: const EdgeInsets.only(top: 80), child: MoviesTab(playlist: widget.playlist)), + Padding(padding: const EdgeInsets.only(top: 80), child: SeriesTab(playlist: widget.playlist)), + const Padding(padding: EdgeInsets.only(top: 80), child: SettingsTab()), + ], + ), ], ), ); diff --git a/lib/features/iptv/widgets/channel_card.dart b/lib/features/iptv/widgets/channel_card.dart index 676b134..4e42a9e 100644 --- a/lib/features/iptv/widgets/channel_card.dart +++ b/lib/features/iptv/widgets/channel_card.dart @@ -52,6 +52,11 @@ class _ChannelCardState extends ConsumerState vsync: this, duration: const Duration(milliseconds: 1000) )..repeat(reverse: true); + + // Fetch EPG immediately when card is built + WidgetsBinding.instance.addPostFrameCallback((_) { + _fetchEpg(); + }); } @override @@ -107,7 +112,6 @@ class _ChannelCardState extends ConsumerState return MouseRegion( onEnter: (_) { setState(() => _isHovered = true); - if (!_epgLoaded) _fetchEpg(); }, onExit: (_) => setState(() => _isHovered = false), cursor: SystemMouseCursors.click, @@ -228,7 +232,7 @@ class _ChannelCardState extends ConsumerState fontSize: 13, ), ), - if ((widget.currentProgram != null || _epgNow != null) && _isHovered) ...[ + if ((widget.currentProgram != null || _epgNow != null)) ...[ const SizedBox(height: 2), Text( _epgNow ?? widget.currentProgram ?? '',