diff --git a/lib/mobile/features/iptv/screens/mobile_playlist_screen.dart b/lib/mobile/features/iptv/screens/mobile_playlist_screen.dart index bfea669..0583a4e 100644 --- a/lib/mobile/features/iptv/screens/mobile_playlist_screen.dart +++ b/lib/mobile/features/iptv/screens/mobile_playlist_screen.dart @@ -134,6 +134,7 @@ class _MobilePlaylistScreenState extends ConsumerState { onSubmitted: () => FocusScope.of(context).requestFocus(dnsFocus), focusNode: nameFocus, + nextFocus: dnsFocus, ), const SizedBox(height: 16), @@ -147,6 +148,8 @@ class _MobilePlaylistScreenState extends ConsumerState { onSubmitted: () => FocusScope.of(context).requestFocus(usernameFocus), focusNode: dnsFocus, + nextFocus: usernameFocus, + prevFocus: nameFocus, ), const SizedBox(height: 16), @@ -159,6 +162,8 @@ class _MobilePlaylistScreenState extends ConsumerState { onSubmitted: () => FocusScope.of(context).requestFocus(passwordFocus), focusNode: usernameFocus, + nextFocus: passwordFocus, + prevFocus: dnsFocus, ), const SizedBox(height: 16), @@ -172,6 +177,8 @@ class _MobilePlaylistScreenState extends ConsumerState { onSubmitted: () => FocusScope.of(context).requestFocus(buttonFocus), focusNode: passwordFocus, + nextFocus: buttonFocus, + prevFocus: usernameFocus, ), const SizedBox(height: 32), @@ -262,6 +269,8 @@ class _MobilePlaylistScreenState extends ConsumerState { TextInputAction? textAction, VoidCallback? onSubmitted, FocusNode? focusNode, // This is now the "navigation" focus + FocusNode? nextFocus, + FocusNode? prevFocus, }) { // Create a dedicated internal focus node for the actual TextField // We don't expose this, allowing us to control when the keyboard opens @@ -280,6 +289,8 @@ class _MobilePlaylistScreenState extends ConsumerState { textAction: textAction, onSubmitted: onSubmitted, navigationFocus: focusNode, + nextFocus: nextFocus, + prevFocus: prevFocus, ); } @@ -599,6 +610,8 @@ class _TVTextField extends StatefulWidget { final TextInputAction? textAction; final VoidCallback? onSubmitted; final FocusNode? navigationFocus; + final FocusNode? nextFocus; + final FocusNode? prevFocus; const _TVTextField({ required this.controller, @@ -610,6 +623,8 @@ class _TVTextField extends StatefulWidget { this.textAction, this.onSubmitted, this.navigationFocus, + this.nextFocus, + this.prevFocus, }); @override @@ -667,6 +682,14 @@ class _TVTextFieldState extends State<_TVTextField> { _activateInput(); return KeyEventResult.handled; } + if (key == LogicalKeyboardKey.arrowDown && widget.nextFocus != null) { + widget.nextFocus!.requestFocus(); + return KeyEventResult.handled; + } + if (key == LogicalKeyboardKey.arrowUp && widget.prevFocus != null) { + widget.prevFocus!.requestFocus(); + return KeyEventResult.handled; + } } return KeyEventResult.ignored; }, diff --git a/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart b/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart index b8cdeac..22c7776 100644 --- a/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart +++ b/lib/mobile/features/iptv/widgets/mobile_settings_tab.dart @@ -102,7 +102,7 @@ class _MobileSettingsTabState extends ConsumerState { ), ), Text( - 'Version 1.5.0', + 'Version 1.5.1', style: GoogleFonts.inter( fontSize: 13, color: AppColors.textSecondary, @@ -173,6 +173,7 @@ class _MobileSettingsTabState extends ConsumerState { label: 'TV en Direct', hint: 'Ex: FR, HD, SPORT', icon: Icons.live_tv, + currentKeywords: settings.liveTvKeywords, controller: _liveTvController, onChanged: (val) { ref @@ -185,6 +186,7 @@ class _MobileSettingsTabState extends ConsumerState { label: 'Films', hint: 'Ex: FR, VF, 4K', icon: Icons.movie, + currentKeywords: settings.moviesKeywords, controller: _moviesController, onChanged: (val) { ref @@ -197,6 +199,7 @@ class _MobileSettingsTabState extends ConsumerState { label: 'Séries', hint: 'Ex: FR, VF', icon: Icons.tv, + currentKeywords: settings.seriesKeywords, controller: _seriesController, onChanged: (val) { ref @@ -393,9 +396,15 @@ class _MobileSettingsTabState extends ConsumerState { required String label, required String hint, required IconData icon, + required List currentKeywords, required TextEditingController controller, required ValueChanged onChanged, }) { + final hasFilters = currentKeywords.isNotEmpty; + final subtitle = hasFilters + ? currentKeywords.join(', ') + : 'Aucun filtre (Tout afficher)'; + return Padding( padding: const EdgeInsets.only(bottom: 8), child: TVFocusable( @@ -427,12 +436,14 @@ class _MobileSettingsTabState extends ConsumerState { ), ), Text( - controller.text.isEmpty ? hint : controller.text, + subtitle, style: TextStyle( - color: controller.text.isEmpty - ? AppColors.textSecondary - : AppColors.textPrimary, + color: hasFilters + ? AppColors.primary + : AppColors.textSecondary, fontSize: 12, + fontWeight: + hasFilters ? FontWeight.w600 : FontWeight.normal, ), maxLines: 1, overflow: TextOverflow.ellipsis, diff --git a/pubspec.yaml b/pubspec.yaml index b86bc1b..677d3fc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: xtremflow description: High-performance IPTV Web Application with Xtream Codes API publish_to: 'none' -version: 1.5.0+10 +version: 1.5.1+11 environment: sdk: '>=3.0.0 <4.0.0'