diff --git a/lib/mixins/tab_navigation_mixin.dart b/lib/mixins/tab_navigation_mixin.dart index 7288c465..d91063fe 100644 --- a/lib/mixins/tab_navigation_mixin.dart +++ b/lib/mixins/tab_navigation_mixin.dart @@ -88,12 +88,17 @@ mixin TabNavigationMixin on State, TickerProviderSt } /// Shared tab chip builder — eliminates duplication between screens. + /// + /// [onNavigateToActions] moves focus into the app bar's right-aligned + /// [FocusableActionBar]. It fires both on RIGHT from the last tab and on UP + /// from any tab, so every screen with that layout gets a consistent remote + /// path to its app bar actions. Widget buildTabChip( String label, int index, { required VoidCallback onSelectWhenActive, required VoidCallback onNavigateDown, - VoidCallback? onNavigateRightFromLast, + VoidCallback? onNavigateToActions, }) { final isSelected = tabController.index == index; return FocusableTabChip( @@ -128,8 +133,9 @@ mixin TabNavigationMixin on State, TickerProviderSt }); getTabChipFocusNode(newIndex).requestFocus(); } - : onNavigateRightFromLast, + : onNavigateToActions, onNavigateDown: onNavigateDown, + onNavigateUp: onNavigateToActions, onBack: onTabBarBack, ); } diff --git a/lib/screens/downloads/downloads_screen.dart b/lib/screens/downloads/downloads_screen.dart index 9685084f..dc262bc0 100644 --- a/lib/screens/downloads/downloads_screen.dart +++ b/lib/screens/downloads/downloads_screen.dart @@ -14,7 +14,6 @@ import '../../mixins/refreshable.dart'; import '../../utils/grid_size_calculator.dart'; import '../../utils/platform_detector.dart'; import '../../widgets/desktop_app_bar.dart'; -import '../../widgets/focusable_tab_chip.dart'; import '../../widgets/focusable_media_card.dart'; import '../../widgets/media_grid_delegate.dart'; import '../../widgets/download_tree_view.dart'; @@ -87,45 +86,12 @@ class DownloadsScreenState extends State } Widget _buildTabChip(String label, int index) { - final isSelected = tabController.index == index; - - return FocusableTabChip( - label: label, - isSelected: isSelected, - focusNode: getTabChipFocusNode(index), - onSelect: () { - if (isSelected) { - // Already selected - navigate to tab content - _focusCurrentTab(); - } else { - // Switch to this tab - setState(() { - tabController.index = index; - }); - } - }, - onNavigateLeft: index > 0 - ? () { - final newIndex = index - 1; - setState(() { - suppressAutoFocus = true; - tabController.index = newIndex; - }); - getTabChipFocusNode(newIndex).requestFocus(); - } - : onTabBarBack, - onNavigateRight: index < tabCount - 1 - ? () { - final newIndex = index + 1; - setState(() { - suppressAutoFocus = true; - tabController.index = newIndex; - }); - getTabChipFocusNode(newIndex).requestFocus(); - } - : () => _actionBarKey.currentState?.requestFocusOnFirst(), + return buildTabChip( + label, + index, + onSelectWhenActive: _focusCurrentTab, onNavigateDown: _focusCurrentTab, - onBack: onTabBarBack, + onNavigateToActions: () => _actionBarKey.currentState?.requestFocusOnFirst(), ); } diff --git a/lib/screens/libraries/libraries_screen.dart b/lib/screens/libraries/libraries_screen.dart index ca78e870..dcd44378 100644 --- a/lib/screens/libraries/libraries_screen.dart +++ b/lib/screens/libraries/libraries_screen.dart @@ -923,7 +923,7 @@ class _LibrariesScreenState extends State i, onSelectWhenActive: _focusCurrentTab, onNavigateDown: _focusCurrentTabFromTabBar, - onNavigateRightFromLast: () => _actionBarKey.currentState?.requestFocusOnFirst(), + onNavigateToActions: () => _actionBarKey.currentState?.requestFocusOnFirst(), ), ], ], @@ -1181,7 +1181,7 @@ class _LibrariesScreenState extends State i, onSelectWhenActive: _focusCurrentTab, onNavigateDown: _focusCurrentTabFromTabBar, - onNavigateRightFromLast: () => _actionBarKey.currentState?.requestFocusOnFirst(), + onNavigateToActions: () => _actionBarKey.currentState?.requestFocusOnFirst(), ), ], ], diff --git a/lib/screens/livetv/live_tv_screen.dart b/lib/screens/livetv/live_tv_screen.dart index 5ee4a151..940ce97b 100644 --- a/lib/screens/livetv/live_tv_screen.dart +++ b/lib/screens/livetv/live_tv_screen.dart @@ -535,7 +535,7 @@ class _LiveTvScreenState extends State i, onSelectWhenActive: _focusCurrentTab, onNavigateDown: _focusCurrentTab, - onNavigateRightFromLast: () => _actionBarKey.currentState?.requestFocusOnFirst(), + onNavigateToActions: () => _actionBarKey.currentState?.requestFocusOnFirst(), ), ], ]; diff --git a/lib/widgets/focusable_tab_chip.dart b/lib/widgets/focusable_tab_chip.dart index f18d4a08..5419bf7a 100644 --- a/lib/widgets/focusable_tab_chip.dart +++ b/lib/widgets/focusable_tab_chip.dart @@ -31,6 +31,9 @@ class FocusableTabChip extends StatefulWidget { /// Called when the user presses DOWN from this chip. final VoidCallback? onNavigateDown; + /// Called when the user presses UP from this chip. + final VoidCallback? onNavigateUp; + /// Called when the user presses BACK from this chip. final VoidCallback? onBack; @@ -50,6 +53,7 @@ class FocusableTabChip extends StatefulWidget { this.onNavigateLeft, this.onNavigateRight, this.onNavigateDown, + this.onNavigateUp, this.onBack, this.onLongPress, this.topImage, @@ -94,6 +98,7 @@ class _FocusableTabChipState extends State with FocusableChipS onNavigateLeft: widget.onNavigateLeft, onNavigateRight: widget.onNavigateRight, onNavigateDown: widget.onNavigateDown, + onNavigateUp: widget.onNavigateUp, onBack: widget.onBack, ), );