Commit graph

126 commits

Author SHA1 Message Date
Lawrence Chen
dd54927cb9
Add React Grab inject button to browser toolbar (#2373)
* Add React Grab inject button to browser toolbar

Adds a toolbar button (cursor click icon) that injects the react-grab
script (unpkg.com/react-grab/dist/index.global.js) into the current
page. Hover over React elements and Cmd+C to copy component context
(file, component name, line number) for AI agents.

Button highlights when active, resets on navigation.

* Auto-activate selection mode on React Grab inject

First click: injects the script and auto-activates selection mode via
the react-grab:init event. Subsequent clicks toggle selection mode
on/off via window.__REACT_GRAB__.toggle().

* Bridge React Grab state back to Swift via WKScriptMessageHandler

Register a cmux-bridge plugin after injecting react-grab that posts
state changes back to Swift via webkit.messageHandlers. The button
now highlights accent color only when selection mode is actually
active (not just when the script is loaded), and deactivates when
the user exits selection mode via Escape or the react-grab toolbar.

* Fetch react-grab script via URLSession to bypass CSP

Sites like vercel.com block loading external scripts via CSP headers.
Fetch the script with URLSession (not subject to page CSP), cache it,
and inject inline via evaluateJavaScript. Also guard against duplicate
injection on repeated clicks.

* Prefetch react-grab script on first browser panel init

Kick off a low-priority background fetch of the react-grab script
when the first BrowserPanel is created. The script is cached
statically so clicking the button is instant.

* Eliminate react-grab button and callback lag

Three changes:
1. Fire-and-forget: use evaluateJavaScript with completionHandler
   instead of await, so button taps return immediately.
2. Single JS payload: combine bootstrap listener + script source
   into one evaluateJavaScript call (one IPC round-trip, not two).
3. Dedupe state callbacks: only post webkit message when isActive
   actually changes, not on every hover/drag state update.

* Fix duplicate state callback on react-grab toggle

toggleReactGrab was sending an explicit postMessage AND the plugin's
onStateChange hook was firing too, causing two @Published updates per
toggle. Remove the explicit postMessage since the plugin hook handles
it. Also add dlog instrumentation for debugging.

* Add Cmd+Shift+G shortcut for React Grab (configurable)

- Add toggleReactGrab to KeyboardShortcutSettings with Cmd+Shift+G default
- Add View menu item with customizable shortcut
- Add command palette entry (searchable as "react grab" or "inspect element")
- Simplify button to use toggleOrInjectReactGrab, remove local state tracking

* Fix Codex review findings: pin version, verify hash, fix retry and state

1. Pin react-grab to exact version (0.1.29) with SHA-256 integrity
   check. Script is verified before evaluation to prevent supply-chain
   attacks via compromised CDN responses.
2. Clear prefetchTask on failure so subsequent attempts retry the
   download instead of reusing a permanently failed task.
3. Remove premature isReactGrabActive=true. State is now only set
   by the onStateChange message handler callback after confirmed
   initialization, or explicitly reset on evaluation error.

* Extract React Grab into own file, make version configurable

Move all react-grab logic (settings, script loader, message handler,
BrowserPanel extension) into Sources/Panels/ReactGrab.swift.

Add a "React Grab Version" text field in Settings > Browser that lets
the user pin which npm version is fetched. Only versions with a known
SHA-256 integrity hash in ReactGrabSettings.knownHashes are accepted.
The cache invalidates when the configured version changes.

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
2026-03-30 18:00:45 -07:00
Lawrence Chen
8a3ab6b3f0
Fix command palette focus after terminal find (#2089)
* test: cover command palette focus guard

* fix: block terminal find from stealing palette focus

* test: cover text view focus-stealer fallback

* Add regression for hidden DevTools sync republish loop

* Avoid redundant DevTools visibility publishes

* test: cover browser find focus after workspace round-trip

* fix: restore browser find focus after workspace round-trip

* fix: keep browser find caret on workspace return

* Add workspace round-trip split find regressions

* Keep inactive find overlays from stealing focus

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
2026-03-25 17:27:54 -07:00
Elvis Tran
b919541044
Fix panel resize stuttering when tiled with browser panels (#1969)
* Fix panel resize stuttering when tiled with browser panels (#1968)

During divider drag, the portal sync system was doing O(N²) work per
frame: each geometry callback synced ALL web views, and multiple
callbacks fired per layout pass (setFrameSize + setFrameOrigin + layout).

Two changes:

1. synchronizeWebViewForAnchor now only syncs the primary web view and
   defers the all-sync. Each panel fires its own geometry callback, so
   secondary syncs are redundant on the hot path.

2. HostContainerView.setFrameOrigin/setFrameSize use markGeometryDirtyIfNeeded
   which defers the callback to layout(), coalescing 2-3 notifications
   per frame into one. An async fallback ensures origin-only changes
   (without a subsequent layout) are still delivered.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix premature geometryRevision increment in markGeometryDirtyIfNeeded

Address reviewer feedback (Greptile, CodeRabbit): geometryRevision and
lastReportedGeometryState are now only updated when the callback
actually fires, not eagerly.  This prevents updateNSView from seeing a
premature revision delta and triggering a redundant synchronizeForAnchor
before the coalesced notification arrives.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 22:24:17 -07:00
Austin Wang
fd279bdcec
Fix splitter hitbox overlap and terminal scrollbar width resync (#1950)
* test: add splitter and scrollbar regressions

* fix: narrow sidebar overlap and resync terminal width

* test: unwrap pending surface width in scrollbar regression

* fix: restore hosted inspector divider drag path
2026-03-22 18:06:11 -07:00
Apptah
5ced3134d3
Fix browser freeze after pane split by reattaching WKWebView rendering state (#1852)
When a pane split occurs, SwiftUI recreates host views and the portal
system rebinds the WKWebView to a new container. However, the bind path
never called BrowserWindowPortalRegistry.refresh(), so WebKit's internal
rendering state (_exitInWindow/_enterInWindow) was never cycled. This
left the WKWebView frozen in the original pane after a split.

Add refresh() calls after every portal bind that changes the host, in
three code paths: the main update path (shouldBindNow), onDidMoveToWindow,
and onGeometryChanged. The refresh is a no-op when no reattach is needed
(browserPortalNeedsRenderingStateReattach == false), so normal rendering
is unaffected.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:05:39 -07:00
Lawrence Chen
4c92271137
Merge pull request #1913 from centraldogma99/fix/korean-input-keyboard-shortcuts
Fix keyboard shortcuts not working with Korean input mode
2026-03-22 17:18:47 -07:00
austinpower1258
e935eb57d3 Fix browser pane video fullscreen 2026-03-21 12:17:55 -07:00
최준영
8cd9cd96c1 Fix keyboard shortcuts not working with Korean (한글) input mode
When a non-Latin input source like Korean 두벌식 is active,
event.charactersIgnoringModifiers returns Hangul characters (e.g. ㅅ
for T key) instead of Latin letters. This caused all character-based
shortcut matching to fail — Cmd+T, Cmd+D, Cmd+1-9, Ctrl+N/P, etc.

Root cause: KeyboardLayout.character(forKeyCode:modifierFlags:) assumed
CJK input sources lack kTISPropertyUnicodeKeyLayoutData, but Korean
두벌식 has it. UCKeyTranslate returned Korean characters and the ASCII
fallback was never reached.

Fix:
- KeyboardLayout.character(): check result is ASCII before accepting;
  fall through to TISCopyCurrentASCIICapableKeyboardInputSource() when
  the current source returns non-ASCII characters
- Add KeyboardLayout.normalizedCharacters(for:) helper that normalizes
  event.charactersIgnoringModifiers for shortcut comparison
- Apply normalization in handleCustomShortcut (AppDelegate),
  BrowserPanelView omnibar key handler, and BrowserPopupWindowController
  Cmd+W handler

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 21:16:10 +09:00
Lawrence Chen
a592ed126a
Add failing regression test for browser find focus (#1891)
* test: add browser find focus regression

* ci: run browser find focus regression on prs

* ci: merge pr ui regressions into one job

* fix: focus browser find after navigation

* test: rename ui regressions workflow guard

* Fix browser find focus after address bar navigation

* Fix test-e2e workflow manifest script

* Address PR review feedback

* Stabilize browser focus regression on CI

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
2026-03-20 22:12:26 -07:00
Lawrence Chen
58de044f4f
Rename "Import From Browser" to "Import Browser Data" (#1672)
Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
2026-03-17 22:07:19 -07:00
Austin Wang
59901034bf
Merge pull request #1627 from manaflow-ai/issue-1623-devtools-x-close-state
Fix browser devtools X-close persistence
2026-03-17 17:48:01 -07:00
austinpower1258
48426bf1ec Tighten browser devtools close timing 2026-03-17 17:37:01 -07:00
austinpower1258
8397b32067 Debounce browser devtools visibility-loss sync 2026-03-17 17:13:51 -07:00
Lawrence Chen
c4742a4ba1
Refine browser import minimal UI 2026-03-17 16:46:10 -07:00
austinpower1258
79fade5add Sync browser devtools preference on surface focus loss 2026-03-17 16:32:59 -07:00
austinpower1258
fabcb06891 Fix browser devtools X-close persistence 2026-03-17 16:28:19 -07:00
Lawrence Chen
d369778f7f
Scroll settings hint to import controls 2026-03-17 04:48:21 -07:00
Lawrence Chen
c5ae8dc9eb
Defer browser import dialog presentation 2026-03-17 03:23:18 -07:00
Lawrence Chen
9807cb087b
Stabilize browser import hint UI tests 2026-03-17 03:14:23 -07:00
Lawrence Chen
b9de0f0446
Add browser import hint debug variants 2026-03-17 03:01:50 -07:00
Lawrence Chen
fdde470dcf
fix: address browser profile review follow-ups 2026-03-16 23:50:43 -07:00
Lawrence Chen
746fb8e5ec
Merge pull request #318 from manaflow-ai/issue-122-import-browser-cookies-history-settings
Browser: import data from detected installed browsers
2026-03-16 22:42:40 -07:00
Lawrence Chen
dc6bcb259a
fix: address browser import review feedback 2026-03-16 22:30:09 -07:00
Austin Wang
9bf6ad9457
Avoid blocking browser PR metadata updates (#1564) 2026-03-16 22:10:15 -07:00
Lawrence Chen
92cb42262c
feat: add browser profile mapping import flow 2026-03-16 21:22:39 -07:00
Lawrence Chen
1d540d0806 Merge origin/main into issue-122-import-browser-cookies-history-settings 2026-03-12 18:40:20 -07:00
austinpower1258
f843ce2706 Hide unsafe side dock controls for attached devtools 2026-03-11 23:04:28 -07:00
austinpower1258
72e7a9de76 Adapt attached devtools to narrow panes 2026-03-11 22:56:39 -07:00
austinpower1258
df54af34cf Merge branch 'main' of https://github.com/manaflow-ai/cmux into issue-1183-devtools-resize-layout
# Conflicts:
#	cmuxTests/CmuxWebViewKeyEquivalentTests.swift
2026-03-11 22:16:07 -07:00
austinpower1258
7d5d4d718d wip 2026-03-11 22:13:45 -07:00
austinpower1258
8aafb68935 Fix browser pane drag/drop follow-ups 2026-03-11 19:16:17 -07:00
Lawrence Chen
5d82a29f45 Repair local-host devtools reparent geometry 2026-03-11 18:21:41 -07:00
Lawrence Chen
6849b83f8d
Reduce typing lag from sidebar re-evaluation and hitTest overhead (#1204)
* Add typing hot path timing diagnostics

* Add stress workspace debug menu item

* Restore stress workspace preload debug path

* Reduce typing lag from sidebar re-evaluation and hitTest overhead

hitTest: gate divider/sidebar/drag routing to pointer events only,
avoiding two full view-tree walks per non-pointer event.

forceRefresh: replace per-keystroke ISO8601DateFormatter + FileHandle
I/O with dlog() in DEBUG builds.

TabItemView: replace @EnvironmentObject subscriptions with plain refs
and precomputed parameters, add Equatable conformance to skip body
re-evaluation when parent rebuilds with unchanged values. @self changed
re-evaluations dropped from 668 to 1 during rapid typing.

* Add typing-latency guardrail comments and CLAUDE.md pitfalls

Strategic comments on hitTest, TabItemView, and forceRefresh to prevent
future regressions. Adds typing-latency-sensitive paths to CLAUDE.md
pitfalls section so agents know the constraints before editing.

* Add workspace palette actions and fix release autosave typing guard

Add Move Up/Down/Top, Close Other/Above/Below, Mark Read/Unread to
Cmd+Shift+P command palette and a Workspace submenu in the menu bar.

Fix recordTypingActivity() being gated behind #if DEBUG, which prevented
release builds from honoring the typing quiet period in autosave.
2026-03-11 17:54:02 -07:00
austinpower1258
06c5cac4df Stabilize docked devtools side resize 2026-03-11 12:26:19 -07:00
austinpower1258
8b66628b19 Route inline inspector hits to native webkit 2026-03-11 04:21:49 -07:00
austinpower1258
63787c26b1 Stabilize inline developer tools hosting 2026-03-11 04:17:37 -07:00
Lawrence Chen
3ca11a5e00 Keep off-window local hosts from stealing devtools view 2026-03-10 21:12:18 -07:00
Lawrence Chen
359ada8a3f Preserve side-docked browser devtools layout on pane resize 2026-03-10 20:42:26 -07:00
Austin Wang
d25067f38f
Merge pull request #1170 from manaflow-ai/fix-1160-devtools-loop
Fix side-docked browser DevTools resizing
2026-03-10 20:12:17 -07:00
austinpower1258
91061ce341 Fix side-docked browser DevTools resizing 2026-03-10 19:49:06 -07:00
Lawrence Chen
ec10dfdaec
Add browser find focus debug logs (#1162)
* Add browser find focus debug logs

* Allow browser find bar focus in portal host

* Add split and terminal find debug logs

* Avoid stealing search focus across splits

* Generalize panel focus restore intent

* Unify split focus intent activation

* Address focus restore review feedback

* Yield inactive panel focus before restore

* Gate browser find focus retries by generation

* Avoid repeated browser focus invalidation

* Keep browser find ownership while find bar is open
2026-03-10 19:31:52 -07:00
austinpower1258
eea6cdc1bd works 2026-03-10 19:18:30 -07:00
Austin Wang
8fa1ca3a4d
Hide browser portal when terminal tab is active (#1130) 2026-03-09 17:24:58 -07:00
Austin Wang
c447bee602
Fix browser pane portal anchor sizing (#1094)
* Fix browser pane webview sizing

* Guard browser portal by pane ownership

* Keep browser portal frame during transient zero geometry

* Guard portal surfaces against duplicate hosts

* Defer terminal surface reflow during tab drags

* Fix browser panel pane ID unit tests
2026-03-09 13:28:05 -07:00
austinpower1258
52bd8cf16a Keep browser webviews alive during drag reparenting 2026-03-08 03:04:12 -07:00
austinpower1258
58f1f34466 Fix browser reattach after pane reparenting 2026-03-07 18:49:42 -08:00
Austin Wang
0c11bc17cd
Merge pull request #1043 from manaflow-ai/issue-1036-tooltip-tracking-area-crash
Fix tooltip tracking lifetime and shortcut lag
2026-03-07 03:05:48 -08:00
Lawrence Chen
e680f1de55
Add DEBUG logging for browser omnibar/content focus handoff (#910)
* Add browser focus debug logging around omnibar/content handoff

* Avoid release-only unused-value warnings in focus debug logs

* Add omnibar focus writer trace logs

* Fix omnibar tap focus race

* Stabilize omnibar focus state transitions

* Propagate event context into responder guard

* Fix webview pointer hit testing in focus guard

* Stop omnibar reacquire on pointer blur intent

* Blur omnibar on webview click intent

* Preserve pointer intent through webview focus handoff

* Restore page input focus after omnibar escape

* Fix omnibar escape focus handoff and restore retry

* Track editable focus for omnibar restore and improve test diagnostics

* Add omnibar focus tracker telemetry to failing UI test

* Wait for page readiness before seeding focused input in UI test setup

* Strengthen omnibar escape focus regression with post-click assertion

* Use deterministic window offsets for post-escape web input click test

* Always enforce webview responder on omnibar escape

* Harden omnibar focus restore and address PR review feedback

---------

Co-authored-by: tiffanysun1 <tiffanysun8@gmail.com>
2026-03-07 03:05:13 -08:00
austinpower1258
9e8a401e3c Fix tooltip tracking lifetime and shortcut lag 2026-03-07 01:46:02 -08:00
austinpower1258
d43d7d6a51 Fix drag hover redraw churn in hosted panes 2026-03-06 15:47:11 -08:00