Skip to content

Find in page (⌘F) - #480

Open
ianu82 wants to merge 3 commits into
pr/agent-appsfrom
pr/find-in-page
Open

Find in page (⌘F)#480
ianu82 wants to merge 3 commits into
pr/agent-appsfrom
pr/find-in-page

Conversation

@ianu82

@ianu82 ianu82 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

What

⌘F opens a Chrome-style find bar over the current tab: live match count, Enter / Shift+Enter to step through matches, Esc to close.

The bar is a DOM strip above the native WebContentsView, so the page's bounds simply shrink below it — no fighting an OS-level view for z-order. Find state resets when you switch tabs (we keep it simple rather than mirroring Chrome's per-tab find memory).

Also carries a one-commit fix for a crash found in testing: closeFind was declared before the activeTabId it closes over, so mounting the route hit a temporal-dead-zone error. It's now declared after.

Stacked on pr/agent-apps. npm run typecheck + tests green.

For QA

  1. On the Browser route press ⌘F: the find bar appears, input focused.
  2. Type a query: matches highlight in the page and the bar shows the count (e.g. "2 of 7").
  3. Enter steps forward, Shift+Enter backward, wrapping at the ends; Esc closes the bar and clears the highlights.
  4. Switch to another tab with the bar open: the bar closes cleanly and the other tab has no leftover highlights.
  5. Launch the app straight into a saved browser session (cold mount): the route renders, no crash — that's the TDZ regression check.

ianu82 added 2 commits July 22, 2026 19:22
Chrome-style find bar: live debounced search with a match counter
(n/m), Enter/Shift+Enter and chevron buttons for next/prev, Esc closes.
The bar takes a DOM strip at the top of the content column so the
native view's mirrored bounds shrink below it — no OS-view overlap.
Closes (and clears highlights) on tab switch. Main side: findInPage/
stopFindInPage IPC resolving through the tab's webContents with the
found-in-page result.
The find-bar close callback referenced activeTabId in its useCallback
deps before the const below it was initialized, so mounting the Browser
route threw a temporal-dead-zone ReferenceError and the whole route
failed to render. Moved below the declaration.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8ebe025d0b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
// Skip the round-trip for an identical query (arrow-key re-renders).
const key = `${q}|${findNext}|${forward}`;
if (key === lastSentRef.current) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not suppress repeated next searches

When the user presses Enter or clicks Next more than once for the same query, the first navigation stores a key like term|true|true, and every subsequent identical next action returns here before sending another findInPage request. That leaves the active match stuck after one advance instead of continuing through the page; the de-dupe needs to skip only passive re-renders/live-search repeats, not explicit findNext actions.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — explicit Enter/Next always sends now; only passive repeats are de-duped (dc3b978).

if (activeTabId) host.browserStopFind?.(activeTabId);
}, [activeTabId]);
// Switching tabs closes the bar (and clears the old page's highlights).
useEffect(() => { if (findOpen) closeFind(); }, [activeTabId]); // eslint-disable-line react-hooks/exhaustive-deps

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear find state on the tab being left

When switching tabs while the find bar is open, this effect runs after activeTabId has already changed, so closeFind() sends browserStopFind to the destination tab rather than the tab that currently has find highlights. The source tab's WebContents keeps its highlighted matches, and they reappear when the user switches back even though the find bar was closed; keep the previous tab id or clear before activating the new tab.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the tab-switch effect stops find on the tab being left (tracked via a ref), so the old page's highlights are actually cleared (dc3b978).

Two valid Codex findings on #480:
- The de-dupe key swallowed explicit repeated Enter/Next actions, so the
  active match advanced once and then appeared stuck. Explicit findNext
  actions now always send; only passive repeats are skipped.
- Switching tabs closed the bar AFTER activeTabId changed, sending
  stopFind to the destination tab and leaving the old page's matches
  highlighted. The switch effect now stops find on the tab being left.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant