From b73c3d3bc062411b277893b2efd09f0c8b9395c7 Mon Sep 17 00:00:00 2001 From: Kaede Akino Date: Sat, 29 Aug 2026 09:00:26 +0800 Subject: [PATCH] Focus Welcome search with Command-F --- Termind/Features/Workspaces/WindowModel.swift | 15 +++++++++++- .../Workspaces/WorkspaceContentView.swift | 3 +++ TermindTests/WindowToolbarFindTests.swift | 24 ++++++++++++++++--- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Termind/Features/Workspaces/WindowModel.swift b/Termind/Features/Workspaces/WindowModel.swift index 293b76b2..c2c35eb8 100644 --- a/Termind/Features/Workspaces/WindowModel.swift +++ b/Termind/Features/Workspaces/WindowModel.swift @@ -239,6 +239,10 @@ final class WindowModel { /// doing nothing. private(set) var findFocusRequest: UInt64 = 0 + /// Bumped by ⌘F while Welcome is in front. Welcome owns a large search + /// field in its content instead of borrowing the titlebar Find field. + private(set) var welcomeSearchFocusRequest: UInt64 = 0 + /// True while the titlebar Find field owns the keyboard. /// /// The field is outside every pane, but what it filters is inside one — so @@ -284,7 +288,12 @@ final class WindowModel { } } - var canFindInMainContent: Bool { findKind != nil } + private var hasWelcomeSearch: Bool { + guard case .vault = selectedDestination else { return false } + return vaultDestination == .welcome + } + + var canFindInMainContent: Bool { hasWelcomeSearch || findKind != nil } /// ⌘F. Focuses the titlebar field, and for a terminal also starts Ghostty's /// search again on a query retained from last time. @@ -295,6 +304,10 @@ final class WindowModel { /// field and the rebuild it caused takes the caret straight back, which is /// how the Find menu item came to be clickable and yet do nothing. func focusToolbarFind() { + if hasWelcomeSearch { + welcomeSearchFocusRequest &+= 1 + return + } guard findKind != nil else { return } isToolbarFindFocused = true if findKind == .terminal { focusedSSHSession?.presentFind() } diff --git a/Termind/Features/Workspaces/WorkspaceContentView.swift b/Termind/Features/Workspaces/WorkspaceContentView.swift index 58c630b9..2e704608 100644 --- a/Termind/Features/Workspaces/WorkspaceContentView.swift +++ b/Termind/Features/Workspaces/WorkspaceContentView.swift @@ -821,6 +821,9 @@ struct WelcomeView: View { .frame(maxWidth: .infinity, maxHeight: .infinity) .background(.background) .onAppear { isSearchFocused = true } + .onChange(of: window.welcomeSearchFocusRequest) { _, _ in + isSearchFocused = true + } } private var header: some View { diff --git a/TermindTests/WindowToolbarFindTests.swift b/TermindTests/WindowToolbarFindTests.swift index 215af18f..0e9daabe 100644 --- a/TermindTests/WindowToolbarFindTests.swift +++ b/TermindTests/WindowToolbarFindTests.swift @@ -38,10 +38,27 @@ struct WindowToolbarFindTests { window.openPage(.welcome) #expect(window.findKind == nil) - #expect(!window.canFindInMainContent) + #expect(window.canFindInMainContent) #expect(window.creationActions.isEmpty) } + /// Welcome participates in the window-level Find command without growing a + /// second search field in the titlebar. + @Test + func focusingFindOnWelcomeRequestsItsContentSearchField() { + let window = WindowModel() + var titlebarFocusRequests = 0 + window.focusToolbarFindField = { titlebarFocusRequests += 1 } + window.openPage(.welcome) + + window.focusToolbarFind() + + #expect(window.welcomeSearchFocusRequest == 1) + #expect(window.findFocusRequest == 0) + #expect(!window.isToolbarFindFocused) + #expect(titlebarFocusRequests == 0) + } + @Test func assistantResolvesToConversationSearch() { let window = WindowModel() @@ -74,6 +91,7 @@ struct WindowToolbarFindTests { let window = WindowModel(workspaces: [Workspace(pane: Pane(.empty))]) #expect(window.findKind == nil) + #expect(!window.canFindInMainContent) #expect(window.creationActions.isEmpty) } @@ -98,12 +116,12 @@ struct WindowToolbarFindTests { /// counter nobody is watching. @Test func focusingFindIsANoOpWhereThereIsNoField() { - let window = WindowModel() - window.openPage(.welcome) + let window = WindowModel(workspaces: [Workspace(pane: Pane(.empty))]) window.focusToolbarFind() #expect(window.findFocusRequest == 0) + #expect(window.welcomeSearchFocusRequest == 0) } @Test