Skip to content

Add AppPopup window system; move pickers, menus, and Resource usage into it#424

Merged
Cheggin merged 5 commits into
mainfrom
fix/app-popup-system
May 9, 2026
Merged

Add AppPopup window system; move pickers, menus, and Resource usage into it#424
Cheggin merged 5 commits into
mainfrom
fix/app-popup-system

Conversation

@Cheggin
Copy link
Copy Markdown
Collaborator

@Cheggin Cheggin commented May 9, 2026

Summary

  • Adds a shared, always-on-top popup window (panel-type Electron window at screen-saver level) with anchoring/placement helpers, IPC bridge, and a renderer that dispatches on a kind field. Wired into shell, pill, and logs preloads.
  • Moves the engine picker and BrowserCode model picker into it. For the BrowserCode submenu, replaces the right-side hover flyout with a drill-in pattern (single panel, back button, no L-shape).
  • Moves Sidebar, AgentPane, and LogsApp menus into it.
  • Moves the Resource usage indicator into it. Previously the Automating pill window was z-ordered above the in-shell dropdown and covered it; now the panel renders in a popup window at the same z-level as the pill.
  • Fix popup measurement to ignore scroll-clipped descendants so the window sizes to actual content.

Test plan

  • Open engine picker; click BrowserCode; confirm it drills in (back button + provider list) instead of opening a side flyout.
  • Confirm engine picker, BrowserCode model picker, sidebar/agent-pane/logs menus all open as anchored popups, click-outside dismisses, Esc dismisses.
  • With Automating pill visible, open Resource usage; confirm it stacks above the pill.
  • Resize/move shell window with a popup open; confirm it follows or closes appropriately.
  • cd app && npx vitest run (380 tests).
  • cd app && npx tsc --noEmit.

Summary by cubic

Adds a shared, always-on-top AppPopup window with anchoring and IPC, and moves engine/model pickers, menus, and Resource usage into it. Also hardens the popup lifecycle to avoid stale listeners and dropped handshakes, and ensures menus render with complete data.

  • New Features

    • Shared popup window (panel-type Electron window at screen-saver level) with anchor/placement helpers, IPC bridge, and a renderer that dispatches by request kind; wired into shell, pill, and logs preloads.
    • Engine picker and BrowserCode model picker now render in the popup; BrowserCode submenu switches to a single-panel drill-in with a back button.
    • Sidebar, AgentPane, and LogsApp menus open as anchored popups with click-outside/Esc to dismiss and follow/close on shell move/resize.
    • Added dedicated popup renderer and preload; introduced window.electronAPI.popup bridge and shared helpers.
  • Bug Fixes

    • Resource usage panel now stacks above the Automating pill (moved into the popup window).
    • Popup measurement ignores scroll-clipped descendants so windows size to actual content.
    • Prevent stale global listeners on fast close/open by tracking a disposed state.
    • Key popup content by request.id to remount per open and reset internal state.
    • Logs "Open in..." menu waits for editor discovery before opening.
    • Ensure renderer-ready handshake isn’t dropped when warming the popup.

Written for commit 6aa64f7. Summary will update on new commits.

Cheggin added 4 commits May 9, 2026 13:28
Introduce a shared, always-on-top popup window (panel-type Electron window
at screen-saver level) with anchoring/placement helpers, an IPC bridge,
and a renderer that dispatches on a request 'kind'. Wire the bridge into
shell, pill, and logs preloads so any window can open anchored popups.

This replaces ad-hoc inline dropdowns and native context menus with a
uniform mechanism that stacks above other floating windows (like the
Automating pill).
Render the engine picker and the BrowserCode model picker inside the
shared popup window instead of inline dropdowns so they stack above
other floating windows and share menu chrome.

For the BrowserCode submenu, replace the right-side hover flyout with a
drill-in: clicking BrowserCode swaps the engine list for the provider
list with a back button, keeping a single panel and consistent styling
instead of two disconnected floating boxes.
Replace inline dropdowns and native context menus in the sidebar,
agent pane, and logs view with anchored popup-window menus so they
match the shared menu chrome and stack predictably above other
floating windows.
The Resource usage panel was rendered as an in-shell DOM dropdown, so
the always-on-top Automating pill window was z-ordered above it and
covered it. Render the panel content inside the shared popup window
(screen-saver level) so it stacks above the pill.

The popup uses plain useEffect-based polling instead of useQuery since
the popup window does not host a QueryClientProvider.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

4 issues found across 27 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/src/renderer/shared/appPopup.ts">

<violation number="1" location="app/src/renderer/shared/appPopup.ts:79">
P2: Guard delayed listener attachment so disposed popups do not attach stale global handlers.</violation>
</file>

<file name="app/src/renderer/popup/AppPopup.tsx">

<violation number="1" location="app/src/renderer/popup/AppPopup.tsx:162">
P2: Popup content is reused across opens, so internal menu state can leak between sessions. Force a remount per popup request to reset drill-in state and rerun mount-time data fetches.</violation>
</file>

<file name="app/src/renderer/logs/LogsApp.tsx">

<violation number="1" location="app/src/renderer/logs/LogsApp.tsx:102">
P2: The menu items are generated from a potentially stale empty `editors` snapshot, so opening the popup before editor discovery finishes can hide all "Open in ..." actions until reopen.</violation>
</file>

<file name="app/src/main/index.ts">

<violation number="1" location="app/src/main/index.ts:295">
P2: Register the popup IPC handlers before warming the popup window, otherwise early launches can drop the renderer-ready handshake and leave popups stuck.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread app/src/renderer/shared/appPopup.ts
Comment thread app/src/renderer/popup/AppPopup.tsx
Comment thread app/src/renderer/logs/LogsApp.tsx
Comment thread app/src/main/index.ts
createPillWindow();
// Create logs overlay window (hidden) and anchor it to the hub
createLogsWindow();
warmAppPopup();
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 9, 2026

Choose a reason for hiding this comment

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

P2: Register the popup IPC handlers before warming the popup window, otherwise early launches can drop the renderer-ready handshake and leave popups stuck.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/src/main/index.ts, line 295:

<comment>Register the popup IPC handlers before warming the popup window, otherwise early launches can drop the renderer-ready handshake and leave popups stuck.</comment>

<file context>
@@ -291,6 +292,7 @@ function openShellAndWire(): BrowserWindow {
   createPillWindow();
   // Create logs overlay window (hidden) and anchor it to the hub
   createLogsWindow();
+  warmAppPopup();
   attachLogsToHub(shellWindow);
   mainLogger.info('main.tray.beforeCreate', { typeofCreateTray: typeof createTray });
</file context>
Fix with Cubic

- appPopup.ts: track a disposed flag so the deferred listener-attach
  setTimeout(0) does not register stale global handlers when a popup is
  closed before the listeners get a chance to mount.
- AppPopup.tsx: key inner content components by request.id so each open
  remounts and resets internal state (drill-in, fetched data) instead
  of leaking it across opens.
- LogsApp.tsx: await getEditors() before opening the file menu so the
  popup always shows the discovered editors instead of an empty
  snapshot when the user clicks before discovery resolves.
- main/appPopup.ts: warmAppPopup self-invokes registerAppPopupHandlers
  so the renderer-ready handshake cannot be dropped if a future caller
  warms the popup before the handlers are wired.
@Cheggin Cheggin merged commit c744257 into main May 9, 2026
10 checks passed
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