fix(tv): dismiss on-screen keyboard on companion-remote search submit

close #1514

A query submitted from the companion remote now behaves like a submit
instead of focus-to-type: TvKeyboardController closes an already-open
OSK and lands focus on the input without reopening it, then the shared
handleSearchSubmit path runs the search and focuses the first result.
Also guard DebouncedMediaSearch against selection-only controller
notifications re-arming the debounce into a duplicate fetch.

Co-authored-by: l3gitpanda <12003346+l3gitpanda@users.noreply.github.com>
This commit is contained in:
edde746
2026-07-10 08:48:38 +02:00
co-authored by l3gitpanda
parent 1261852514
commit b46107cb58
7 changed files with 248 additions and 36 deletions
+16 -7
View File
@@ -810,11 +810,15 @@ class _MainScreenState extends State<MainScreen>
receiver.onTabSettings = () => _selectTab(NavigationTabId.settings);
receiver.onHome = () => _selectTab(NavigationTabId.discover);
receiver.onSearchAction = (query) {
_selectTab(NavigationTabId.search);
if (query != null && query.isNotEmpty) {
final trimmed = query?.trim() ?? '';
final hasQuery = trimmed.isNotEmpty;
// With a query, don't focus the input (which would auto-open the TV
// keyboard); submitSearchQuery runs the search and focuses results.
_selectTab(NavigationTabId.search, focusSearchInput: !hasQuery);
if (hasQuery) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (_searchKey.currentState case final SearchInputFocusable searchable) {
searchable.setSearchQuery(query);
searchable.submitSearchQuery(trimmed);
}
});
}
@@ -1423,7 +1427,7 @@ class _MainScreenState extends State<MainScreen>
}
}
void _selectTab(NavigationTabId tab) {
void _selectTab(NavigationTabId tab, {bool focusSearchInput = true}) {
// Guard: ignore if tab isn't available in current mode
if (!_getVisibleTabs(_isOffline).any((t) => t.id == tab)) return;
@@ -1454,7 +1458,10 @@ class _MainScreenState extends State<MainScreen>
// Back-to-home keeps the sidebar focused (chain: content → sidebar →
// home → exit); stealing focus here left _isSidebarFocused stuck true
// while real focus sat on a content card (#1411).
if (!_isSidebarFocused) {
// A companion-remote search (focusSearchInput: false) must NOT focus the
// search input, since focusing it auto-opens the on-screen keyboard; the
// query submit focuses results instead.
if (!_isSidebarFocused && (tab != NavigationTabId.search || focusSearchInput)) {
if (newState case final FocusableTab focusable) {
focusable.focusActiveTabIfReady();
}
@@ -1466,8 +1473,10 @@ class _MainScreenState extends State<MainScreen>
_onDiscoverBecameVisible();
}
// Focus search input after rebuild so IndexedStack has made it visible
if (tab == NavigationTabId.search) {
// Focus search input after rebuild so IndexedStack has made it visible.
// Skipped for a companion-remote search (focusSearchInput: false), whose
// submit runs the search and focuses results without opening the keyboard.
if (tab == NavigationTabId.search && focusSearchInput) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (_searchKey.currentState case final SearchInputFocusable searchable) {
searchable.focusSearchInput();