fix: library initial focus
This commit is contained in:
@@ -170,7 +170,8 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
|||||||
setState(() {});
|
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() {
|
void _focusCurrentTab() {
|
||||||
// Don't focus during tab animations - wait for animation to complete
|
// Don't focus during tab animations - wait for animation to complete
|
||||||
// This prevents race conditions during focus restoration
|
// 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((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
||||||
State? tabState;
|
final tabState = _getTabState(_tabController.index);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tabState != null) {
|
if (tabState != null) {
|
||||||
// Browse tab has a chips bar - focus that first so DOWN navigates to grid
|
(tabState as dynamic).focusFirstItem();
|
||||||
if (_tabController.index == 1) {
|
|
||||||
(tabState as dynamic).focusChipsBar();
|
|
||||||
} else {
|
|
||||||
(tabState as dynamic).focusFirstItem();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// State not available yet, retry after another frame
|
// State not available yet, retry after another frame
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
@@ -229,34 +205,59 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
|||||||
|
|
||||||
/// Focus without additional frame delay (used for retry)
|
/// Focus without additional frame delay (used for retry)
|
||||||
void _focusCurrentTabImmediate() {
|
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
|
// Scroll outer view to top to ensure tab content (including chips bar) is visible
|
||||||
if (_outerScrollController.hasClients && _outerScrollController.offset > 0) {
|
if (_outerScrollController.hasClients && _outerScrollController.offset > 0) {
|
||||||
_outerScrollController.jumpTo(0);
|
_outerScrollController.jumpTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
State? tabState;
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
switch (_tabController.index) {
|
if (!mounted) return;
|
||||||
case 0:
|
|
||||||
tabState = _recommendedTabKey.currentState;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
tabState = _browseTabKey.currentState;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
tabState = _collectionsTabKey.currentState;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
tabState = _playlistsTabKey.currentState;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tabState != null) {
|
final tabState = _getTabState(_tabController.index);
|
||||||
// Browse tab has a chips bar - focus that first so DOWN navigates to grid
|
if (tabState != null) {
|
||||||
if (_tabController.index == 1) {
|
// Browse tab has a chips bar - focus that first so DOWN navigates to grid
|
||||||
(tabState as dynamic).focusChipsBar();
|
if (_tabController.index == 1) {
|
||||||
} else {
|
(tabState as dynamic).focusChipsBar();
|
||||||
(tabState as dynamic).focusFirstItem();
|
} 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();
|
_getTabChipFocusNode(newIndex).requestFocus();
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
onNavigateDown: _focusCurrentTab,
|
onNavigateDown: _focusCurrentTabFromTabBar,
|
||||||
onBack: _onTabBarBack,
|
onBack: _onTabBarBack,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1095,7 +1096,6 @@ class _LibrariesScreenState extends State<LibrariesScreen>
|
|||||||
slivers: [
|
slivers: [
|
||||||
DesktopSliverAppBar(
|
DesktopSliverAppBar(
|
||||||
title: _buildAppBarTitle(visibleLibraries),
|
title: _buildAppBarTitle(visibleLibraries),
|
||||||
floating: true,
|
|
||||||
pinned: true,
|
pinned: true,
|
||||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
surfaceTintColor: Colors.transparent,
|
surfaceTintColor: Colors.transparent,
|
||||||
|
|||||||
Reference in New Issue
Block a user