diff --git a/frontend/app/element/search.tsx b/frontend/app/element/search.tsx index 031bcd97d..b9770570a 100644 --- a/frontend/app/element/search.tsx +++ b/frontend/app/element/search.tsx @@ -16,6 +16,7 @@ type SearchProps = SearchAtoms & { onSearch?: (search: string) => void; onNext?: () => void; onPrev?: () => void; + blockId?: string; }; const SearchComponent = ({ @@ -32,6 +33,7 @@ const SearchComponent = ({ onSearch, onNext, onPrev, + blockId, }: SearchProps) => { const [isOpen, setIsOpen] = useAtom(isOpenAtom); const [search, setSearch] = useAtom(searchAtom); @@ -144,7 +146,7 @@ const SearchComponent = ({ <> {isOpen && ( -
+
0) { + return terminalSelection.trim(); + } + } + } + + // Check for regular text selection + const selection = window.getSelection(); + if (selection && selection.rangeCount > 0 && !selection.isCollapsed) { + const selectedText = selection.toString().trim(); + if (selectedText.length > 0) { + return selectedText; + } + } + return ""; + } + + function focusSearchInput() { + setTimeout(() => { + const blockId = getFocusedBlockInStaticTab(); + if (!blockId) { + return; + } + + // Directly find the search container by data-blockid attribute + const searchContainer = document.querySelector( + `.search-container[data-blockid="${blockId}"]` + ) as HTMLElement; + if (searchContainer) { + const searchInput = searchContainer.querySelector("input") as HTMLInputElement; + if (searchInput) { + searchInput.focus(); + searchInput.select(); + } + } + }, 0); + } + function activateSearch(event: WaveKeyboardEvent): boolean { const bcm = getBlockComponentModel(getFocusedBlockInStaticTab()); - // Ctrl+f is reserved in most shells + // Ctrl+f is reserved in most shells. if (event.control && bcm.viewModel.viewType == "term") { return false; } if (bcm.viewModel.searchAtoms) { - globalStore.set(bcm.viewModel.searchAtoms.isOpen, true); + const searchAtoms = bcm.viewModel.searchAtoms; + const isOpen = globalStore.get(searchAtoms.isOpen); + const selectedText = getSelectedText(); + + // Open search dialog if not already open + if (!isOpen) { + globalStore.set(searchAtoms.isOpen, true); + } + // Set search value (use selected text if available, otherwise empty string) + globalStore.set(searchAtoms.searchValue, selectedText || ""); + // Reset search results + globalStore.set(searchAtoms.resultsIndex, 0); + globalStore.set(searchAtoms.resultsCount, 0); + focusSearchInput(); return true; } return false; diff --git a/frontend/app/view/term/term.tsx b/frontend/app/view/term/term.tsx index 387155752..89948f81c 100644 --- a/frontend/app/view/term/term.tsx +++ b/frontend/app/view/term/term.tsx @@ -178,6 +178,7 @@ const TerminalView = ({ blockId, model }: ViewComponentProps) => caseSensitive: false, wholeWord: false, regex: false, + blockId: blockId, }); const searchIsOpen = jotai.useAtomValue(searchProps.isOpen); const caseSensitive = useAtomValueSafe(searchProps.caseSensitive); diff --git a/frontend/app/view/webview/webview.tsx b/frontend/app/view/webview/webview.tsx index 5695f99e6..104330725 100644 --- a/frontend/app/view/webview/webview.tsx +++ b/frontend/app/view/webview/webview.tsx @@ -821,7 +821,7 @@ const WebView = memo(({ model, onFailLoad, blockRef, initialSrc }: WebViewProps) } // Search - const searchProps = useSearch({ anchorRef: model.webviewRef, viewModel: model }); + const searchProps = useSearch({ anchorRef: model.webviewRef, viewModel: model, blockId: model.blockId }); const searchVal = useAtomValue(searchProps.searchValue); const setSearchIndex = useSetAtom(searchProps.resultsIndex); const setNumSearchResults = useSetAtom(searchProps.resultsCount);