diff --git a/lib/core/theme/app_colors.dart b/lib/core/theme/app_colors.dart index 2234c8a..5a28049 100644 --- a/lib/core/theme/app_colors.dart +++ b/lib/core/theme/app_colors.dart @@ -53,6 +53,14 @@ class AppColors { /// en restant la même couleur perçue. static const Color primaryFill = Color(0xFFA8360C); + /// Encre chaude — remplace le noir pur pour du texte/des icônes posés sur un + /// remplissage clair (crème, ember clair). Un noir pur sur une teinte chaude + /// paraît sale ; ce brun très sombre garde le contraste sans le décalage. + static const Color onPrimaryFixed = Color(0xFF360F00); + static const Color primaryFixed = Color(0xFFFFDBC8); + static const Color primaryFixedDim = Color(0xFFFFB68C); + static const Color onPrimaryFixedVariant = Color(0xFF7A2C08); + // ============ SECONDARY (Terre cuite / argile) ============ static const Color secondary = Color(0xFFE7C3AC); static const Color onSecondary = Color(0xFF442A1B); @@ -92,6 +100,7 @@ class AppColors { static const Color onSurface24 = Color(0x3DF3E9DF); static const Color onSurface38 = Color(0x61F3E9DF); static const Color onSurface54 = Color(0x8AF3E9DF); + static const Color onSurface70 = Color(0xB3F3E9DF); // ============ STATUS ============ static const Color success = Color(0xFF9BC46A); // olive lumineux diff --git a/lib/core/utils/image_cache_config.dart b/lib/core/utils/image_cache_config.dart index 9e4bbef..4d1cfab 100644 --- a/lib/core/utils/image_cache_config.dart +++ b/lib/core/utils/image_cache_config.dart @@ -10,6 +10,7 @@ library; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; +import 'package:xtremobile/core/theme/app_colors.dart'; /// Standard cache manager with 200MB size limit class AppCacheManager { @@ -103,7 +104,7 @@ class ImageCacheConfig { width: width, height: height, decoration: BoxDecoration( - color: const Color(0xFF2C2C2E), + color: AppColors.surfaceContainer, borderRadius: BorderRadius.circular(8), ), ), @@ -111,10 +112,10 @@ class ImageCacheConfig { width: width, height: height, decoration: BoxDecoration( - color: const Color(0xFF3A3A3C), + color: AppColors.surfaceContainerHigh, borderRadius: BorderRadius.circular(8), ), - child: const Icon(Icons.image_not_supported, color: Color(0xFF8E8E93)), + child: const Icon(Icons.image_not_supported, color: AppColors.textTertiary), ), ); } diff --git a/lib/core/widgets/components/hero_carousel.dart b/lib/core/widgets/components/hero_carousel.dart index cfa6738..54b53be 100644 --- a/lib/core/widgets/components/hero_carousel.dart +++ b/lib/core/widgets/components/hero_carousel.dart @@ -150,7 +150,7 @@ class _HeroCarouselState extends State { style: GoogleFonts.outfit( fontSize: 32, fontWeight: FontWeight.bold, - color: Colors.white, + color: AppColors.onSurface, ), maxLines: 2, overflow: TextOverflow.ellipsis, @@ -161,7 +161,7 @@ class _HeroCarouselState extends State { item.subtitle!, style: GoogleFonts.inter( fontSize: 16, - color: Colors.white.withOpacity(0.8), + color: AppColors.onSurface.withOpacity(0.8), ), maxLines: 2, overflow: TextOverflow.ellipsis, @@ -227,8 +227,8 @@ class _HeroButtonState extends State<_HeroButton> { padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), decoration: BoxDecoration( color: widget.isPrimary - ? (_isHovered ? Colors.white : Colors.white.withOpacity(0.9)) - : (_isHovered ? Colors.white.withOpacity(0.2) : Colors.white.withOpacity(0.1)), + ? (_isHovered ? AppColors.onSurface : AppColors.onSurface.withOpacity(0.9)) + : (_isHovered ? AppColors.onSurface.withOpacity(0.2) : AppColors.onSurface.withOpacity(0.1)), borderRadius: BorderRadius.circular(AppTheme.radiusFull), ), child: Row( @@ -236,14 +236,14 @@ class _HeroButtonState extends State<_HeroButton> { children: [ Icon( widget.icon, - color: widget.isPrimary ? Colors.black : Colors.white, + color: widget.isPrimary ? AppColors.onPrimaryFixed : AppColors.onSurface, size: 20, ), const SizedBox(width: 8), Text( widget.label, style: GoogleFonts.inter( - color: widget.isPrimary ? Colors.black : Colors.white, + color: widget.isPrimary ? AppColors.onPrimaryFixed : AppColors.onSurface, fontWeight: FontWeight.w600, ), ), diff --git a/lib/core/widgets/components/ui_components.dart b/lib/core/widgets/components/ui_components.dart index 139d907..889bf67 100644 --- a/lib/core/widgets/components/ui_components.dart +++ b/lib/core/widgets/components/ui_components.dart @@ -134,7 +134,7 @@ class _GradientButtonState extends State height: 20, child: CircularProgressIndicator( strokeWidth: 2, - color: Colors.black, + color: AppColors.onPrimaryFixed, ), ) : Row( @@ -143,13 +143,13 @@ class _GradientButtonState extends State mainAxisAlignment: MainAxisAlignment.center, children: [ if (widget.icon != null) ...[ - Icon(widget.icon, color: Colors.black, size: 20), + Icon(widget.icon, color: AppColors.onPrimaryFixed, size: 20), const SizedBox(width: 8), ], Text( widget.label, style: const TextStyle( - color: Colors.black, + color: AppColors.onPrimaryFixed, fontWeight: FontWeight.w600, fontSize: 14, ), @@ -247,12 +247,12 @@ class LiveBadge extends StatelessWidget { child: const Row( mainAxisSize: MainAxisSize.min, children: [ - Icon(Icons.circle, size: 6, color: Colors.white), + Icon(Icons.circle, size: 6, color: AppColors.onSurface), SizedBox(width: 4), Text( 'LIVE', style: TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontSize: 10, fontWeight: FontWeight.w700, ), @@ -427,11 +427,11 @@ class _MediaCardState extends State child: Row( mainAxisSize: MainAxisSize.min, children: [ - const Icon(Icons.star, size: 10, color: Color(0xFFFFD700)), + const Icon(Icons.star, size: 10, color: AppColors.ratingGold), const SizedBox(width: 4), Text( widget.rating!, - style: const TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold), + style: const TextStyle(color: AppColors.onSurface, fontSize: 10, fontWeight: FontWeight.bold), ), ], ), @@ -449,7 +449,7 @@ class _MediaCardState extends State color: AppColors.success, shape: BoxShape.circle, ), - child: const Icon(Icons.check, size: 12, color: Colors.white), + child: const Icon(Icons.check, size: 12, color: AppColors.onSurface), ), ), ], diff --git a/lib/core/widgets/digital_clock.dart b/lib/core/widgets/digital_clock.dart index 7ceda67..b08baa4 100644 --- a/lib/core/widgets/digital_clock.dart +++ b/lib/core/widgets/digital_clock.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; +import 'package:xtremobile/core/theme/app_colors.dart'; class DigitalClock extends StatefulWidget { const DigitalClock({super.key}); @@ -31,16 +32,16 @@ class _DigitalClockState extends State { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.1), + color: AppColors.onSurface.withOpacity(0.1), borderRadius: BorderRadius.circular(20), - border: Border.all(color: Colors.white.withOpacity(0.05)), + border: Border.all(color: AppColors.onSurface.withOpacity(0.05)), ), child: Text( timeString, style: GoogleFonts.inter( fontWeight: FontWeight.w600, fontSize: 16, - color: Colors.white, + color: AppColors.onSurface, ), ), ); diff --git a/lib/core/widgets/themed_loading_screen.dart b/lib/core/widgets/themed_loading_screen.dart index e1db1dd..0d0d5f1 100644 --- a/lib/core/widgets/themed_loading_screen.dart +++ b/lib/core/widgets/themed_loading_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:xtremobile/core/theme/app_colors.dart'; class ThemedLoading extends StatelessWidget { const ThemedLoading({super.key}); @@ -11,7 +12,7 @@ class ThemedLoading extends StatelessWidget { center: Alignment(0, -0.2), radius: 1.5, colors: [ - Color(0xFF2C2C2E), + AppColors.surfaceContainerHigh, Color(0xFF000000), ], stops: [0.0, 1.0], @@ -19,7 +20,7 @@ class ThemedLoading extends StatelessWidget { ), child: const Center( child: CircularProgressIndicator( - color: Colors.white, + color: AppColors.onSurface, strokeWidth: 3, ), ), diff --git a/lib/features/iptv/screens/lite_player_screen.dart b/lib/features/iptv/screens/lite_player_screen.dart index 6e564c4..c303fc3 100644 --- a/lib/features/iptv/screens/lite_player_screen.dart +++ b/lib/features/iptv/screens/lite_player_screen.dart @@ -416,6 +416,7 @@ class _LitePlayerScreenState extends ConsumerState : widget.title; return Scaffold( + // True black behind the video surface, never the warm ink. backgroundColor: Colors.black, body: GestureDetector( onTap: _onUserInteraction, @@ -453,7 +454,7 @@ class _LitePlayerScreenState extends ConsumerState ), child: const Icon( Icons.arrow_back, - color: Colors.white, + color: AppColors.onSurface, size: 28, ), ), @@ -472,7 +473,7 @@ class _LitePlayerScreenState extends ConsumerState child: Text( _currentTime, style: const TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontSize: 18, fontWeight: FontWeight.bold, ), @@ -495,7 +496,7 @@ class _LitePlayerScreenState extends ConsumerState ), child: Text( _errorMessage!, - style: const TextStyle(color: Colors.red), + style: const TextStyle(color: AppColors.error), ), ), ), @@ -554,7 +555,7 @@ class _LitePlayerScreenState extends ConsumerState decoration: BoxDecoration( color: Colors.black.withOpacity(0.7), borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.white10), + border: Border.all(color: AppColors.onSurface12), ), child: IntrinsicHeight( child: Row( @@ -579,7 +580,7 @@ class _LitePlayerScreenState extends ConsumerState ), child: const Icon( Icons.skip_previous, - color: Colors.white, + color: AppColors.onSurface, size: 36, ), ), @@ -591,7 +592,7 @@ class _LitePlayerScreenState extends ConsumerState _isPlaying ? Icons.pause_circle_filled : Icons.play_circle_filled, - color: Colors.white, + color: AppColors.onSurface, size: 56, ), ), @@ -605,7 +606,7 @@ class _LitePlayerScreenState extends ConsumerState ), child: const Icon( Icons.skip_next, - color: Colors.white, + color: AppColors.onSurface, size: 36, ), ), @@ -642,7 +643,7 @@ class _LitePlayerScreenState extends ConsumerState child: const Icon( Icons .grid_on, // Icon representing interlaced grid/mesh - color: Colors.white, + color: AppColors.onSurface, size: 32, ), ), @@ -684,7 +685,7 @@ class _LitePlayerScreenState extends ConsumerState child: Text( title, style: const TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontSize: 18, fontWeight: FontWeight.bold, ), @@ -710,7 +711,7 @@ class _LitePlayerScreenState extends ConsumerState borderRadius: BorderRadius.circular(4), child: LinearProgressIndicator( value: progress, - backgroundColor: Colors.white10, + backgroundColor: AppColors.onSurface12, color: AppColors.primary, minHeight: 4, ), @@ -718,7 +719,7 @@ class _LitePlayerScreenState extends ConsumerState const SizedBox(height: 6), Text( next, - style: const TextStyle(color: Colors.white54, fontSize: 12), + style: const TextStyle(color: AppColors.onSurface54, fontSize: 12), maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -758,7 +759,7 @@ class _LitePlayerScreenState extends ConsumerState min: 0, max: _duration.inSeconds.toDouble(), activeColor: AppColors.primary, - inactiveColor: Colors.white24, + inactiveColor: AppColors.onSurface24, onChanged: (v) => setState(() { _position = Duration(seconds: v.toInt()); _isSeeking = true; diff --git a/lib/features/iptv/screens/mobile_playlist_screen.dart b/lib/features/iptv/screens/mobile_playlist_screen.dart index faaa4a1..f49e3f2 100644 --- a/lib/features/iptv/screens/mobile_playlist_screen.dart +++ b/lib/features/iptv/screens/mobile_playlist_screen.dart @@ -236,7 +236,7 @@ class _MobilePlaylistScreenState extends ConsumerState { ? 'Playlist modifiée' : 'Playlist ajoutée', ), - backgroundColor: Colors.green, + backgroundColor: AppColors.success, ), ); } diff --git a/lib/features/iptv/screens/mobile_playlist_selection_screen.dart b/lib/features/iptv/screens/mobile_playlist_selection_screen.dart index 05a7661..cbdc8a7 100644 --- a/lib/features/iptv/screens/mobile_playlist_selection_screen.dart +++ b/lib/features/iptv/screens/mobile_playlist_selection_screen.dart @@ -125,7 +125,7 @@ class _MobilePlaylistSelectionScreenState const SizedBox(height: 16), Text( 'Erreur de chargement', - style: GoogleFonts.inter(color: Colors.white), + style: GoogleFonts.inter(color: AppColors.onSurface), ), TextButton( onPressed: () => ref.invalidate(playlistsProvider), @@ -143,14 +143,14 @@ class _MobilePlaylistSelectionScreenState const Icon( Icons.playlist_add, size: 64, - color: Colors.white54, + color: AppColors.onSurface54, ), const SizedBox(height: 24), Text( 'Aucune playlist configurée', style: GoogleFonts.inter( fontSize: 18, - color: Colors.white70, + color: AppColors.onSurface70, ), ), const SizedBox(height: 32), @@ -163,18 +163,18 @@ class _MobilePlaylistSelectionScreenState vertical: 14, ), decoration: BoxDecoration( - color: const Color(0xFF0A84FF), + color: AppColors.primaryFill, borderRadius: BorderRadius.circular(12), ), child: const Row( mainAxisSize: MainAxisSize.min, children: [ - Icon(Icons.add, color: Colors.white, size: 20), + Icon(Icons.add, color: AppColors.onSurface, size: 20), SizedBox(width: 10), Text( 'Ajouter une Playlist', style: TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontWeight: FontWeight.bold, fontSize: 15, ), @@ -268,21 +268,21 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> { context: context, builder: (ctx) => AlertDialog( backgroundColor: AppColors.surface, - title: Text(label, style: const TextStyle(color: Colors.white)), + title: Text(label, style: const TextStyle(color: AppColors.onSurface)), content: TextField( controller: controller, autofocus: true, obscureText: obscure, keyboardType: keyboardType, textInputAction: TextInputAction.done, - style: const TextStyle(color: Colors.white), + style: const TextStyle(color: AppColors.onSurface), decoration: const InputDecoration( - labelStyle: TextStyle(color: Colors.white70), + labelStyle: TextStyle(color: AppColors.onSurface70), enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.white24), + borderSide: BorderSide(color: AppColors.onSurface24), ), focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.white), + borderSide: BorderSide(color: AppColors.onSurface), ), ), onSubmitted: (val) => Navigator.pop(ctx, val), @@ -327,7 +327,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> { child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.07), + color: AppColors.onSurface.withOpacity(0.07), borderRadius: BorderRadius.circular(10), ), child: Row( @@ -341,7 +341,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> { Text( label, style: const TextStyle( - color: Colors.white70, + color: AppColors.onSurface70, fontSize: 11, fontWeight: FontWeight.w500, ), @@ -350,7 +350,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> { Text( displayValue, style: TextStyle( - color: value.isEmpty ? Colors.white38 : Colors.white, + color: value.isEmpty ? AppColors.onSurface38 : AppColors.onSurface, fontSize: 14, fontWeight: FontWeight.w500, ), @@ -360,7 +360,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> { ], ), ), - const Icon(Icons.edit, color: Colors.white38, size: 18), + const Icon(Icons.edit, color: AppColors.onSurface38, size: 18), ], ), ), @@ -374,7 +374,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> { backgroundColor: AppColors.surface, title: Text( widget.isEditing ? 'Modifier la Playlist' : 'Ajouter une Playlist', - style: GoogleFonts.inter(color: Colors.white), + style: GoogleFonts.inter(color: AppColors.onSurface), ), content: SizedBox( width: 480, @@ -435,8 +435,8 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> { context: context, builder: (ctx) => AlertDialog( backgroundColor: AppColors.surface, - title: const Text('Confirmer', style: TextStyle(color: Colors.white)), - content: const Text('Supprimer cette playlist ?', style: TextStyle(color: Colors.white70)), + title: const Text('Confirmer', style: TextStyle(color: AppColors.onSurface)), + content: const Text('Supprimer cette playlist ?', style: TextStyle(color: AppColors.onSurface70)), actions: [ TextButton( onPressed: () => Navigator.pop(ctx, false), @@ -444,7 +444,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> { ), TextButton( onPressed: () => Navigator.pop(ctx, true), - style: TextButton.styleFrom(foregroundColor: Colors.red), + style: TextButton.styleFrom(foregroundColor: AppColors.error), child: const Text('Supprimer'), ), ], @@ -458,7 +458,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> { borderRadius: BorderRadius.circular(8), child: const Padding( padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), - child: Text('Supprimer', style: TextStyle(color: Colors.red)), + child: Text('Supprimer', style: TextStyle(color: AppColors.error)), ), ), TVFocusable( @@ -466,7 +466,7 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> { borderRadius: BorderRadius.circular(8), child: const Padding( padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), - child: Text('Annuler', style: TextStyle(color: Colors.white70)), + child: Text('Annuler', style: TextStyle(color: AppColors.onSurface70)), ), ), TVFocusable( @@ -482,14 +482,14 @@ class _PlaylistEditDialogState extends State<_PlaylistEditDialog> { padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( color: _name.isEmpty || _dns.isEmpty - ? Colors.white12 + ? AppColors.onSurface12 : AppColors.primary, borderRadius: BorderRadius.circular(8), ), child: Text( _isSaving ? '...' : 'Enregistrer', style: const TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontWeight: FontWeight.bold, ), ), diff --git a/lib/features/iptv/screens/mobile_series_detail_screen.dart b/lib/features/iptv/screens/mobile_series_detail_screen.dart index fd498a2..b999862 100644 --- a/lib/features/iptv/screens/mobile_series_detail_screen.dart +++ b/lib/features/iptv/screens/mobile_series_detail_screen.dart @@ -129,7 +129,7 @@ class _MobileSeriesDetailScreenState shape: BoxShape.circle, ), child: IconButton( - icon: const Icon(Icons.arrow_back, color: Colors.white), + icon: const Icon(Icons.arrow_back, color: AppColors.onSurface), onPressed: () => Navigator.pop(context), tooltip: 'Back', ), @@ -149,7 +149,7 @@ class _MobileSeriesDetailScreenState maxHeightDiskCache: 720, cacheManager: AppCacheManager.instance, errorWidget: (_, __, ___) => - Container(color: Colors.grey.shade900), + Container(color: AppColors.surfaceContainerLowest), ), // Gradient Overlay Container( @@ -190,7 +190,7 @@ class _MobileSeriesDetailScreenState const Icon( Icons.star, size: 16, - color: Colors.amber, + color: AppColors.ratingGold, ), const SizedBox(width: 4), Text( @@ -261,15 +261,15 @@ class _MobileSeriesDetailScreenState } }, backgroundColor: isDark - ? const Color(0xFF1C1C1E) - : Colors.grey.shade300, - selectedColor: isDark ? Colors.white : Colors.blue, + ? AppColors.surfaceContainer + : AppColors.surfaceContainerHigh, + selectedColor: isDark ? AppColors.onSurface : AppColors.primaryFill, labelStyle: TextStyle( color: isSelected - ? (isDark ? Colors.black : Colors.white) + ? (isDark ? AppColors.onPrimaryFixed : AppColors.onSurface) : (isDark - ? Colors.grey.shade400 - : Colors.grey.shade700), + ? AppColors.textSecondary + : AppColors.outlineVariant), fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, ), @@ -323,10 +323,10 @@ class _MobileSeriesDetailScreenState } // Force dark mode colors since background is hardcoded dark - const textColor = Colors.white; - final secondaryTextColor = Colors.grey.shade400; - const surfaceColor = Color(0xFF1C1C1E); - const primaryColor = Colors.white; // Or accent color if preferred + const textColor = AppColors.onSurface; + final secondaryTextColor = AppColors.textSecondary; + const surfaceColor = AppColors.surfaceContainer; + const primaryColor = AppColors.onSurface; // Or accent color if preferred return InkWell( onTap: () { @@ -356,7 +356,7 @@ class _MobileSeriesDetailScreenState Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: const BoxDecoration( - border: Border(bottom: BorderSide(color: Colors.white10)), + border: Border(bottom: BorderSide(color: AppColors.onSurface12)), ), child: Row( children: [ @@ -374,7 +374,7 @@ class _MobileSeriesDetailScreenState child: Icon( isWatched ? Icons.check : Icons.play_arrow, color: isWatched - ? Colors.black // Checkmark on white bg + ? AppColors.onPrimaryFixed // Checkmark on white bg : primaryColor, // Play icon size: 20, ), @@ -413,7 +413,7 @@ class _MobileSeriesDetailScreenState LinearProgressIndicator( value: progress, backgroundColor: Colors.transparent, - valueColor: const AlwaysStoppedAnimation(Colors.red), + valueColor: const AlwaysStoppedAnimation(AppColors.error), minHeight: 2, ), ], diff --git a/lib/features/iptv/screens/native_player_screen.dart b/lib/features/iptv/screens/native_player_screen.dart index 496367a..365967d 100644 --- a/lib/features/iptv/screens/native_player_screen.dart +++ b/lib/features/iptv/screens/native_player_screen.dart @@ -654,7 +654,7 @@ class _NativePlayerScreenState extends ConsumerState 'Reprise à ${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}', ), duration: const Duration(seconds: 2), - backgroundColor: Colors.green.shade700, + backgroundColor: AppColors.success, ), ); } else { @@ -1293,6 +1293,7 @@ class _NativePlayerScreenState extends ConsumerState // Loading Overlay — black only on FIRST load if (_isLoading && _errorMessage == null) Container( + // True black, not the warm ink: this sits over the video surface. color: Colors.black, child: _buildLoadingView(), ), @@ -1313,7 +1314,7 @@ class _NativePlayerScreenState extends ConsumerState height: 20, child: CircularProgressIndicator( strokeWidth: 2, - color: Colors.white70, + color: AppColors.onSurface70, ), ), ), @@ -1349,7 +1350,7 @@ class _NativePlayerScreenState extends ConsumerState child: IconButton( icon: const Icon( Icons.arrow_back, - color: Colors.white, + color: AppColors.onSurface, ), onPressed: () => Navigator.pop(context), ), @@ -1380,7 +1381,7 @@ class _NativePlayerScreenState extends ConsumerState Text( title, style: const TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontSize: 16, fontWeight: FontWeight.w600, ), @@ -1392,7 +1393,7 @@ class _NativePlayerScreenState extends ConsumerState Text( _currentTime, style: const TextStyle( - color: Colors.white70, + color: AppColors.onSurface70, fontSize: 12, fontWeight: FontWeight.w500, ), @@ -1485,7 +1486,7 @@ class _NativePlayerScreenState extends ConsumerState decoration: BoxDecoration( color: Colors.black.withOpacity(0.7), borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.white10), + border: Border.all(color: AppColors.onSurface12), ), child: IntrinsicHeight( child: Row( @@ -1506,7 +1507,7 @@ class _NativePlayerScreenState extends ConsumerState onFocus: _resetControlsTimer, child: const Icon( Icons.skip_previous, - color: Colors.white, + color: AppColors.onSurface, size: 36, ), ), @@ -1521,7 +1522,7 @@ class _NativePlayerScreenState extends ConsumerState _isPlaying ? Icons.pause_circle_filled : Icons.play_circle_filled, - color: Colors.white, + color: AppColors.onSurface, size: 56, ), ), @@ -1534,7 +1535,7 @@ class _NativePlayerScreenState extends ConsumerState onFocus: _resetControlsTimer, child: const Icon( Icons.skip_next, - color: Colors.white, + color: AppColors.onSurface, size: 36, ), ), @@ -1570,7 +1571,7 @@ class _NativePlayerScreenState extends ConsumerState onFocus: _resetControlsTimer, child: const Icon( Icons.grid_off, - color: Colors.white, + color: AppColors.onSurface, size: 32, ), ), @@ -1618,7 +1619,7 @@ class _NativePlayerScreenState extends ConsumerState imageUrl: widget.channels![_currentIndex].streamIcon, fit: BoxFit.contain, errorWidget: (_, __, ___) => - const Icon(Icons.tv, color: Colors.white38), + const Icon(Icons.tv, color: AppColors.onSurface38), ), ), Expanded( @@ -1628,7 +1629,7 @@ class _NativePlayerScreenState extends ConsumerState Text( title, style: const TextStyle( - color: Colors.white70, + color: AppColors.onSurface70, fontSize: 14, fontWeight: FontWeight.w500, ), @@ -1639,7 +1640,7 @@ class _NativePlayerScreenState extends ConsumerState Text( nowPlaying, style: const TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -1654,7 +1655,7 @@ class _NativePlayerScreenState extends ConsumerState Text( startTime, style: const TextStyle( - color: Colors.white54, fontSize: 11), + color: AppColors.onSurface54, fontSize: 11), ), const SizedBox(width: 6), Expanded( @@ -1663,9 +1664,9 @@ class _NativePlayerScreenState extends ConsumerState child: LinearProgressIndicator( value: epgProgress.clamp(0.0, 1.0), minHeight: 4, - backgroundColor: Colors.white24, + backgroundColor: AppColors.onSurface24, valueColor: const AlwaysStoppedAnimation( - Color(0xFF4FC3F7), + AppColors.primary, ), ), ), @@ -1674,7 +1675,7 @@ class _NativePlayerScreenState extends ConsumerState Text( endTime, style: const TextStyle( - color: Colors.white54, fontSize: 11), + color: AppColors.onSurface54, fontSize: 11), ), ], ), @@ -1714,7 +1715,7 @@ class _NativePlayerScreenState extends ConsumerState decoration: BoxDecoration( color: Colors.black.withOpacity(0.82), borderRadius: BorderRadius.circular(16), - border: Border.all(color: Colors.white12), + border: Border.all(color: AppColors.onSurface12), ), child: Row( mainAxisSize: MainAxisSize.min, @@ -1728,7 +1729,7 @@ class _NativePlayerScreenState extends ConsumerState margin: const EdgeInsets.only(right: 16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), - color: Colors.white10, + color: AppColors.onSurface12, ), child: ClipRRect( borderRadius: BorderRadius.circular(8), @@ -1736,7 +1737,7 @@ class _NativePlayerScreenState extends ConsumerState imageUrl: ch.streamIcon, fit: BoxFit.contain, errorWidget: (_, __, ___) => - const Icon(Icons.tv, color: Colors.white38, size: 32), + const Icon(Icons.tv, color: AppColors.onSurface38, size: 32), ), ), ) @@ -1747,9 +1748,9 @@ class _NativePlayerScreenState extends ConsumerState margin: const EdgeInsets.only(right: 16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), - color: Colors.white10, + color: AppColors.onSurface12, ), - child: const Icon(Icons.tv, color: Colors.white38, size: 32), + child: const Icon(Icons.tv, color: AppColors.onSurface38, size: 32), ), // Channel info @@ -1765,13 +1766,13 @@ class _NativePlayerScreenState extends ConsumerState horizontal: 6, vertical: 2), margin: const EdgeInsets.only(right: 8), decoration: BoxDecoration( - color: const Color(0xFF1565C0), + color: const AppColors.primaryFill, borderRadius: BorderRadius.circular(4), ), child: Text( 'CH $chNum', style: const TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontSize: 11, fontWeight: FontWeight.bold, ), @@ -1781,7 +1782,7 @@ class _NativePlayerScreenState extends ConsumerState child: Text( ch.name, style: const TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -1797,9 +1798,9 @@ class _NativePlayerScreenState extends ConsumerState child: SizedBox( height: 3, child: LinearProgressIndicator( - backgroundColor: Colors.white24, + backgroundColor: AppColors.onSurface24, valueColor: AlwaysStoppedAnimation( - Color(0xFF4FC3F7)), + AppColors.primary), ), ), ) @@ -1808,7 +1809,7 @@ class _NativePlayerScreenState extends ConsumerState Text( nowPlaying, style: const TextStyle( - color: Colors.white70, + color: AppColors.onSurface70, fontSize: 13, ), maxLines: 1, @@ -1820,9 +1821,9 @@ class _NativePlayerScreenState extends ConsumerState child: LinearProgressIndicator( value: epgProgress.clamp(0.0, 1.0), minHeight: 3, - backgroundColor: Colors.white24, + backgroundColor: AppColors.onSurface24, valueColor: const AlwaysStoppedAnimation( - Color(0xFF4FC3F7)), + AppColors.primary), ), ), ], @@ -1861,18 +1862,18 @@ class _NativePlayerScreenState extends ConsumerState padding: const EdgeInsets.fromLTRB(16, 12, 16, 8), decoration: const BoxDecoration( border: Border( - bottom: BorderSide(color: Colors.white12), + bottom: BorderSide(color: AppColors.onSurface12), ), ), child: Row( children: [ - const Icon(Icons.list, color: Colors.white70, size: 18), + const Icon(Icons.list, color: AppColors.onSurface70, size: 18), const SizedBox(width: 8), const Expanded( child: Text( 'Chaînes', style: TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontSize: 15, fontWeight: FontWeight.bold, ), @@ -1881,7 +1882,7 @@ class _NativePlayerScreenState extends ConsumerState GestureDetector( onTap: () => setState(() => _showChannelList = false), child: const Icon(Icons.close, - color: Colors.white54, size: 18), + color: AppColors.onSurface54, size: 18), ), ], ), @@ -1903,12 +1904,12 @@ class _NativePlayerScreenState extends ConsumerState child: Container( decoration: BoxDecoration( color: isActive - ? const Color(0xFF1565C0).withOpacity(0.6) + ? AppColors.primaryFill.withValues(alpha: 0.6) : Colors.transparent, border: isActive ? const Border( left: BorderSide( - color: Color(0xFF4FC3F7), + color: AppColors.primary, width: 3, ), ) @@ -1924,7 +1925,7 @@ class _NativePlayerScreenState extends ConsumerState height: 40, margin: const EdgeInsets.only(right: 10), decoration: BoxDecoration( - color: Colors.white10, + color: AppColors.onSurface12, borderRadius: BorderRadius.circular(6), ), child: ch.streamIcon.isNotEmpty @@ -1935,12 +1936,12 @@ class _NativePlayerScreenState extends ConsumerState fit: BoxFit.contain, errorWidget: (_, __, ___) => const Icon(Icons.tv, - color: Colors.white38, + color: AppColors.onSurface38, size: 20), ), ) : const Icon(Icons.tv, - color: Colors.white38, size: 20), + color: AppColors.onSurface38, size: 20), ), // Name + num Expanded( @@ -1952,8 +1953,8 @@ class _NativePlayerScreenState extends ConsumerState ch.name, style: TextStyle( color: isActive - ? Colors.white - : Colors.white70, + ? AppColors.onSurface + : AppColors.onSurface70, fontSize: 13, fontWeight: isActive ? FontWeight.bold @@ -1965,7 +1966,7 @@ class _NativePlayerScreenState extends ConsumerState Text( 'CH ${index + 1}', style: const TextStyle( - color: Colors.white38, + color: AppColors.onSurface38, fontSize: 11, ), ), @@ -1976,7 +1977,7 @@ class _NativePlayerScreenState extends ConsumerState if (isActive) const Icon( Icons.play_arrow, - color: Color(0xFF4FC3F7), + color: AppColors.primary, size: 18, ), ], @@ -2021,7 +2022,7 @@ class _NativePlayerScreenState extends ConsumerState child: IconButton( icon: const Icon( Icons.replay_10, - color: Colors.white, + color: AppColors.onSurface, size: 48, ), onPressed: () async { @@ -2046,7 +2047,7 @@ class _NativePlayerScreenState extends ConsumerState _isPlaying ? Icons.pause_circle_filled : Icons.play_circle_filled, - color: Colors.white, + color: AppColors.onSurface, ), onPressed: _togglePlayPause, ), @@ -2067,7 +2068,7 @@ class _NativePlayerScreenState extends ConsumerState child: IconButton( icon: const Icon( Icons.forward_10, - color: Colors.white, + color: AppColors.onSurface, size: 48, ), onPressed: () async { @@ -2103,7 +2104,7 @@ class _NativePlayerScreenState extends ConsumerState Text( _formatDuration(_position), style: const TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontSize: 14, ), ), @@ -2157,14 +2158,14 @@ class _NativePlayerScreenState extends ConsumerState _resetControlsTimer(); }, activeColor: AppColors.primary, - inactiveColor: Colors.white24, + inactiveColor: AppColors.onSurface24, ), ), ), Text( _formatDuration(_duration), style: const TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontSize: 14, ), ), @@ -2199,7 +2200,7 @@ class _NativePlayerScreenState extends ConsumerState height: 72, margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( - color: Colors.white10, + color: AppColors.onSurface12, borderRadius: BorderRadius.circular(12), ), child: ClipRRect( @@ -2208,7 +2209,7 @@ class _NativePlayerScreenState extends ConsumerState imageUrl: ch.streamIcon, fit: BoxFit.contain, errorWidget: (_, __, ___) => - const Icon(Icons.tv, color: Colors.white38, size: 40), + const Icon(Icons.tv, color: AppColors.onSurface38, size: 40), ), ), ), @@ -2217,7 +2218,7 @@ class _NativePlayerScreenState extends ConsumerState Text( ch != null ? ch.name : 'Chargement...', style: const TextStyle( - color: Colors.white70, + color: AppColors.onSurface70, fontSize: 15, fontWeight: FontWeight.w500, ), @@ -2232,18 +2233,18 @@ class _NativePlayerScreenState extends ConsumerState child: Column( mainAxisSize: MainAxisSize.min, children: [ - const Icon(Icons.error_outline, size: 64, color: Colors.red), + const Icon(Icons.error_outline, size: 64, color: AppColors.error), const SizedBox(height: 16), const Text( 'Erreur de lecture', - style: TextStyle(color: Colors.white, fontSize: 18), + style: TextStyle(color: AppColors.onSurface, fontSize: 18), ), const SizedBox(height: 8), Padding( padding: const EdgeInsets.symmetric(horizontal: 32), child: Text( _errorMessage ?? 'Une erreur inconnue est survenue', - style: const TextStyle(color: Colors.white70), + style: const TextStyle(color: AppColors.onSurface70), textAlign: TextAlign.center, ), ), @@ -2256,8 +2257,8 @@ class _NativePlayerScreenState extends ConsumerState icon: const Icon(Icons.arrow_back), label: const Text('Retour'), style: ElevatedButton.styleFrom( - backgroundColor: Colors.white, - foregroundColor: Colors.black, + backgroundColor: AppColors.onSurface, + foregroundColor: AppColors.onPrimaryFixed, ), ), const SizedBox(width: 16), @@ -2267,7 +2268,7 @@ class _NativePlayerScreenState extends ConsumerState label: const Text('Réessayer'), style: ElevatedButton.styleFrom( backgroundColor: AppColors.primary, - foregroundColor: Colors.black, + foregroundColor: AppColors.onPrimaryFixed, ), ), ], @@ -2328,7 +2329,7 @@ class _StatsOverlayWidgetState extends ConsumerState { decoration: BoxDecoration( color: Colors.black.withOpacity(0.7), borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.green.withOpacity(0.5)), + border: Border.all(color: AppColors.success.withOpacity(0.5)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -2337,7 +2338,7 @@ class _StatsOverlayWidgetState extends ConsumerState { const Text( 'STATS FOR NERDS 🤓', style: TextStyle( - color: Colors.green, + color: AppColors.success, fontWeight: FontWeight.bold, fontSize: 12, ), @@ -2345,11 +2346,11 @@ class _StatsOverlayWidgetState extends ConsumerState { const SizedBox(height: 4), Text( 'Buffer: ${_buffer.inSeconds}s', - style: const TextStyle(color: Colors.white, fontSize: 12), + style: const TextStyle(color: AppColors.onSurface, fontSize: 12), ), Text( 'Decoder: $_decoder', - style: const TextStyle(color: Colors.white, fontSize: 12), + style: const TextStyle(color: AppColors.onSurface, fontSize: 12), ), ], ), diff --git a/lib/features/iptv/widgets/mobile_live_tv_tab.dart b/lib/features/iptv/widgets/mobile_live_tv_tab.dart index ed22869..859c829 100644 --- a/lib/features/iptv/widgets/mobile_live_tv_tab.dart +++ b/lib/features/iptv/widgets/mobile_live_tv_tab.dart @@ -16,6 +16,7 @@ import 'package:xtremobile/features/iptv/screens/lite_player_screen.dart'; import 'package:flutter/services.dart'; import 'package:xtremobile/core/services/ip_service.dart'; import 'package:xtremobile/core/models/iptv_models.dart' as model; +import 'package:xtremobile/core/theme/app_colors.dart'; class MobileLiveTVTab extends ConsumerStatefulWidget { final PlaylistConfig playlist; @@ -130,14 +131,14 @@ class _MobileLiveTVTabState extends ConsumerState final shouldExit = await showDialog( context: context, builder: (context) => AlertDialog( - backgroundColor: Colors.grey[900], + backgroundColor: AppColors.surfaceContainerLowest, title: const Text( "Quitter l'application", - style: TextStyle(color: Colors.white), + style: TextStyle(color: AppColors.onSurface), ), content: const Text( "Voulez-vous vraiment quitter l'application ?", - style: TextStyle(color: Colors.white70), + style: TextStyle(color: AppColors.onSurface70), ), actions: [ TextButton( @@ -145,14 +146,14 @@ class _MobileLiveTVTabState extends ConsumerState autofocus: true, child: const Text( 'Annuler', - style: TextStyle(color: Colors.blueAccent), + style: TextStyle(color: AppColors.primary), ), ), TextButton( onPressed: () => Navigator.of(context).pop(true), child: const Text( 'Quitter', - style: TextStyle(color: Colors.redAccent), + style: TextStyle(color: AppColors.error), ), ), ], @@ -171,7 +172,7 @@ class _MobileLiveTVTabState extends ConsumerState padding: const EdgeInsets.all(16), child: Text( 'Erreur: $e', - style: const TextStyle(color: Colors.red), + style: const TextStyle(color: AppColors.error), textAlign: TextAlign.center, ), ), @@ -235,7 +236,7 @@ class _MobileLiveTVTabState extends ConsumerState // Search Bar TVFocusable( scale: 1.0, - focusColor: Colors.white, + focusColor: AppColors.onSurface, onPressed: () { setState(() => _isSearchEditing = true); WidgetsBinding.instance @@ -263,7 +264,7 @@ class _MobileLiveTVTabState extends ConsumerState child: ExcludeFocus( excluding: !_isSearchEditing, child: TextField( - cursorColor: Colors.white, + cursorColor: AppColors.onSurface, controller: _searchController, focusNode: _searchFocusNode, readOnly: !_isSearchEditing, @@ -357,7 +358,7 @@ class _MobileLiveTVTabState extends ConsumerState ? Icons.favorite : Icons.favorite_border, color: _showFavoritesOnly - ? const Color(0xFFFF453A) + ? AppColors.live : AppDecorations.textSecondary( context), ), @@ -535,7 +536,7 @@ class _ChannelListView extends ConsumerWidget { child: Center( child: Text( 'Aucune catégorie sélectionnée', - style: TextStyle(color: Colors.white70), + style: TextStyle(color: AppColors.onSurface70), ), ), ); @@ -557,7 +558,7 @@ class _ChannelListView extends ConsumerWidget { showFavoritesOnly ? 'Sélectionnez une catégorie pour voir vos favoris' : 'Sélectionnez une catégorie pour rechercher', - style: const TextStyle(color: Colors.white70), + style: const TextStyle(color: AppColors.onSurface70), textAlign: TextAlign.center, ), ), @@ -575,7 +576,7 @@ class _ChannelListView extends ConsumerWidget { padding: const EdgeInsets.all(16), child: Text( 'Erreur: $e', - style: const TextStyle(color: Colors.red), + style: const TextStyle(color: AppColors.error), textAlign: TextAlign.center, ), ), @@ -600,7 +601,7 @@ class _ChannelListView extends ConsumerWidget { child: Center( child: Text( 'Aucune chaîne trouvée', - style: TextStyle(color: Colors.white70), + style: TextStyle(color: AppColors.onSurface70), ), ), ); @@ -754,12 +755,12 @@ class _MobileChannelCardState extends ConsumerState<_MobileChannelCard> { child: Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( - color: Colors.red, + color: AppColors.error, borderRadius: BorderRadius.circular(12), ), child: const Icon( Icons.favorite, - color: Colors.white, + color: AppColors.onSurface, size: 10, ), ), @@ -779,7 +780,7 @@ class _MobileChannelCardState extends ConsumerState<_MobileChannelCard> { Text( widget.channel.name, style: const TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontWeight: FontWeight.bold, fontSize: 10, ), @@ -792,7 +793,7 @@ class _MobileChannelCardState extends ConsumerState<_MobileChannelCard> { Text( _epgTitle!, style: const TextStyle( - color: Colors.yellow, + color: AppColors.ratingGold, fontSize: 8, ), textAlign: TextAlign.center, diff --git a/lib/features/iptv/widgets/mobile_movies_tab.dart b/lib/features/iptv/widgets/mobile_movies_tab.dart index 54b92bc..48641d0 100644 --- a/lib/features/iptv/widgets/mobile_movies_tab.dart +++ b/lib/features/iptv/widgets/mobile_movies_tab.dart @@ -11,6 +11,7 @@ import 'package:xtremobile/mobile/providers/mobile_settings_providers.dart'; import 'package:xtremobile/mobile/providers/mobile_xtream_providers.dart'; import 'package:xtremobile/core/models/iptv_models.dart' as model; import 'package:xtremobile/features/iptv/screens/native_player_screen.dart'; +import 'package:xtremobile/core/theme/app_colors.dart'; class MobileMoviesTab extends ConsumerStatefulWidget { final PlaylistConfig playlist; @@ -285,14 +286,14 @@ class _MobileMoviesTabState extends ConsumerState final shouldExit = await showDialog( context: context, builder: (context) => AlertDialog( - backgroundColor: Colors.grey[900], + backgroundColor: AppColors.surfaceContainerLowest, title: const Text( "Quitter l'application", - style: TextStyle(color: Colors.white), + style: TextStyle(color: AppColors.onSurface), ), content: const Text( "Voulez-vous vraiment quitter l'application ?", - style: TextStyle(color: Colors.white70), + style: TextStyle(color: AppColors.onSurface70), ), actions: [ TextButton( @@ -300,14 +301,14 @@ class _MobileMoviesTabState extends ConsumerState autofocus: true, child: const Text( 'Annuler', - style: TextStyle(color: Colors.blueAccent), + style: TextStyle(color: AppColors.primary), ), ), TextButton( onPressed: () => Navigator.of(context).pop(true), child: const Text( 'Quitter', - style: TextStyle(color: Colors.redAccent), + style: TextStyle(color: AppColors.error), ), ), ], @@ -346,7 +347,7 @@ class _MobileMoviesTabState extends ConsumerState // Search Bar TVFocusable( scale: 1.0, - focusColor: Colors.white, + focusColor: AppColors.onSurface, onPressed: () { setState(() => _isSearchEditing = true); WidgetsBinding.instance.addPostFrameCallback((_) { @@ -367,7 +368,7 @@ class _MobileMoviesTabState extends ConsumerState child: ExcludeFocus( excluding: !_isSearchEditing, child: TextField( - cursorColor: Colors.white, + cursorColor: AppColors.onSurface, controller: _searchController, focusNode: _searchFocusNode, readOnly: !_isSearchEditing, diff --git a/lib/features/iptv/widgets/mobile_series_tab.dart b/lib/features/iptv/widgets/mobile_series_tab.dart index 292d3fb..18a0ac3 100644 --- a/lib/features/iptv/widgets/mobile_series_tab.dart +++ b/lib/features/iptv/widgets/mobile_series_tab.dart @@ -11,6 +11,7 @@ import 'package:xtremobile/mobile/providers/mobile_settings_providers.dart'; import 'package:xtremobile/mobile/providers/mobile_xtream_providers.dart'; import 'package:xtremobile/core/models/iptv_models.dart' as model; import 'package:xtremobile/features/iptv/screens/mobile_series_detail_screen.dart'; +import 'package:xtremobile/core/theme/app_colors.dart'; class MobileSeriesTab extends ConsumerStatefulWidget { final PlaylistConfig playlist; @@ -269,18 +270,18 @@ class _MobileSeriesTabState extends ConsumerState final shouldExit = await showDialog( context: context, builder: (context) => AlertDialog( - backgroundColor: Colors.grey[900], - title: const Text("Quitter l'application", style: TextStyle(color: Colors.white)), - content: const Text("Voulez-vous vraiment quitter l'application ?", style: TextStyle(color: Colors.white70)), + backgroundColor: AppColors.surfaceContainerLowest, + title: const Text("Quitter l'application", style: TextStyle(color: AppColors.onSurface)), + content: const Text("Voulez-vous vraiment quitter l'application ?", style: TextStyle(color: AppColors.onSurface70)), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), autofocus: true, - child: const Text('Annuler', style: TextStyle(color: Colors.blueAccent)), + child: const Text('Annuler', style: TextStyle(color: AppColors.primary)), ), TextButton( onPressed: () => Navigator.of(context).pop(true), - child: const Text('Quitter', style: TextStyle(color: Colors.redAccent)), + child: const Text('Quitter', style: TextStyle(color: AppColors.error)), ), ], ), @@ -316,7 +317,7 @@ class _MobileSeriesTabState extends ConsumerState // Search Bar TVFocusable( scale: 1.0, - focusColor: Colors.white, + focusColor: AppColors.onSurface, onPressed: () { setState(() => _isSearchEditing = true); WidgetsBinding.instance.addPostFrameCallback((_) { @@ -337,7 +338,7 @@ class _MobileSeriesTabState extends ConsumerState child: ExcludeFocus( excluding: !_isSearchEditing, child: TextField( - cursorColor: Colors.white, + cursorColor: AppColors.onSurface, controller: _searchController, focusNode: _searchFocusNode, readOnly: !_isSearchEditing, diff --git a/lib/features/iptv/widgets/mobile_settings_tab.dart b/lib/features/iptv/widgets/mobile_settings_tab.dart index 9f1a672..9a19695 100644 --- a/lib/features/iptv/widgets/mobile_settings_tab.dart +++ b/lib/features/iptv/widgets/mobile_settings_tab.dart @@ -8,6 +8,7 @@ import 'package:xtremobile/core/theme/app_decorations.dart'; import 'package:xtremobile/core/theme/app_theme.dart'; import 'package:xtremobile/core/providers/theme_provider.dart'; import 'package:xtremobile/features/iptv/screens/mobile_playlist_selection_screen.dart'; +import 'package:xtremobile/core/theme/app_colors.dart'; /// Simplified mobile settings tab - optimized for TV remote control class MobileSettingsTab extends ConsumerStatefulWidget { @@ -105,7 +106,7 @@ class _MobileSettingsTabState extends ConsumerState { ), ), Text( - 'Version 1.5.1', + 'Version 1.6.1', style: GoogleFonts.inter( fontSize: 13, color: AppDecorations.textSecondary(context), @@ -327,7 +328,7 @@ class _MobileSettingsTabState extends ConsumerState { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Cache actualisé ! Relancez l\'app pour recharger.'), - backgroundColor: Colors.green, + backgroundColor: AppColors.success, duration: Duration(seconds: 3), ), ); @@ -335,7 +336,7 @@ class _MobileSettingsTabState extends ConsumerState { } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Erreur: $e'), backgroundColor: Colors.red), + SnackBar(content: Text('Erreur: $e'), backgroundColor: AppColors.error), ); } } finally { @@ -415,7 +416,7 @@ class _MobileSettingsTabState extends ConsumerState { icon, size: 16, color: selected - ? Colors.white + ? AppColors.onSurface : AppDecorations.textSecondary(context), ), const SizedBox(height: 3), @@ -427,7 +428,7 @@ class _MobileSettingsTabState extends ConsumerState { ? FontWeight.w700 : FontWeight.w500, color: selected - ? Colors.white + ? AppColors.onSurface : AppDecorations.textSecondary(context), ), ), diff --git a/lib/mobile/widgets/mobile_category_card.dart b/lib/mobile/widgets/mobile_category_card.dart index 11b9bcc..49c2a80 100644 --- a/lib/mobile/widgets/mobile_category_card.dart +++ b/lib/mobile/widgets/mobile_category_card.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:xtremobile/core/theme/app_decorations.dart'; import 'package:xtremobile/mobile/widgets/tv_focusable.dart'; +import 'package:xtremobile/core/theme/app_colors.dart'; class MobileCategoryCard extends StatelessWidget { final String title; @@ -13,7 +14,7 @@ class MobileCategoryCard extends StatelessWidget { required this.title, required this.onTap, this.icon = Icons.folder_rounded, - this.iconColor = const Color(0xFF0A84FF), + this.iconColor = AppColors.primary, }); @override diff --git a/lib/mobile/widgets/mobile_poster_card.dart b/lib/mobile/widgets/mobile_poster_card.dart index 4a12b12..6dd1131 100644 --- a/lib/mobile/widgets/mobile_poster_card.dart +++ b/lib/mobile/widgets/mobile_poster_card.dart @@ -3,6 +3,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:xtremobile/core/theme/app_decorations.dart'; import 'package:xtremobile/mobile/widgets/tv_focusable.dart'; import 'package:xtremobile/core/utils/image_cache_config.dart'; +import 'package:xtremobile/core/theme/app_colors.dart'; class MobilePosterCard extends StatelessWidget { final String title; @@ -134,12 +135,12 @@ class MobilePosterCard extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, children: [ - const Icon(Icons.star, color: Colors.amber, size: 10), + const Icon(Icons.star, color: AppColors.ratingGold, size: 10), const SizedBox(width: 2), Text( rating!, style: const TextStyle( - color: Colors.white, + color: AppColors.onSurface, fontSize: 10, fontWeight: FontWeight.bold, ), @@ -157,13 +158,13 @@ class MobilePosterCard extends StatelessWidget { child: Container( padding: const EdgeInsets.all(4), decoration: const BoxDecoration( - color: Color(0xFF30D158), + color: AppColors.success, shape: BoxShape.circle, ), child: const Icon( Icons.check, size: 10, - color: Colors.white, + color: AppColors.onSurface, ), ), ); diff --git a/lib/mobile/widgets/mobile_scaffold.dart b/lib/mobile/widgets/mobile_scaffold.dart index d905510..e1f4703 100644 --- a/lib/mobile/widgets/mobile_scaffold.dart +++ b/lib/mobile/widgets/mobile_scaffold.dart @@ -4,6 +4,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import '../../core/theme/app_decorations.dart'; +import 'package:xtremobile/core/theme/app_colors.dart'; class MobileScaffold extends ConsumerStatefulWidget { final Widget child; @@ -71,7 +72,7 @@ class _MobileScaffoldState extends ConsumerState { fit: BoxFit.contain, errorBuilder: (_, __, ___) => const Icon( Icons.play_circle_filled, - color: Colors.white, + color: AppColors.onSurface, size: 40, ), ), @@ -201,12 +202,12 @@ class _AppleTVNavItemState extends State<_AppleTVNavItem> { @override Widget build(BuildContext context) { - const Color selectedColor = Color(0xFF0A84FF); + const Color selectedColor = AppColors.primaryFill; final Color unselectedColor = AppDecorations.textSecondary(context); final Color textColor = - widget.isSelected ? Colors.white : unselectedColor; + widget.isSelected ? AppColors.onSurface : unselectedColor; final Color iconColor = - widget.isSelected ? Colors.white : unselectedColor; + widget.isSelected ? AppColors.onSurface : unselectedColor; final FontWeight fontWeight = widget.isSelected ? FontWeight.w700 : FontWeight.w500; diff --git a/lib/mobile/widgets/tv_focusable.dart b/lib/mobile/widgets/tv_focusable.dart index a745f93..964788b 100644 --- a/lib/mobile/widgets/tv_focusable.dart +++ b/lib/mobile/widgets/tv_focusable.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:xtremobile/core/theme/app_colors.dart'; class TVFocusable extends StatefulWidget { final Widget child; @@ -25,7 +26,7 @@ class TVFocusable extends StatefulWidget { this.autofocus = false, this.scale = 1.05, // Apple TV subtle lift this.borderWidth = 2.0, - this.focusColor = Colors.white, + this.focusColor = AppColors.onSurface, this.borderRadius, this.longPressDuration = const Duration(seconds: 3), }); @@ -162,7 +163,7 @@ class _TVFocusableState extends State { offset: const Offset(0, 6), ), const BoxShadow( - color: Color(0x40FFFFFF), // White glow + color: Color(0x59D9541F), // Ember glow blurRadius: 12, spreadRadius: 0, ), diff --git a/pubspec.yaml b/pubspec.yaml index 549f8de..73b8730 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: xtremobile description: High-performance IPTV Android Application with Xtream Codes API publish_to: 'none' -version: 1.6.0+12 +version: 1.6.1+13 environment: sdk: '>=3.0.0 <4.0.0' diff --git a/task.md b/task.md index 566d5c9..90a5d59 100644 --- a/task.md +++ b/task.md @@ -25,6 +25,21 @@ - [x] `mobile_theme.dart` : dérive désormais de `AppTheme` (échelle typo mobile) au lieu de dupliquer 390 lignes - [x] `app_decorations.dart` : hexs Apple codés en dur remplacés par la palette +- [x] **Passe 2 (v1.6.1)** — le thème ne suffisait pas : du bleu restait codé en + dur dans 19 fichiers d'écran/widget, hors palette. Balayage complet : + - `0xFF0A84FF` (bleu Apple) dans la **pilule de navigation sélectionnée** + (`mobile_scaffold`), les icônes de catégorie et le bouton « ajouter » + - `0xFF4FC3F7` / `0xFF1565C0` (bleus) dans les overlays du lecteur + - `Colors.blueAccent` / `Colors.blue` dans les boîtes de dialogue + - gris Apple `1C1C1E` / `2C2C2E` / `3A3A3C` / `8E8E93` → charbons chauds + - `Colors.white*` (128 occurrences) → paliers crème `onSurfaceNN` + - `Colors.red/green/amber/yellow/grey*` → `error` / `success` / + `ratingGold` / `outlineVariant` + - noir pur sur remplissage clair → encre chaude `onPrimaryFixed` + - halo de focus blanc → halo ember + - Conservés en noir vrai : fonds de surface vidéo et voiles (`scrims`) + - Vérification : plus **aucune** couleur Material/Apple codée en dur hors + de `lib/core/theme/` ## 3. Lecture — arrêt en arrière-plan et tenue dans la durée