Skip to content

Add browser inspect prompt and composer image polish#257

Merged
zvadaadam merged 9 commits into
mainfrom
zvadaadam/inspect-mode-prompt
Apr 28, 2026
Merged

Add browser inspect prompt and composer image polish#257
zvadaadam merged 9 commits into
mainfrom
zvadaadam/inspect-mode-prompt

Conversation

@zvadaadam

@zvadaadam zvadaadam commented Apr 23, 2026

Copy link
Copy Markdown
Owner

Adds the inline browser inspect prompt flow, including pinned selection state, prompt anchoring, padded element screenshots, and shared screenshot-to-composer attachment handling. It also hardens inspect cleanup across tab and selector changes while keeping the selected element visible during prompt entry. On the composer side, staged content is split into separate pill, image, and pasted-text rows, and pasted images now open in a cleaner preview dialog with better framing, controls, and image handling. Validation: bunx tsc --noEmit --project tsconfig.web.json and targeted ESLint on the touched files.

Summary by CodeRabbit

  • New Features

    • Floating inspect prompt to annotate selected elements and attach element-scoped or full-page screenshots
    • Toggleable inspect overlays and safe/conditional clear-selection controls (host-accessible)
    • Keyboard shortcut to toggle inspect mode
  • UI Improvements

    • Pinned element selection keeps highlights stable and immediate overlay repositioning
    • Composer staged content reorganized into grouped sections
    • Dialog-driven image preview with improved remove interaction
  • Bug Fixes

    • Pinned selection now resets when inspect mode is toggled or cleared

@coderabbitai

coderabbitai Bot commented Apr 23, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds per-selection keys and pinned selection state to injected inspect-mode, exposes overlay-visibility and keyed clear APIs, extends host/webview types and BrowserTab handle for rect-based captures and inspect controls, introduces attachScreenshotToComposer, adds a deferred InspectPromptOverlay flow for user text before attaching element-scoped screenshots, and wires a guest toggle shortcut.

Changes

Cohort / File(s) Summary
Inspect-mode Injection & Runtime
apps/web/src/features/browser/automation/inject/inspect-mode.js
Adds counter-based selectionKey, returns selectionKey from click capture, pins overlays to clicked elements (suppressing hover redraws), hides dimension label when pinned, and exposes window.__deusInspect.setOverlaysVisible(visible) and window.__deusInspect.clearSelection(expectedSelectionKey).
Inspect-mode Helpers / Builders
apps/web/src/features/browser/automation/inspect-mode.ts
Exports IIFE strings/constants INSPECT_MODE_HIDE_OVERLAYS, INSPECT_MODE_SHOW_OVERLAYS, and buildInspectModeClearSelection(expectedSelectionKey?) for host injection.
Types & Webview API
apps/web/src/features/browser/types.ts, apps/web/src/features/browser/webview-manager.ts
ElementSelectedEvent gains optional selectionKey. captureScreenshot/WebviewElement.capturePage accept optional rect {x,y,width,height}. BrowserTabHandle adds setInspectOverlaysVisible, clearInspectSelection(expectedSelectionKey?), getWebviewBounds, and setElementSelectorActive. Adds TOGGLE_INSPECT_MODE_EVENT.
BrowserTab Host Integration
apps/web/src/features/browser/ui/BrowserTab.tsx
Adds setElementSelectorActive(active) helper, forwards rect to wv.capturePage(rect), maintains pageBoundsRef, and exposes setInspectOverlaysVisible, clearInspectSelection, and getWebviewBounds via the imperative handle (best-effort, swallow failures). Emits TOGGLE_INSPECT_MODE_EVENT for guest shortcut.
BrowserPanel & Inspect Flow
apps/web/src/features/browser/ui/BrowserPanel.tsx
Switches to deferred prompt flow: stores pendingInspection + webview bounds, renders InspectPromptOverlay, temporarily hides overlays to capture padded element-region screenshots, uses attachScreenshotToComposer for attachments, and clears/dismisses pending inspection on tab change or selector toggle.
Inspect Prompt UI
apps/web/src/features/browser/ui/InspectPromptOverlay.tsx
New portal dialog anchored to translated element rect; manages textarea state, focus, Escape/Enter/compose behavior, placement/clamping, async submit lifecycle, and animations.
Screenshot Attachment Utility
apps/web/src/features/browser/lib/attachScreenshotToComposer.ts
New helper decodes data URL to a PNG File (named browser-${label}-${Date.now()}.png), calls processImageFiles, attaches resulting files to composer, and returns boolean success (logs on error).
Session Composer & Staged UI
apps/web/src/features/session/ui/MessageInput.tsx, apps/web/src/features/session/ui/PastedImageCard.tsx
Replaces combined staged content with ComposerStagedContent splitting pills/images/pastes; PastedImageCard now uses dialog-driven preview and adjusts remove button behavior to avoid interfering with dialog interactions.
Parsing & Text Rendering
apps/web/src/features/session/lib/parseInspectTags.ts, apps/web/src/features/session/ui/blocks/TextBlock.tsx
Normalizes HTML-escaped <inspect> markup before parsing; TextBlock now detects escaped &lt;inspect markers to call parser.
Desktop Guest Shortcut
apps/desktop/preload/browser-preload.ts
Adds Cmd/Ctrl+Shift+D → toggle-inspect-mode guest shortcut and extends BrowserGuestShortcut union.
Backend PR Lookup & Tests
apps/backend/src/services/gh.service.ts, apps/backend/test/unit/services/gh.service.test.ts
getPrStatus removes --author @me`` from gh pr list calls; tests updated to mock remotes and assert `--head <owner/branch>` is used and `--author` is absent.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Inject as Injected Inspect JS
    participant BrowserPanel
    participant BrowserTab
    participant Overlay as InspectPromptOverlay
    participant Composer

    User->>Inject: click element -> captureElement() returns {rect, selectionKey}
    Inject-->>BrowserPanel: emit ElementSelectedEvent (rect, selectionKey)
    BrowserPanel->>BrowserPanel: store pendingInspection + webviewBounds
    BrowserPanel->>Overlay: render prompt anchored to translated rect

    User->>Overlay: submit text
    Overlay->>BrowserPanel: onSubmit(text)
    BrowserPanel->>BrowserTab: setInspectOverlaysVisible(false)
    BrowserTab->>Inject: inject hide overlays IIFE
    BrowserPanel->>BrowserTab: captureScreenshot(rect)
    BrowserTab->>Inject: capturePage(rect) -> dataURL
    BrowserPanel->>BrowserTab: setInspectOverlaysVisible(true)
    BrowserTab->>Inject: inject show overlays IIFE
    BrowserPanel->>Composer: appendDraft + addInspectedElement
    BrowserPanel->>Composer: attachScreenshotToComposer(dataURL, label)
    BrowserPanel->>BrowserTab: clearInspectSelection(selectionKey)
    BrowserTab->>Inject: inject clear-selection IIFE (expectedSelectionKey)
    BrowserPanel->>BrowserPanel: clear pendingInspection
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped and I keyed the element bright,

A pin held my pick through hover and light.
I typed a small note, hid overlays for a snap,
Tucked a padded screenshot — then closed up the map.
Nibble, send — the inspect dance drew a happy clap!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add browser inspect prompt and composer image polish' directly corresponds to the main changes: a new inline browser inspect prompt flow (InspectPromptOverlay component, pinned selection state, prompt anchoring) and composer image UI polish (staged content split, pasted image preview dialog).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch zvadaadam/inspect-mode-prompt

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/web/src/features/browser/ui/InspectPromptOverlay.tsx (1)

137-157: Derive the overlay position instead of syncing it through effects.

Line 137 introduces placement as local state even though it is fully derived from anchor, and Lines 144-157 immediately synchronize that derived value plus the reset state in effects. That adds an avoidable extra render on every retarget and is the same pattern react-hooks/set-state-in-effect is warning about here. placement can be computed during render (anchor ? placeOverlay(anchor) : null), and the textarea reset can come from keying the overlay by the inspection id in the parent instead of effect-driven setState.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/features/browser/ui/InspectPromptOverlay.tsx` around lines 137 -
157, The placement state in InspectPromptOverlay (placement / setPlacement) is
derived from anchor via placeOverlay and is unnecessarily synchronized in a
useLayoutEffect; compute placement during render using const placement = anchor
? placeOverlay(anchor) : null and remove the placement useState and its
useLayoutEffect; also remove the useEffect that resets setText/setIsSubmitting
on event and instead have the parent key the overlay by the inspection id (or
event identity) so a new key causes React to remount the overlay and reset local
textarea state automatically, leaving only anchor, placeOverlay, setText,
setIsSubmitting, and event references to guide the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/features/browser/ui/BrowserPanel.tsx`:
- Around line 74-79: The pendingInspection flow currently snapshots
getWebviewBounds() into PendingInspection.webviewBounds and passes that frozen
rect to InspectPromptOverlay, causing the prompt to drift when layout changes;
change PendingInspection to omit or keep webviewBounds null (store only id,
event, tabId), stop persisting the frozen bounds in pendingInspection, and
instead call getWebviewBounds() at render time (or recompute/update bounds on
layout/resizes) when creating/rendering InspectPromptOverlay so the overlay
always receives live webview bounds; update any code that constructs
pendingInspection (references to pendingInspection and getWebviewBounds) and the
InspectPromptOverlay prop usage to read current bounds rather than the stored
rect.

In `@apps/web/src/features/session/ui/PastedImageCard.tsx`:
- Around line 67-77: The className strings on the remove-button (the m.div
wrapper/button with X) and the DialogContent component contain hardcoded color
utilities like bg-black/72, rgba(...) shadows, and hover:bg-black/5; replace
each hardcoded color or rgba shadow with the corresponding theme CSS
variable/token classes (e.g., overlay background token, theme shadow token,
hover-bg token) so the component is theme-safe, updating the className values on
the remove button and DialogContent accordingly; leave the intentional
image-edge exception border-black/10 and dark:border-white/10 unchanged and
ensure no other hardcoded color literals remain in the m.div/button,
DialogContent, or nearby className strings.

---

Nitpick comments:
In `@apps/web/src/features/browser/ui/InspectPromptOverlay.tsx`:
- Around line 137-157: The placement state in InspectPromptOverlay (placement /
setPlacement) is derived from anchor via placeOverlay and is unnecessarily
synchronized in a useLayoutEffect; compute placement during render using const
placement = anchor ? placeOverlay(anchor) : null and remove the placement
useState and its useLayoutEffect; also remove the useEffect that resets
setText/setIsSubmitting on event and instead have the parent key the overlay by
the inspection id (or event identity) so a new key causes React to remount the
overlay and reset local textarea state automatically, leaving only anchor,
placeOverlay, setText, setIsSubmitting, and event references to guide the
change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d4c7b9b3-890e-4b0c-a1c4-a1fde5af4b80

📥 Commits

Reviewing files that changed from the base of the PR and between e1903a0 and ab0d62e.

📒 Files selected for processing (10)
  • apps/web/src/features/browser/automation/inject/inspect-mode.js
  • apps/web/src/features/browser/automation/inspect-mode.ts
  • apps/web/src/features/browser/lib/attachScreenshotToComposer.ts
  • apps/web/src/features/browser/types.ts
  • apps/web/src/features/browser/ui/BrowserPanel.tsx
  • apps/web/src/features/browser/ui/BrowserTab.tsx
  • apps/web/src/features/browser/ui/InspectPromptOverlay.tsx
  • apps/web/src/features/browser/webview-manager.ts
  • apps/web/src/features/session/ui/MessageInput.tsx
  • apps/web/src/features/session/ui/PastedImageCard.tsx

Comment thread apps/web/src/features/browser/ui/BrowserPanel.tsx
Comment thread apps/web/src/features/session/ui/PastedImageCard.tsx Outdated
@zvadaadam

Copy link
Copy Markdown
Owner Author

Greenlight — Round 1

Fixed (2): live webview bounds are now resolved at render time for the inspect prompt; PastedImageCard no longer uses hardcoded non-exempt colors/shadows and stays on theme tokens.
Disagreed (0): none.
Deferred (0): none.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (3)
apps/web/src/features/browser/ui/BrowserPanel.tsx (3)

594-647: Consider adding error logging for silent failures.

If appendDraft, addInspectedElement, or the screenshot capture throws, the finally block clears the inspection but the error is swallowed silently. The user might not realize their inspection data wasn't attached.

♻️ Optional: add error logging
     try {
       // 1. User-typed prompt — appended (preserves any in-progress draft).
       sessionComposerActions.appendDraft(sid, text);
       // ... rest of try block
+    } catch (err) {
+      console.error("[BrowserPanel] Inspect prompt submission failed:", err);
     } finally {
       clearPendingInspection(inspection);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/features/browser/ui/BrowserPanel.tsx` around lines 594 - 647,
The try/finally in handleInspectPromptSubmit swallows errors from
sessionComposerActions.appendDraft, sessionComposerActions.addInspectedElement,
handle.captureScreenshot, or attachScreenshotToComposer so failures are silent;
update the handler to catch errors, log them (include operation context and
inspection ref/tabId) and surface a user-visible error (or rethrow) before the
finally clears the inspection. Specifically wrap the body where
appendDraft/addInspectedElement/captureScreenshot/attachScreenshotToComposer are
called with a catch that calls your logging facility (e.g., console.error or app
logger) and triggers a UI error/notification, referencing
handleInspectPromptSubmit, sessionComposerActions.appendDraft,
sessionComposerActions.addInspectedElement, handle.captureScreenshot,
attachScreenshotToComposer, and ensure clearPendingInspection(inspection) still
runs in finally.

664-666: Ref access during render — won't react to layout changes.

ESLint correctly flags that reading tabRefs.current during render violates the refs-outside-render guideline. While this approach gives you "fresh" bounds on each render, it won't trigger a re-render when the webview resizes (splitter drag, DevTools dock). The overlay could drift if the user resizes while the prompt is open.

If you want the overlay to stay anchored through layout changes, consider tracking bounds in state via a ResizeObserver:

♻️ Optional: reactive bounds via ResizeObserver
const [pendingInspectionBounds, setPendingInspectionBounds] = useState<Bounds | null>(null);

useEffect(() => {
  if (!pendingInspection) {
    setPendingInspectionBounds(null);
    return;
  }
  const handle = tabRefs.current.get(pendingInspection.tabId);
  if (!handle?.getWebviewBounds) return;
  
  // Initial read
  setPendingInspectionBounds(handle.getWebviewBounds());
  
  // Observe resize of the tab host container
  const ro = new ResizeObserver(() => {
    setPendingInspectionBounds(handle.getWebviewBounds());
  });
  if (tabHostEl) ro.observe(tabHostEl);
  return () => ro.disconnect();
}, [pendingInspection, tabHostEl]);

If layout-change drift is acceptable for this flow (prompt is typically short-lived), you can suppress with // eslint-disable-next-line react-hooks/refs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/features/browser/ui/BrowserPanel.tsx` around lines 664 - 666,
Reading tabRefs.current.get(...) during render (creating pendingInspectionBounds
from pendingInspection and tabRefs) violates refs-outside-render and won't
update on layout changes; instead, track bounds in state and update them with a
ResizeObserver inside an effect: create state pendingInspectionBounds via
useState, in a useEffect keyed on pendingInspection and tabHostEl read the
handle = tabRefs.current.get(pendingInspection.tabId), set initial bounds from
handle.getWebviewBounds(), and attach a ResizeObserver to tabHostEl that calls
setPendingInspectionBounds(handle.getWebviewBounds()) on resize (cleanup
disconnect on unmount); alternatively, if drift is acceptable, explicitly
suppress the lint rule with // eslint-disable-next-line react-hooks/refs.

657-662: ESLint flags setState inside effect — intentional synchronization, but consider restructuring.

The linter warns about calling clearPendingInspection (which calls setState) inside the effect body. While this pattern is technically a "sync effect" (responding to external state changes like tab switches or selector deactivation), it can cause cascading renders.

This is acceptable here since the setState is conditional and guards against redundant updates. To silence the lint error without changing behavior, you could wrap the call in a microtask:

♻️ Optional: defer to avoid lint warning
   useEffect(() => {
     if (!pendingInspection) return;
     if (pendingInspection.tabId !== activeTabId || !activeSelectorActive) {
-      clearPendingInspection(pendingInspection);
+      queueMicrotask(() => clearPendingInspection(pendingInspection));
     }
   }, [pendingInspection, activeTabId, activeSelectorActive, clearPendingInspection]);

Alternatively, you could add an eslint-disable comment if the current synchronous behavior is preferred.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/features/browser/ui/BrowserPanel.tsx` around lines 657 - 662,
The useEffect is calling clearPendingInspection (which triggers setState)
directly causing an ESLint warning; to silence the lint while preserving
behavior, defer the call to clearPendingInspection by wrapping it in a microtask
(e.g., Promise.resolve().then(() => clearPendingInspection(pendingInspection)))
inside the existing useEffect that depends on pendingInspection, activeTabId and
activeSelectorActive; keep the existing conditional (pendingInspection.tabId !==
activeTabId || !activeSelectorActive) and reference the same symbols (useEffect,
pendingInspection, activeTabId, activeSelectorActive, clearPendingInspection) so
renders are unchanged but the linter warning is resolved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/web/src/features/browser/ui/BrowserPanel.tsx`:
- Around line 594-647: The try/finally in handleInspectPromptSubmit swallows
errors from sessionComposerActions.appendDraft,
sessionComposerActions.addInspectedElement, handle.captureScreenshot, or
attachScreenshotToComposer so failures are silent; update the handler to catch
errors, log them (include operation context and inspection ref/tabId) and
surface a user-visible error (or rethrow) before the finally clears the
inspection. Specifically wrap the body where
appendDraft/addInspectedElement/captureScreenshot/attachScreenshotToComposer are
called with a catch that calls your logging facility (e.g., console.error or app
logger) and triggers a UI error/notification, referencing
handleInspectPromptSubmit, sessionComposerActions.appendDraft,
sessionComposerActions.addInspectedElement, handle.captureScreenshot,
attachScreenshotToComposer, and ensure clearPendingInspection(inspection) still
runs in finally.
- Around line 664-666: Reading tabRefs.current.get(...) during render (creating
pendingInspectionBounds from pendingInspection and tabRefs) violates
refs-outside-render and won't update on layout changes; instead, track bounds in
state and update them with a ResizeObserver inside an effect: create state
pendingInspectionBounds via useState, in a useEffect keyed on pendingInspection
and tabHostEl read the handle = tabRefs.current.get(pendingInspection.tabId),
set initial bounds from handle.getWebviewBounds(), and attach a ResizeObserver
to tabHostEl that calls setPendingInspectionBounds(handle.getWebviewBounds()) on
resize (cleanup disconnect on unmount); alternatively, if drift is acceptable,
explicitly suppress the lint rule with // eslint-disable-next-line
react-hooks/refs.
- Around line 657-662: The useEffect is calling clearPendingInspection (which
triggers setState) directly causing an ESLint warning; to silence the lint while
preserving behavior, defer the call to clearPendingInspection by wrapping it in
a microtask (e.g., Promise.resolve().then(() =>
clearPendingInspection(pendingInspection))) inside the existing useEffect that
depends on pendingInspection, activeTabId and activeSelectorActive; keep the
existing conditional (pendingInspection.tabId !== activeTabId ||
!activeSelectorActive) and reference the same symbols (useEffect,
pendingInspection, activeTabId, activeSelectorActive, clearPendingInspection) so
renders are unchanged but the linter warning is resolved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cf328277-8c19-4920-8c73-567941fd381c

📥 Commits

Reviewing files that changed from the base of the PR and between ab0d62e and 19cdb2f.

📒 Files selected for processing (2)
  • apps/web/src/features/browser/ui/BrowserPanel.tsx
  • apps/web/src/features/session/ui/PastedImageCard.tsx

@zvadaadam

zvadaadam commented Apr 23, 2026

Copy link
Copy Markdown
Owner Author

Greenlight — Round 2

Fixed (2): stale inspect selections are now invalidated when the webview viewport changes, so the prompt cannot submit against a reflowed page; Escape in the inspect prompt now dismisses the prompt without also exiting browser focus mode.
Disagreed (0): none.
Deferred (0): none.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/features/browser/ui/BrowserPanel.tsx`:
- Around line 574-584: The handleElementSelected callback is referencing
setPendingInspectionBounds before its hook is declared, violating React hooks
ordering; move the useState declaration for pendingInspectionBounds (the
useState<Bounds | null>(null) that returns [pendingInspectionBounds,
setPendingInspectionBounds]) so it appears above the handleElementSelected
function definition, ensuring setPendingInspectionBounds is declared before
being captured by handleElementSelected and keeping existing behavior of
setPendingInspection and nextInspectionIdRef.current increment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 98aacf76-2bdb-4dc3-885a-d249659dd902

📥 Commits

Reviewing files that changed from the base of the PR and between 19cdb2f and be826b9.

📒 Files selected for processing (2)
  • apps/web/src/features/browser/ui/BrowserPanel.tsx
  • apps/web/src/features/browser/ui/InspectPromptOverlay.tsx

Comment thread apps/web/src/features/browser/ui/BrowserPanel.tsx
@zvadaadam

Copy link
Copy Markdown
Owner Author

Greenlight — Round 3

Fixed (0): none.
Disagreed (1): the new setPendingInspectionBounds comment is a false positive; the callback closes over the setter but does not access it during initialization, and local lint/typecheck are clean.
Deferred (0): none.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/desktop/preload/browser-preload.ts`:
- Around line 52-59: The keydown handler in browser-preload.ts should ignore
repeated keydown events so Cmd/Ctrl+Shift+D (inspect toggle) doesn't flip twice;
add a guard that returns early when e.repeat is true before deciding and routing
the shortcut (the handler block that computes `meta`, `shortcut` and `key`),
ensuring the repeat check runs prior to setting or sending the
`"toggle-inspect-mode"` shortcut.

In `@apps/web/src/features/browser/ui/BrowserPanel.tsx`:
- Line 74: The tooltip always shows a macOS glyph string but the keyboard
handler supports Ctrl+Shift+D on Windows/Linux; change the INSPECT_SHORTCUT
constant to be platform-aware (e.g., detect macOS via navigator.platform or
navigator.userAgent and set INSPECT_SHORTCUT = "⌘⇧D" for macOS else "Ctrl⇧D")
and replace any hard-coded usages with that constant (referenced symbol:
INSPECT_SHORTCUT) so all tooltip locations (including the other places flagged)
display the correct shortcut per OS.
- Around line 76-78: The inspect shortcut is being retriggered on held keys
because repeated keydown events aren't filtered; update isInspectShortcut to
ignore auto-repeats by returning false when the KeyboardEvent.repeat flag is
true (i.e., check e.repeat) in addition to the existing modifiers and key checks
so holding Cmd/Ctrl+Shift+D won't flip inspect mode repeatedly; modify the
isInspectShortcut function to include this repeat check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2013d7a4-a3f0-4e29-b9f9-fd8928981c73

📥 Commits

Reviewing files that changed from the base of the PR and between be826b9 and 22ac027.

📒 Files selected for processing (5)
  • apps/desktop/preload/browser-preload.ts
  • apps/web/src/features/browser/types.ts
  • apps/web/src/features/browser/ui/BrowserPanel.tsx
  • apps/web/src/features/browser/ui/BrowserTab.tsx
  • apps/web/src/features/browser/ui/InspectPromptOverlay.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/features/browser/types.ts

Comment thread apps/desktop/preload/browser-preload.ts
Comment thread apps/web/src/features/browser/ui/BrowserPanel.tsx Outdated
Comment thread apps/web/src/features/browser/ui/BrowserPanel.tsx

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/features/session/lib/parseInspectTags.ts`:
- Around line 65-71: normalizeInspectMarkup is decoding `&gt;` globally which
turns serialized attribute values (e.g. `path="body &gt; div"`) into raw `>`
before tagRegex runs and also mutates plain-text; remove the final
.replace(/&gt;/g, ">") so only the inspect tag markers are unescaped (keep the
.replace(/&lt;(\/?)inspect/g, "<$1inspect") and the specific
.replace(/&lt;\/inspect&gt;/g, "</inspect>")), ensuring `&gt;` remains encoded
in the source string and letting unescapeAttr handle decoding after tagRegex
matches the tag.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 97a0035c-99af-43aa-9987-83e1d3788d57

📥 Commits

Reviewing files that changed from the base of the PR and between 22ac027 and ffcad9c.

📒 Files selected for processing (4)
  • apps/backend/src/services/gh.service.ts
  • apps/backend/test/unit/services/gh.service.test.ts
  • apps/web/src/features/session/lib/parseInspectTags.ts
  • apps/web/src/features/session/ui/blocks/TextBlock.tsx

Comment thread apps/web/src/features/session/lib/parseInspectTags.ts Outdated
@zvadaadam

Copy link
Copy Markdown
Owner Author

Greenlight — Round 2

Fixed (4): ignored key-repeat for guest shortcut forwarding, ignored key-repeat for host shortcut handling, made the inspect shortcut label platform-aware, and fixed escaped inspect tag parsing so encoded attribute/text values stay intact until unescape.

Already addressed / stale (2): live inspect prompt bounds were already handled via pendingInspectionBounds refresh, and PastedImageCard non-exempt colors are already tokenized.

Disagreed (1): setPendingInspectionBounds declaration-order concern is a false positive; the callback only closes over the setter and typecheck passes.

Validation: bun run typecheck; focused eslint for parser/preload; raw + escaped inspect parser smoke test.

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