fix: library initial focus

This commit is contained in:
edde746
2026-01-24 03:26:24 +01:00
parent ec57cd436e
commit 99f3e78a30
+51 -51
View File
@@ -170,7 +170,8 @@ class _LibrariesScreenState extends State<LibrariesScreen>
setState(() {});
}
/// Focus the first item in the currently active tab
/// Focus the first item in the currently active tab.
/// Used for initial load and tab switching - focuses the grid content directly.
void _focusCurrentTab() {
// Don't focus during tab animations - wait for animation to complete
// This prevents race conditions during focus restoration
@@ -186,37 +187,12 @@ class _LibrariesScreenState extends State<LibrariesScreen>
});
}
// Scroll outer view to top to ensure tab content (including chips bar) is visible
if (_outerScrollController.hasClients && _outerScrollController.offset > 0) {
_outerScrollController.jumpTo(0);
}
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
State? tabState;
switch (_tabController.index) {
case 0:
tabState = _recommendedTabKey.currentState;
break;
case 1:
tabState = _browseTabKey.currentState;
break;
case 2:
tabState = _collectionsTabKey.currentState;
break;
case 3:
tabState = _playlistsTabKey.currentState;
break;
}
final tabState = _getTabState(_tabController.index);
if (tabState != null) {
// Browse tab has a chips bar - focus that first so DOWN navigates to grid
if (_tabController.index == 1) {
(tabState as dynamic).focusChipsBar();
} else {
(tabState as dynamic).focusFirstItem();
}
(tabState as dynamic).focusFirstItem();
} else {
// State not available yet, retry after another frame
WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -229,34 +205,59 @@ class _LibrariesScreenState extends State<LibrariesScreen>
/// Focus without additional frame delay (used for retry)
void _focusCurrentTabImmediate() {
final tabState = _getTabState(_tabController.index);
if (tabState != null) {
(tabState as dynamic).focusFirstItem();
}
}
/// Focus tab content when navigating DOWN from the tab bar.
/// For browse tab, this focuses the chips bar first so DOWN navigates to grid.
/// For other tabs, focuses the first item directly.
void _focusCurrentTabFromTabBar() {
if (_tabController.indexIsChanging) {
return;
}
if (_suppressAutoFocus) {
setState(() {
_suppressAutoFocus = false;
});
}
// Scroll outer view to top to ensure tab content (including chips bar) is visible
if (_outerScrollController.hasClients && _outerScrollController.offset > 0) {
_outerScrollController.jumpTo(0);
}
State? tabState;
switch (_tabController.index) {
case 0:
tabState = _recommendedTabKey.currentState;
break;
case 1:
tabState = _browseTabKey.currentState;
break;
case 2:
tabState = _collectionsTabKey.currentState;
break;
case 3:
tabState = _playlistsTabKey.currentState;
break;
}
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
if (tabState != null) {
// Browse tab has a chips bar - focus that first so DOWN navigates to grid
if (_tabController.index == 1) {
(tabState as dynamic).focusChipsBar();
} else {
(tabState as dynamic).focusFirstItem();
final tabState = _getTabState(_tabController.index);
if (tabState != null) {
// Browse tab has a chips bar - focus that first so DOWN navigates to grid
if (_tabController.index == 1) {
(tabState as dynamic).focusChipsBar();
} else {
(tabState as dynamic).focusFirstItem();
}
}
});
}
/// Get the state for a tab by index
State? _getTabState(int index) {
switch (index) {
case 0:
return _recommendedTabKey.currentState;
case 1:
return _browseTabKey.currentState;
case 2:
return _collectionsTabKey.currentState;
case 3:
return _playlistsTabKey.currentState;
default:
return null;
}
}
@@ -1003,7 +1004,7 @@ class _LibrariesScreenState extends State<LibrariesScreen>
_getTabChipFocusNode(newIndex).requestFocus();
}
: null,
onNavigateDown: _focusCurrentTab,
onNavigateDown: _focusCurrentTabFromTabBar,
onBack: _onTabBarBack,
);
}
@@ -1095,7 +1096,6 @@ class _LibrariesScreenState extends State<LibrariesScreen>
slivers: [
DesktopSliverAppBar(
title: _buildAppBarTitle(visibleLibraries),
floating: true,
pinned: true,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
surfaceTintColor: Colors.transparent,