@@ -88,12 +88,17 @@ mixin TabNavigationMixin<T extends StatefulWidget> on State<T>, 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<T extends StatefulWidget> on State<T>, TickerProviderSt
|
||||
});
|
||||
getTabChipFocusNode(newIndex).requestFocus();
|
||||
}
|
||||
: onNavigateRightFromLast,
|
||||
: onNavigateToActions,
|
||||
onNavigateDown: onNavigateDown,
|
||||
onNavigateUp: onNavigateToActions,
|
||||
onBack: onTabBarBack,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<DownloadsScreen>
|
||||
}
|
||||
|
||||
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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -923,7 +923,7 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
i,
|
||||
onSelectWhenActive: _focusCurrentTab,
|
||||
onNavigateDown: _focusCurrentTabFromTabBar,
|
||||
onNavigateRightFromLast: () => _actionBarKey.currentState?.requestFocusOnFirst(),
|
||||
onNavigateToActions: () => _actionBarKey.currentState?.requestFocusOnFirst(),
|
||||
),
|
||||
],
|
||||
],
|
||||
@@ -1181,7 +1181,7 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
||||
i,
|
||||
onSelectWhenActive: _focusCurrentTab,
|
||||
onNavigateDown: _focusCurrentTabFromTabBar,
|
||||
onNavigateRightFromLast: () => _actionBarKey.currentState?.requestFocusOnFirst(),
|
||||
onNavigateToActions: () => _actionBarKey.currentState?.requestFocusOnFirst(),
|
||||
),
|
||||
],
|
||||
],
|
||||
|
||||
@@ -535,7 +535,7 @@ class _LiveTvScreenState extends State<LiveTvScreen>
|
||||
i,
|
||||
onSelectWhenActive: _focusCurrentTab,
|
||||
onNavigateDown: _focusCurrentTab,
|
||||
onNavigateRightFromLast: () => _actionBarKey.currentState?.requestFocusOnFirst(),
|
||||
onNavigateToActions: () => _actionBarKey.currentState?.requestFocusOnFirst(),
|
||||
),
|
||||
],
|
||||
];
|
||||
|
||||
@@ -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<FocusableTabChip> with FocusableChipS
|
||||
onNavigateLeft: widget.onNavigateLeft,
|
||||
onNavigateRight: widget.onNavigateRight,
|
||||
onNavigateDown: widget.onNavigateDown,
|
||||
onNavigateUp: widget.onNavigateUp,
|
||||
onBack: widget.onBack,
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user