feat: per-panel zoom system#9
Conversation
…d panel close Replace scattered keydown listeners with a ShortcutManager singleton that handles platform-aware modifier normalization (Cmd/Ctrl) and provides a useShortcut React hook for component-scoped registration. Migrate existing Cmd+Shift+T (new terminal) shortcut and add Cmd+B (sidebar toggle) and Cmd+W (close active panel). Also add @electron/rebuild with postinstall script to fix node-pty posix_spawnp errors from ABI mismatch. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… tree Replace planned chokidar integration with @parcel/watcher (same library VS Code uses) for reliable macOS file watching. Native C++ FSEvents integration with ignore patterns processed at the OS level — no more CPU spikes or crashes from scanning node_modules/.git. Adds right-click context menu on file tree items with New File, New Folder, Rename (inline input), Delete (with confirmation), Copy Path, and Reveal in Finder. File watcher provides incremental tree updates with debounced event batching (150ms normal, 500ms for bulk operations). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Note cmux-inspired panel header buttons for new terminal, new browser, and split operations in the Tiling Pane System section. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix three production-only issues where the packaged .dmg rendered differently from pnpm dev: 1. CSP under file:// protocol — move Content-Security-Policy from HTML meta tag to Electron session headers so 'self' resolves correctly for both http:// and file:// origins. 2. Dockview CSS cascade — strip dockview's runtime styleInject() via a Vite plugin so the manually imported CSS (with our theme overrides) is the single source of truth. Dockview's JS was injecting a <style> tag after our <link>, causing equal-specificity rules to win and override .dockview-theme-aide variables. 3. CodeMirror light theme — add a complete Atom One Light theme (editor chrome + syntax highlighting) so the editor matches the shell UI in light mode instead of falling back to bare defaults. Also adds error handling and validation to theme IPC in useTheme.ts. Closes #2, closes #3 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move all state reads into the setNodes functional updater so toggleExpand never references the captured nodes closure. Add a loadingPaths ref to guard against concurrent directory loads on rapid clicks, and remove nodes from the dependency array since it is no longer referenced. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The @parcel/watcher native addon was ABI-incompatible with Electron 41, causing napi_fatal_error on startup that crashed the main process and broke terminal spawning. Replace with Node.js built-in fs.watch (recursive mode) which uses macOS FSEvents natively without a native addon. Also add cwd existence check in ptyManager to prevent posix_spawnp failures from stale workspace paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…hting Implement milestone 2.5 — side-by-side markdown preview in Dockview with live editor content via editorContentBus pub/sub, marked v17 + DOMPurify for XSS-safe rendering, and highlight.js for code block syntax highlighting mapped to aIDE theme CSS variables. Includes Cmd+Shift+V toggle shortcut, toast notification on .md file open, and auto-close on editor tab close. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… filter Integrate simple-git to poll git status every 3s and display colored file status badges (M/A/U/D) in the file tree with filename tinting. Replace hardcoded branch name in StatusBar with live git branch. Add search/filter input to sidebar that narrows the file tree by substring match with ancestor directory auto-expansion. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…imming Virtualize file tree with @tanstack/react-virtual for large directory performance (22px fixed rows, 15-item overscan, memoized DFS into VirtualRow[] union type). Replace generic file/folder icons with Seti-style colored SVG icons (~30 file types, ~15 special folders). Add gitignored file dimming via git ls-files with 0.4 opacity and italic text styling. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…egration Add worktree sidebar panel to create, remove, and switch between git worktrees. File tree re-roots on worktree switch, terminals can switch cwd via right-click context menu, and externally created worktrees are auto-detected via 5s polling. Sidebar refactored into collapsible SidebarSection components. New IPC channels and worktreeManager backend following the gitStatus.ts polling pattern. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…segmented toggle Add VS Code-style active item accent border, inline hover action buttons (terminal + more), "M" dirty badge with pulse animation, context menu icons, segmented toggle replacing checkbox in create modal, CSS spinner and success flash on submit, entry slide-in animations, empty state guidance, and list-integrated add button. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…batching React 18 may defer functional updaters when other state updates are batched, causing needsLoad/nodeDepth variables set inside setNodes() to be unreliable when checked outside. Read node state directly instead. Also fix dev tools menu crash with BaseWindow + WebContentsView by replacing role: 'toggleDevTools' with a manual handler. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Conflicted files were incorrectly mapped to 'M' (modified), hiding merge conflict state. Add distinct 'C' status to GitFileStatus union and update the file tree UI to display conflicts with error styling. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add --text-on-accent CSS variable to both theme definitions and replace all hardcoded #fff color values on accent backgrounds across modal, toast, context-menu, and worktree-panel styles to support future custom themes with light accent colors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Check that saved workspace and worktree paths exist on disk before starting file watcher and git polling at launch. Clears stale paths from the store if the directory no longer exists. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
clearContent was deleting the listener set along with cached content, which could orphan active subscriptions (e.g. markdown preview) and prevent them from receiving future updates. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…preview Add cancellation guard and re-check in-memory content before applying disk-read result, avoiding a race where a slow readFile response could overwrite newer editor updates. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevent anchor clicks in the markdown preview from navigating the Electron renderer. Links are now intercepted and routed through the app actions openUrl system, ready for future browser pane integration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Docstrings generation was requested by @Cheezeiii365. * #5 (comment) The following files were modified: * `packages/main/src/gitStatus.ts` * `packages/main/src/index.ts` * `packages/main/src/worktreeManager.ts` * `packages/renderer/src/components/AppShell.tsx` * `packages/renderer/src/components/DockviewContainer.tsx` * `packages/renderer/src/components/FileTree/FileTree.tsx` * `packages/renderer/src/components/FileTree/FileTreeItem.tsx` * `packages/renderer/src/components/FileTree/FileTypeIcon.tsx` * `packages/renderer/src/components/FileTree/fileIcons.ts` * `packages/renderer/src/components/Sidebar.tsx` * `packages/renderer/src/components/SidebarSection.tsx` * `packages/renderer/src/components/StatusBar.tsx` * `packages/renderer/src/components/Toast.tsx` * `packages/renderer/src/components/WorktreePanel/CreateWorktreeModal.tsx` * `packages/renderer/src/components/WorktreePanel/WorktreeItem.tsx` * `packages/renderer/src/components/WorktreePanel/WorktreePanel.tsx` * `packages/renderer/src/components/panes/EditorPane.tsx` * `packages/renderer/src/components/panes/MarkdownPreviewPane.tsx` * `packages/renderer/src/components/panes/TerminalPane.tsx` * `packages/renderer/src/hooks/useWorktrees.ts` * `packages/renderer/src/lib/editorContentBus.ts` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
… and worktree ideas Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nd shortcut wiring Central CommandRegistry replaces ad-hoc shortcuts as the single source of truth for all IDE actions. ShortcutManager enhanced with chord support and conflict detection. Reusable SearchPanel powers both the command palette (Cmd+Shift+P) and quick open (Cmd+P). Find-in-files (Cmd+Shift+F) uses bundled ripgrep with streaming results, replace mode, and jump-to-line. Remaining shortcuts wired: split editor, workspace placeholders, symbol search placeholder. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… resolution Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
File watcher was single-rooted — switching worktrees killed the old watcher, making changes in the original repo root invisible. EditorPane never subscribed to file watch events, so even detected changes were ignored. Rewrites fileWatcher.ts with a scopeId-keyed Map of watcher groups so multiple roots can be watched simultaneously. Worktree switching now watches both repo root and active worktree. Adds external change detection to EditorPane (auto- reload clean files, toast prompt for dirty files, deletion detection). The scopeId infrastructure prepares for Phase 4 cross-workspace file watching. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…it, task system
Phase A: .aide folder infrastructure
- aideInit.ts: idempotent .aide/ creation, project type detection, default settings
- settingsResolver.ts: three-layer settings cascade (project > user > defaults)
- Shared types: AideProjectSettings, ResolvedSettings, AideLocalWorkspace, ProjectType
Phase B: Gitignore security audit
- gitignoreAudit.ts: parse gitignore, check 22 security patterns, append with confirmation
- GitignoreReviewModal: grouped checkbox UI for selecting patterns to add
- Command palette integration and dismissal tracking
Phase B.5: Task system
- taskRunner.ts: load/validate tasks.json, spawn via node-pty, dependsOn graph,
compound tasks (parallel/sequence), auto-restart, timeout, user input prompts
- taskVariableResolver.ts: resolve ${workspaceRoot}, ${file}, ${branch}, ${input:id}, etc.
- problemMatcher.ts: 7 built-in matchers (tsc, eslint, python, gcc, go, pytest, generic)
- taskAutoDetect.ts: scan package.json/Cargo.toml/go.mod/etc. and offer to generate tasks.json
- useTasks hook, TaskInputModal, StatusBar task indicator, command palette commands
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract workspace serialization into a dedicated workspaceRuntimeSnapshots module that captures and caches layout, terminal, sidebar, and active panel state in memory. This enables instant restore on workspace switch without disk reads, consolidates save logic from AppShell/workspaceSwitcher/DockviewContainer, and fixes workspace close/remove to properly clean up task runners, watchers, and terminal state. Also adds resolveAppDefaults for blank workspaces without a rootPath. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Docstrings generation was requested by @Cheezeiii365. The following files were modified: * `packages/main/src/aideInit.ts` * `packages/main/src/fileWatcher.ts` * `packages/main/src/gitStatus.ts` * `packages/main/src/gitignoreAudit.ts` * `packages/main/src/index.ts` * `packages/main/src/problemMatcher.ts` * `packages/main/src/ptyManager.ts` * `packages/main/src/ripgrepSearch.ts` * `packages/main/src/settingsResolver.ts` * `packages/main/src/stateSerializer.ts` * `packages/main/src/taskAutoDetect.ts` * `packages/main/src/taskVariableResolver.ts` * `packages/main/src/worktreeManager.ts` * `packages/renderer/src/components/AppShell.tsx` * `packages/renderer/src/components/CommandPalette.tsx` * `packages/renderer/src/components/DockviewContainer.tsx` * `packages/renderer/src/components/FileTree/FileTree.tsx` * `packages/renderer/src/components/FileTree/FileTreeItem.tsx` * `packages/renderer/src/components/GitignoreReviewModal.tsx` * `packages/renderer/src/components/QuickOpen.tsx` * `packages/renderer/src/components/SearchPanel.tsx` * `packages/renderer/src/components/SidebarSection.tsx` * `packages/renderer/src/components/StatusBar.tsx` * `packages/renderer/src/components/TaskInputModal.tsx` * `packages/renderer/src/components/Toast.tsx` * `packages/renderer/src/components/WorkspaceContextMenu.tsx` * `packages/renderer/src/components/WorkspaceRibbon.tsx` * `packages/renderer/src/components/panes/EditorPane.tsx` * `packages/renderer/src/components/panes/FindInFilesPane.tsx` * `packages/renderer/src/components/panes/TerminalPane.tsx` * `packages/renderer/src/components/panes/WelcomePane.tsx` * `packages/renderer/src/hooks/useTasks.ts` * `packages/renderer/src/hooks/useWorkspaces.ts` * `packages/renderer/src/lib/CommandRegistry.ts` * `packages/renderer/src/lib/ContextKeys.ts` * `packages/renderer/src/lib/ShortcutManager.ts` * `packages/renderer/src/lib/editorContentBus.ts` * `packages/renderer/src/lib/editorDirtyState.ts` * `packages/renderer/src/lib/editorStateCache.ts` * `packages/renderer/src/lib/terminalState.ts` * `packages/renderer/src/lib/workspaceRuntimeSnapshots.ts` * `packages/renderer/src/lib/workspaceStateSerializer.ts` * `packages/renderer/src/lib/workspaceSwitcher.ts` These files were kept as they were: * `packages/renderer/src/components/FileTree/FileTypeIcon.tsx` * `packages/renderer/src/components/FileTree/fileIcons.ts` * `packages/renderer/src/components/Sidebar.tsx` * `packages/renderer/src/components/WorktreePanel/CreateWorktreeModal.tsx` * `packages/renderer/src/components/WorktreePanel/WorktreeItem.tsx` * `packages/renderer/src/components/WorktreePanel/WorktreePanel.tsx` * `packages/renderer/src/components/panes/MarkdownPreviewPane.tsx` * `packages/renderer/src/hooks/useWorktrees.ts` * `packages/renderer/src/lib/defaultCommands.ts` These files were ignored: * `tests/unit/app.test.tsx` These file types are not supported: * `.aide/.gitignore` * `.aide/settings.json` * `.aide/tasks.json` * `.gitignore` * `IDE_BUILD_PLAN.md` * `README.md` * `WORKSPACE_PLAN.md` * `electron-builder.yml` * `package.json` * `packages/renderer/src/styles/app-shell.css` * `packages/renderer/src/styles/find-in-files.css` * `packages/renderer/src/styles/gitignore-modal.css` * `packages/renderer/src/styles/search-panel.css` * `packages/renderer/src/styles/welcome-pane.css`
The settings resolver already merged exclude patterns from project, user, and built-in defaults, but the ripgrep search never read them. Now the SEARCH_START handler resolves settings and converts enabled exclude entries into --glob '!pattern' args so Find in Files actually respects filesExclude and searchExclude from .aide/settings.json. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a sequence-number cancellation pattern to prevent race conditions when rapid workspace switches cause overlapping activateWorkspace calls, which could leave watchers/pollers pointed at the wrong workspace root. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The pytest problem matcher was registered with line: 0, but createMatcherFromDef() returned null whenever lineNum === 0, making the matcher dead code. Make line optional in MatcherDef and TaskDiagnostic, and relax the guard to only require a non-empty file. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents the pty onExit callback from overwriting 'killed' status with 'succeeded'/'failed' and from auto-restarting tasks that were intentionally terminated (e.g. workspace switch, app quit, timeout). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verify that the text at each recorded position still matches before splicing, skipping stale hits instead of silently corrupting the file. Also fix handleReplaceAll to check per-file results instead of unconditionally clearing state. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…failures onExit removed executions from `this.running` before waitForCompletion could poll the terminal state, causing all finished tasks to resolve as exit code 0. This broke dependency chains and sequential compounds that rely on exit codes to abort on failure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a user cancels an input prompt or promptBefore confirmation, runSingle() returns a killed execution with an empty ptyId. Both the dependency loop and sequential compound loop only checked ptyId for failure, silently treating cancellations as success and continuing to run subsequent tasks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Files starting with a dot (e.g. .gitignore) returned the entire
filename as the extension because lastIndexOf('.') returned 0.
Change the guard from >= 0 to > 0 so dotfiles without a secondary
extension correctly return an empty string.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The totalFiles count was always reported as 0 because the Set was created empty at close time after fileMap had already been cleared by flush(). Use a running Set that accumulates file paths as matches arrive. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two fixes in taskAutoDetect: 1. Skip plain 'python' detection when 'python-pyproject' is also found, preventing duplicate task IDs (python:test, python:run). 2. Create .aide/ directory in generateTasksFile before writing, so callers that skip ensureAideFolder() (like TASK_GENERATE) don't hit ENOENT. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Confirm dialogs rendered both a Cancel and a No button, both calling handleCancel. Now confirm shows No/Yes and other types show Cancel/OK. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Check for 'error' in result before accessing result.missing, matching the pattern used by the aideInit and generateTasks handlers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
If appendToGitignore throws, the modal was stuck with a disabled button. Wrap in try/catch and reset submitting state on error. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a unified zoom system that lets each Dockview panel independently control its zoom level (0.5×–2×). Menu bar Cmd+=/Cmd+-/Cmd+0 zooms the active panel. Editor and terminal panes scale font size via CodeMirror compartment and xterm.js options. Browser panes use native webContents.setZoomFactor() with toolbar ±/readout controls. CSS-based panes (welcome, find-in-files, markdown preview, placeholder) use a --panel-zoom CSS variable. Zoom state is persisted per-panel in workspace runtime snapshots. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds per-panel zoom and browser-pane support: new main-process BrowserPaneManager and IPC, renderer BrowserPane UI and modal, zoom utilities and propagation to editor/terminal/CSS panes, workspace serialization of browser panes, tests, and related styles and shared types. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant AppShell as AppShell (Renderer)
participant Modal as NewBrowserPaneModal (Renderer)
participant Preload as Preload API
participant Main as Main Process
participant BPM as BrowserPaneManager
participant WebView as WebContentsView
User->>AppShell: Click "New Browser Pane"
AppShell->>Modal: show modal
User->>Modal: submit(sessionMode, url)
Modal->>AppShell: onSubmit(sessionMode, url)
AppShell->>Preload: browserCreate(paneId, workspaceId, sessionMode)
Preload->>Main: IPC BROWSER_CREATE
Main->>BPM: create(paneId, workspaceId, sessionMode)
BPM->>WebView: instantiate WebContentsView(session)
BPM-->>Main: create success
Main-->>Preload: IPC response
Preload-->>AppShell: promise resolves
AppShell->>AppShell: add Dockview panel (BrowserPane)
AppShell->>Preload: browserNavigate(paneId, url)
Preload->>Main: IPC BROWSER_NAVIGATE
Main->>BPM: navigate(paneId, url)
BPM->>WebView: loadURL(normalizedUrl)
WebView-->>BPM: navigation events (title, loading, did-navigate)
BPM->>Main: emit IPC events (BROWSER_DID_NAVIGATE, PAGE_TITLE_UPDATED, LOADING_CHANGED)
Main-->>Preload: IPC forward
Preload-->>AppShell: onBrowserDidNavigate/onBrowserTitleUpdated...
AppShell->>BrowserPane: update UI/state
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/renderer/src/lib/terminalState.ts (1)
54-68:⚠️ Potential issue | 🟠 MajorRestored terminal params currently reset zoom to 1×
Line 67 forces
zoomFactor: 1during restore, so restored terminal params cannot preserve a previously saved zoom value.Suggested fix
export function createRestoredTerminalPanelParams( terminalId: string, workspaceId?: string, worktreePath?: string, title?: string, shell?: string, + zoomFactor = 1, ): TerminalPanelParams { return { terminalId, workspaceId, worktreePath, title, shell, - zoomFactor: 1, + zoomFactor, } }You should also include
zoomFactorin serialized terminal state and in the sharedTerminalStatetype so this value can round-trip.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/renderer/src/lib/terminalState.ts` around lines 54 - 68, createRestoredTerminalPanelParams currently forces zoomFactor: 1 so restored terminals lose saved zoom; update the createRestoredTerminalPanelParams signature and return to accept and propagate a zoomFactor (do not hardcode 1) and ensure TerminalPanelParams includes zoomFactor, then add zoomFactor to the serialized terminal state and the shared TerminalState type so the value is included when serializing/deserializing/restoring terminals (update any serialize/deserialize or toJSON/fromJSON logic that handles terminal state to round-trip zoomFactor).packages/shared/src/index.ts (1)
321-329:⚠️ Potential issue | 🟠 MajorBrowser pane state is serialized but restoration logic is missing.
AideLocalState.browserPanesis persisted viaserializeBrowserPaneState()inworkspaceStateSerializer.ts(line 78), but the workspace restoration flow inworkspaceSwitcher.tshas no corresponding logic to read this field and recreate browser panels. The restoration process (lines 99-129) handles layout, sidebar, and active tab, butsavedState.browserPanesis never accessed. This means browser panes won't survive app restarts even though their state is saved.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/shared/src/index.ts` around lines 321 - 329, Saved browser pane state (AideLocalState.browserPanes) is serialized by serializeBrowserPaneState() but never restored; update the workspace restoration in workspaceSwitcher.ts to read savedState.browserPanes, iterate each BrowserPaneState and recreate the browser panels (via the existing panel creation/dispatch API used elsewhere) so persisted panes are rehydrated at startup; use the inverse of serializeBrowserPaneState (or a deserializer/helper) to convert stored entries back to BrowserPaneState and call the appropriate recreate/open function for each pane.
🧹 Nitpick comments (8)
tests/unit/panelZoom.test.ts (1)
1-16: Good test coverage for core functionality.The tests verify the essential behavior of
getPanelZoomFactorandupdatePanelZoomParams. Consider adding edge case tests for boundary values (0.5, 2.0 clamp limits) and overwriting an existingzoomFactor.💡 Optional: Additional test cases
it('extracts existing zoom factor from params', () => { expect(getPanelZoomFactor({ zoomFactor: 1.5 })).toBe(1.5) }) it('overwrites existing zoom factor', () => { expect(updatePanelZoomParams({ zoomFactor: 1.0 }, 1.5)).toEqual({ zoomFactor: 1.5, }) })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/unit/panelZoom.test.ts` around lines 1 - 16, Add unit tests to cover boundary clamping and overwriting behavior: add cases in tests/unit/panelZoom.test.ts that assert getPanelZoomFactor({ zoomFactor: 0.5 }) returns 0.5 and getPanelZoomFactor({ zoomFactor: 2.0 }) returns 2.0 (or that inputs outside allowed range are clamped if implementation does that), add a test that getPanelZoomFactor({ zoomFactor: 1.5 }) returns 1.5, and add a test that updatePanelZoomParams({ zoomFactor: 1.0 }, 1.5) returns an object with zoomFactor: 1.5 (confirming overwrite) as well as a test that updatePanelZoomParams({ filePath: '/tmp/test.ts', zoomFactor: 0.8 }, 2.0) updates zoomFactor to 2.0 while preserving other fields.tests/unit/workspaceStateSerializer.test.ts (1)
11-25: Consider adding test coverage for browser pane serialization.The test validates sidebar state but doesn't exercise the new
browserPanesserialization path added in this PR. Given thatserializeBrowserPaneStateis now called withinserializeWorkspaceState, a test case with mock browser pane panels would strengthen confidence in the integration.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/unit/workspaceStateSerializer.test.ts` around lines 11 - 25, Add a unit test that supplies a dockviewApi with one or more panels representing browser panes (e.g., panels containing type or view id that serializeBrowserPaneState expects) and an activePanel as needed, then call serializeWorkspaceState and assert that the returned object includes a browserPanes key with the expected serialized structure; specifically target serializeWorkspaceState and serializeBrowserPaneState so the test verifies browser pane serialization is exercised and the browserPanes shape matches the output from serializeBrowserPaneState.packages/renderer/src/lib/workspaceStateSerializer.ts (1)
15-27: Update JSDoc to document the newworkspaceIdparameter.The JSDoc block lists parameters but omits the newly added
workspaceId. This creates documentation drift.📝 Proposed JSDoc update
/** * Build an AideLocalState representing the current workspace layout, open editor tabs, active tab, and sidebar settings. * * `@param` dockviewApi - The Dockview API instance to read panels and layout from, or `null` if unavailable + * `@param` workspaceId - The workspace ID to filter browser panes by, or `null` if unavailable * `@param` sidebarWidth - The current sidebar width in pixels * `@param` sidebarCollapsed - Whether the sidebar is collapsed - * `@returns` The serialized AideLocalState with `layout`, `openTabs`, `activeTabPath`, `sidebarWidth`, `sidebarCollapsed`, and `sidebarSections` + * `@returns` The serialized AideLocalState with `layout`, `openTabs`, `activeTabPath`, `sidebarWidth`, `sidebarCollapsed`, `sidebarSections`, and `browserPanes` */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/renderer/src/lib/workspaceStateSerializer.ts` around lines 15 - 27, The JSDoc for serializeWorkspaceState is missing documentation for the newly added workspaceId parameter; update the comment block above function serializeWorkspaceState to include a new `@param` entry describing workspaceId (type and meaning—e.g., the current workspace identifier or null when unavailable) and ensure the `@returns` and existing param descriptions remain accurate and consistent with the function signature.packages/renderer/src/components/NewBrowserPaneModal.tsx (1)
40-48: Consider deriving session mode options from the type definition.The select options are hardcoded strings that must stay in sync with the
BrowserSessionModetype definition inpackages/shared/src/index.ts. If the type is extended with new modes, this component won't show them and TypeScript won't catch the omission.This is a minor maintainability concern for future changes.
♻️ Optional: Extract options to a shared constant
// In packages/shared/src/index.ts export const BROWSER_SESSION_MODES: readonly BrowserSessionMode[] = [ 'shared-auth', 'workspace', 'temporary', ] as const // In NewBrowserPaneModal.tsx import { BROWSER_SESSION_MODES } from '@aide/shared' // ... {BROWSER_SESSION_MODES.map((mode) => ( <option key={mode} value={mode}>{formatSessionMode(mode)}</option> ))}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/renderer/src/components/NewBrowserPaneModal.tsx` around lines 40 - 48, The select options in NewBrowserPaneModal are hardcoded and can get out of sync with the BrowserSessionMode type; introduce or import a single source-of-truth array (e.g., export const BROWSER_SESSION_MODES: readonly BrowserSessionMode[] from the shared package) and replace the hardcoded <option> elements by mapping over BROWSER_SESSION_MODES in NewBrowserPaneModal, using each mode as key/value and a small formatter (e.g., formatSessionMode) for display; update imports to bring in BROWSER_SESSION_MODES (and the formatter if created) and remove the literal strings so new modes added to BrowserSessionMode automatically appear.packages/shared/src/index.test.ts (1)
31-45: Consider adding edge case tests for zoom helpers.The current tests cover basic functionality, but consider adding tests for edge cases:
- Non-finite values (
NaN,Infinity)- Exact boundary values (
0.5,2.0)- Negative zoom factors
- Step direction at boundaries (e.g.,
stepZoomFactor(0.5, -1)should stay at 0.5)🧪 Suggested additional test cases
describe('zoom helpers', () => { it('clamps zoom factors into the supported range', () => { expect(clampZoomFactor(0.1)).toBe(0.5) expect(clampZoomFactor(3)).toBe(2) + expect(clampZoomFactor(0.5)).toBe(0.5) // exact min + expect(clampZoomFactor(2)).toBe(2) // exact max + expect(clampZoomFactor(NaN)).toBe(1) // non-finite fallback + expect(clampZoomFactor(-1)).toBe(0.5) // negative }) it('adjusts zoom factors in 10 percent increments', () => { expect(adjustZoomFactor(1, 0.1)).toBe(1.1) expect(stepZoomFactor(1.1, -1)).toBe(1) + expect(stepZoomFactor(0.5, -1)).toBe(0.5) // clamped at min + expect(stepZoomFactor(2, 1)).toBe(2) // clamped at max })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/shared/src/index.test.ts` around lines 31 - 45, Add unit tests for edge cases in the zoom helpers: add assertions for non-finite inputs (NaN and Infinity) passed to clampZoomFactor/adjustZoomFactor/zoomFactorToPercent to ensure they behave predictably, add tests using exact boundary values 0.5 and 2.0 for clampZoomFactor and stepZoomFactor to confirm they clamp correctly, add a test for a negative zoom factor (e.g., clampZoomFactor(-1) and adjustZoomFactor(-1, 0.1)) to verify handling, and add step-direction boundary tests such as stepZoomFactor(0.5, -1) and stepZoomFactor(2.0, 1) to assert they remain within bounds; reference the functions clampZoomFactor, adjustZoomFactor, stepZoomFactor, and zoomFactorToPercent when adding these cases.packages/renderer/src/components/panes/BrowserPane.tsx (2)
44-66: Unusedapiin dependency array.The
pushHostUpdatecallback includesapiin its dependency array (line 66) but doesn't use it in the function body. This causes unnecessary re-creation of the callback.♻️ Proposed fix
- }, [api, paneId, workspaceId]) + }, [paneId, workspaceId])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/renderer/src/components/panes/BrowserPane.tsx` around lines 44 - 66, The useCallback pushHostUpdate re-creates unnecessarily because its dependency array includes api which is not referenced inside the function; remove api from the dependency list so the hook depends only on paneId and workspaceId (and any refs) or alternatively use the api variable consistently inside pushHostUpdate instead of window.api to justify keeping it—update the dependency array for pushHostUpdate (function name) accordingly and ensure lastHostUpdateRef, hostRef and chromeRef remain accessed as refs rather than added to the dependencies.
119-129: Unusedapiin dependency array.Similar issue:
requestInitialLoadincludesapiin dependencies but only usescommitNavigation.♻️ Proposed fix
- }, [api, commitNavigation]) + }, [commitNavigation])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/renderer/src/components/panes/BrowserPane.tsx` around lines 119 - 129, The requestInitialLoad callback lists an unused dependency `api`, which can cause unnecessary re-creations; update the dependency array of requestInitialLoad to only include the actually used symbol(s) (e.g., change from [api, commitNavigation] to [commitNavigation]) so that requestInitialLoad (which references hostRef, paramsRef, browserReadyRef, initialLoadRequestedRef and calls commitNavigation) only re-renders when commitNavigation changes.packages/shared/src/index.ts (1)
346-353:zoomFactoris optional but always serialized.
BrowserPaneState.zoomFactoris marked optional (zoomFactor?: number), butserializeBrowserPaneState()inpackages/renderer/src/lib/browserState.tsalways includes it. Consider making it required for consistency, or document why it's optional (e.g., backwards compatibility with older persisted state).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/shared/src/index.ts` around lines 346 - 353, The BrowserPaneState interface declares zoomFactor as optional but serializeBrowserPaneState() always writes it; update one side for consistency: either make zoomFactor required on BrowserPaneState (remove the ? from zoomFactor) so serializeBrowserPaneState() and consumers can assume it exists, or change serializeBrowserPaneState() to only include zoomFactor when defined (and add a comment explaining backward-compatibility if needed); reference BrowserPaneState and serializeBrowserPaneState in your change so callers and persisted state handling are updated accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@browserPanes.md`:
- Around line 124-133: The fenced ASCII-art block is missing a language tag;
update the fence that begins with the ┌ box (the ASCII-art placeholder div
block) to include a language identifier (e.g., add ```text instead of ``` ) so
the Markdown linter rule MD040 is satisfied and the block is treated as plain
text.
In `@packages/main/src/browserPaneManager.ts`:
- Around line 32-41: The normalizeUrl function can still throw when the fallback
new URL(`https://${trimmed}`) is given a completely malformed input like "://";
update normalizeUrl to catch errors from the fallback attempt as well and return
a safe default (e.g., empty string) instead of letting an exception propagate.
Specifically, keep the initial trim and empty check, attempt new URL(trimmed) in
a try, and if that fails attempt new URL(`https://${trimmed}`) inside a second
try/catch (or a single try with nested catches) and return '' on any remaining
error; refer to the normalizeUrl function and the trimmed variable to locate the
change.
In `@packages/renderer/src/components/panes/EditorPane.tsx`:
- Around line 151-159: When restoring a cached editor state in the view.dispatch
block, detect whether the cached state already contains the
editorMetricsCompartment and use StateEffect.reconfigure (or the
compartment.reconfigure effect) in that case, otherwise use
StateEffect.appendConfig.of(...) as current code does; specifically, inspect the
cached state's extensions for editorMetricsCompartment (the compartment symbol)
and then call either a reconfigure effect with
getEditorMetricsExtension(Math.round(EDITOR_BASE_FONT_SIZE *
getPanelZoomFactor(params))) or
appendConfig.of([...editorMetricsCompartment.of(getEditorMetricsExtension(...))])
to avoid duplicating compartments or failing for older cached states.
In `@packages/renderer/src/lib/panelZoom.ts`:
- Around line 5-14: getPanelZoomFactor and updatePanelZoomParams currently
accept any numeric value; clamp zoom values to the 0.5–2.0 range and reject
non-finite numbers. In getPanelZoomFactor (function name) validate the extracted
zoomFactor is a finite number and return Math.min(2, Math.max(0.5, zoomFactor))
(or 1 if invalid). In updatePanelZoomParams (function name) clamp the provided
zoomFactor parameter to the same 0.5–2.0 bounds before merging it into the
returned object so saved/externally supplied values cannot break rendering.
---
Outside diff comments:
In `@packages/renderer/src/lib/terminalState.ts`:
- Around line 54-68: createRestoredTerminalPanelParams currently forces
zoomFactor: 1 so restored terminals lose saved zoom; update the
createRestoredTerminalPanelParams signature and return to accept and propagate a
zoomFactor (do not hardcode 1) and ensure TerminalPanelParams includes
zoomFactor, then add zoomFactor to the serialized terminal state and the shared
TerminalState type so the value is included when
serializing/deserializing/restoring terminals (update any serialize/deserialize
or toJSON/fromJSON logic that handles terminal state to round-trip zoomFactor).
In `@packages/shared/src/index.ts`:
- Around line 321-329: Saved browser pane state (AideLocalState.browserPanes) is
serialized by serializeBrowserPaneState() but never restored; update the
workspace restoration in workspaceSwitcher.ts to read savedState.browserPanes,
iterate each BrowserPaneState and recreate the browser panels (via the existing
panel creation/dispatch API used elsewhere) so persisted panes are rehydrated at
startup; use the inverse of serializeBrowserPaneState (or a deserializer/helper)
to convert stored entries back to BrowserPaneState and call the appropriate
recreate/open function for each pane.
---
Nitpick comments:
In `@packages/renderer/src/components/NewBrowserPaneModal.tsx`:
- Around line 40-48: The select options in NewBrowserPaneModal are hardcoded and
can get out of sync with the BrowserSessionMode type; introduce or import a
single source-of-truth array (e.g., export const BROWSER_SESSION_MODES: readonly
BrowserSessionMode[] from the shared package) and replace the hardcoded <option>
elements by mapping over BROWSER_SESSION_MODES in NewBrowserPaneModal, using
each mode as key/value and a small formatter (e.g., formatSessionMode) for
display; update imports to bring in BROWSER_SESSION_MODES (and the formatter if
created) and remove the literal strings so new modes added to BrowserSessionMode
automatically appear.
In `@packages/renderer/src/components/panes/BrowserPane.tsx`:
- Around line 44-66: The useCallback pushHostUpdate re-creates unnecessarily
because its dependency array includes api which is not referenced inside the
function; remove api from the dependency list so the hook depends only on paneId
and workspaceId (and any refs) or alternatively use the api variable
consistently inside pushHostUpdate instead of window.api to justify keeping
it—update the dependency array for pushHostUpdate (function name) accordingly
and ensure lastHostUpdateRef, hostRef and chromeRef remain accessed as refs
rather than added to the dependencies.
- Around line 119-129: The requestInitialLoad callback lists an unused
dependency `api`, which can cause unnecessary re-creations; update the
dependency array of requestInitialLoad to only include the actually used
symbol(s) (e.g., change from [api, commitNavigation] to [commitNavigation]) so
that requestInitialLoad (which references hostRef, paramsRef, browserReadyRef,
initialLoadRequestedRef and calls commitNavigation) only re-renders when
commitNavigation changes.
In `@packages/renderer/src/lib/workspaceStateSerializer.ts`:
- Around line 15-27: The JSDoc for serializeWorkspaceState is missing
documentation for the newly added workspaceId parameter; update the comment
block above function serializeWorkspaceState to include a new `@param` entry
describing workspaceId (type and meaning—e.g., the current workspace identifier
or null when unavailable) and ensure the `@returns` and existing param
descriptions remain accurate and consistent with the function signature.
In `@packages/shared/src/index.test.ts`:
- Around line 31-45: Add unit tests for edge cases in the zoom helpers: add
assertions for non-finite inputs (NaN and Infinity) passed to
clampZoomFactor/adjustZoomFactor/zoomFactorToPercent to ensure they behave
predictably, add tests using exact boundary values 0.5 and 2.0 for
clampZoomFactor and stepZoomFactor to confirm they clamp correctly, add a test
for a negative zoom factor (e.g., clampZoomFactor(-1) and adjustZoomFactor(-1,
0.1)) to verify handling, and add step-direction boundary tests such as
stepZoomFactor(0.5, -1) and stepZoomFactor(2.0, 1) to assert they remain within
bounds; reference the functions clampZoomFactor, adjustZoomFactor,
stepZoomFactor, and zoomFactorToPercent when adding these cases.
In `@packages/shared/src/index.ts`:
- Around line 346-353: The BrowserPaneState interface declares zoomFactor as
optional but serializeBrowserPaneState() always writes it; update one side for
consistency: either make zoomFactor required on BrowserPaneState (remove the ?
from zoomFactor) so serializeBrowserPaneState() and consumers can assume it
exists, or change serializeBrowserPaneState() to only include zoomFactor when
defined (and add a comment explaining backward-compatibility if needed);
reference BrowserPaneState and serializeBrowserPaneState in your change so
callers and persisted state handling are updated accordingly.
In `@tests/unit/panelZoom.test.ts`:
- Around line 1-16: Add unit tests to cover boundary clamping and overwriting
behavior: add cases in tests/unit/panelZoom.test.ts that assert
getPanelZoomFactor({ zoomFactor: 0.5 }) returns 0.5 and getPanelZoomFactor({
zoomFactor: 2.0 }) returns 2.0 (or that inputs outside allowed range are clamped
if implementation does that), add a test that getPanelZoomFactor({ zoomFactor:
1.5 }) returns 1.5, and add a test that updatePanelZoomParams({ zoomFactor: 1.0
}, 1.5) returns an object with zoomFactor: 1.5 (confirming overwrite) as well as
a test that updatePanelZoomParams({ filePath: '/tmp/test.ts', zoomFactor: 0.8 },
2.0) updates zoomFactor to 2.0 while preserving other fields.
In `@tests/unit/workspaceStateSerializer.test.ts`:
- Around line 11-25: Add a unit test that supplies a dockviewApi with one or
more panels representing browser panes (e.g., panels containing type or view id
that serializeBrowserPaneState expects) and an activePanel as needed, then call
serializeWorkspaceState and assert that the returned object includes a
browserPanes key with the expected serialized structure; specifically target
serializeWorkspaceState and serializeBrowserPaneState so the test verifies
browser pane serialization is exercised and the browserPanes shape matches the
output from serializeBrowserPaneState.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9e4e26b6-ed5a-4a50-864b-296ffcc6471c
📒 Files selected for processing (40)
IDE_BUILD_PLAN.mdLSPPLAN.mdbrowserPanes.mdpackages/main/src/browserPaneManager.tspackages/main/src/index.tspackages/main/src/preload.tspackages/renderer/src/components/AppShell.tsxpackages/renderer/src/components/DockviewContainer.tsxpackages/renderer/src/components/FileTree/FileTypeIcon.tsxpackages/renderer/src/components/NewBrowserPaneModal.tsxpackages/renderer/src/components/Sidebar.tsxpackages/renderer/src/components/panes/BrowserPane.tsxpackages/renderer/src/components/panes/EditorPane.tsxpackages/renderer/src/components/panes/FindInFilesPane.tsxpackages/renderer/src/components/panes/MarkdownPreviewPane.tsxpackages/renderer/src/components/panes/PlaceholderPane.tsxpackages/renderer/src/components/panes/TerminalPane.tsxpackages/renderer/src/components/panes/WelcomePane.tsxpackages/renderer/src/lib/browserState.tspackages/renderer/src/lib/defaultCommands.tspackages/renderer/src/lib/editorTheme.tspackages/renderer/src/lib/panelZoom.tspackages/renderer/src/lib/terminalState.tspackages/renderer/src/lib/workspaceRuntimeSnapshots.tspackages/renderer/src/lib/workspaceStateSerializer.tspackages/renderer/src/styles/app-shell.csspackages/renderer/src/styles/browser-pane.csspackages/renderer/src/styles/dockview-theme.csspackages/renderer/src/styles/file-tree.csspackages/renderer/src/styles/find-in-files.csspackages/renderer/src/styles/markdown-preview.csspackages/renderer/src/styles/welcome-pane.csspackages/shared/src/index.test.tspackages/shared/src/index.tspackages/shared/src/zoom.tstests/unit/app.test.tsxtests/unit/browserState.test.tstests/unit/editorTheme.test.tstests/unit/panelZoom.test.tstests/unit/workspaceStateSerializer.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{css,scss,tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CSS variable token system with
data-themeattribute for theming, supporting dark and light mode
Files:
packages/renderer/src/lib/workspaceRuntimeSnapshots.tspackages/renderer/src/components/FileTree/FileTypeIcon.tsxpackages/renderer/src/components/DockviewContainer.tsxpackages/renderer/src/styles/dockview-theme.csspackages/renderer/src/lib/defaultCommands.tspackages/renderer/src/components/panes/PlaceholderPane.tsxpackages/renderer/src/components/Sidebar.tsxtests/unit/panelZoom.test.tstests/unit/editorTheme.test.tspackages/renderer/src/styles/file-tree.csspackages/renderer/src/styles/welcome-pane.csspackages/renderer/src/styles/app-shell.csspackages/renderer/src/components/panes/TerminalPane.tsxtests/unit/browserState.test.tspackages/renderer/src/styles/markdown-preview.csspackages/renderer/src/components/panes/EditorPane.tsxpackages/renderer/src/lib/workspaceStateSerializer.tspackages/renderer/src/styles/browser-pane.csstests/unit/workspaceStateSerializer.test.tspackages/renderer/src/lib/terminalState.tspackages/renderer/src/lib/panelZoom.tspackages/shared/src/index.test.tstests/unit/app.test.tsxpackages/renderer/src/styles/find-in-files.csspackages/renderer/src/components/NewBrowserPaneModal.tsxpackages/renderer/src/lib/editorTheme.tspackages/main/src/index.tspackages/renderer/src/components/panes/MarkdownPreviewPane.tsxpackages/shared/src/zoom.tspackages/renderer/src/lib/browserState.tspackages/renderer/src/components/panes/FindInFilesPane.tsxpackages/renderer/src/components/panes/WelcomePane.tsxpackages/renderer/src/components/panes/BrowserPane.tsxpackages/main/src/browserPaneManager.tspackages/renderer/src/components/AppShell.tsxpackages/main/src/preload.tspackages/shared/src/index.ts
**/*editor*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CodeMirror 6 for editor implementation (not Monaco)
Files:
tests/unit/editorTheme.test.tspackages/renderer/src/lib/editorTheme.ts
🧠 Learnings (6)
📚 Learning: 2026-03-25T11:00:59.388Z
Learnt from: Cheezeiii365
Repo: Cheezeiii365/aIDE PR: 4
File: packages/renderer/src/components/FileTree/ContextMenu.tsx:16-20
Timestamp: 2026-03-25T11:00:59.388Z
Learning: Since aIDE does not support Windows, path-handling utilities and related code should assume POSIX-style separators (`/`) (e.g., helpers like `dirname`/`basename` that split on `/`). During review, do not require Windows-style backslash (`\\`) support or `path.sep`/cross-platform normalization unless the project explicitly adds Windows support.
Applied to files:
packages/renderer/src/lib/workspaceRuntimeSnapshots.tspackages/renderer/src/components/FileTree/FileTypeIcon.tsxpackages/renderer/src/components/DockviewContainer.tsxpackages/renderer/src/lib/defaultCommands.tspackages/renderer/src/components/panes/PlaceholderPane.tsxpackages/renderer/src/components/Sidebar.tsxpackages/renderer/src/components/panes/TerminalPane.tsxpackages/renderer/src/components/panes/EditorPane.tsxpackages/renderer/src/lib/workspaceStateSerializer.tspackages/renderer/src/lib/terminalState.tspackages/renderer/src/lib/panelZoom.tspackages/shared/src/index.test.tspackages/renderer/src/components/NewBrowserPaneModal.tsxpackages/renderer/src/lib/editorTheme.tspackages/main/src/index.tspackages/renderer/src/components/panes/MarkdownPreviewPane.tsxpackages/shared/src/zoom.tspackages/renderer/src/lib/browserState.tspackages/renderer/src/components/panes/FindInFilesPane.tsxpackages/renderer/src/components/panes/WelcomePane.tsxpackages/renderer/src/components/panes/BrowserPane.tsxpackages/main/src/browserPaneManager.tspackages/renderer/src/components/AppShell.tsxpackages/main/src/preload.tspackages/shared/src/index.ts
📚 Learning: 2026-03-25T11:11:52.630Z
Learnt from: CR
Repo: Cheezeiii365/aIDE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-25T11:11:52.630Z
Learning: Applies to **/*layout*.{ts,tsx} : Use Dockview 5.x for layout and tiling panes
Applied to files:
packages/renderer/src/components/DockviewContainer.tsxpackages/renderer/src/styles/dockview-theme.csspackages/renderer/src/components/panes/PlaceholderPane.tsxpackages/renderer/src/components/panes/TerminalPane.tsxpackages/renderer/src/components/panes/EditorPane.tsxpackages/renderer/src/lib/workspaceStateSerializer.tsIDE_BUILD_PLAN.mdpackages/renderer/src/lib/browserState.tspackages/renderer/src/components/panes/WelcomePane.tsxpackages/renderer/src/components/panes/BrowserPane.tsxpackages/renderer/src/components/AppShell.tsx
📚 Learning: 2026-03-25T11:11:52.630Z
Learnt from: CR
Repo: Cheezeiii365/aIDE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-25T11:11:52.630Z
Learning: Always check against the .gitignore file when committing for security and performance reasons
Applied to files:
packages/renderer/src/lib/defaultCommands.ts
📚 Learning: 2026-03-25T11:11:52.630Z
Learnt from: CR
Repo: Cheezeiii365/aIDE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-25T11:11:52.630Z
Learning: Applies to **/*.{css,scss,tsx,ts} : Use CSS variable token system with `data-theme` attribute for theming, supporting dark and light mode
Applied to files:
packages/renderer/src/styles/welcome-pane.csspackages/renderer/src/styles/markdown-preview.csspackages/renderer/src/styles/find-in-files.csspackages/renderer/src/lib/editorTheme.ts
📚 Learning: 2026-03-25T11:11:52.630Z
Learnt from: CR
Repo: Cheezeiii365/aIDE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-25T11:11:52.630Z
Learning: Applies to **/*editor*.{ts,tsx} : Use CodeMirror 6 for editor implementation (not Monaco)
Applied to files:
packages/renderer/src/components/panes/EditorPane.tsxpackages/renderer/src/lib/editorTheme.ts
📚 Learning: 2026-03-25T11:11:52.630Z
Learnt from: CR
Repo: Cheezeiii365/aIDE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-25T11:11:52.630Z
Learning: Always update IDE_BUILD_PLAN.md when making changes to the codebase
Applied to files:
IDE_BUILD_PLAN.mdLSPPLAN.md
🪛 LanguageTool
LSPPLAN.md
[style] ~47-~47: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...esses should not run in the renderer. - LSP server runtime should be workspace-scop...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~195-~195: Ensure spelling is correct
Context: ...tion Use a plain folder format with an aIDE-specific manifest. Example shape: ```...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~568-~568: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: .... Add LSP-backed hover integration. 16. Add definition/symbol request plumbing. 17....
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~569-~569: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...definition/symbol request plumbing. 17. Add a shared diagnostics store and editor d...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~698-~698: Ensure spelling is correct
Context: ...tory be on each platform? 2. How should aIDE represent pack health states in the UI ...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🪛 markdownlint-cli2 (0.22.0)
browserPanes.md
[warning] 124-124: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🪛 Stylelint (17.5.0)
packages/renderer/src/styles/welcome-pane.css
[error] 3-3: Expected empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
packages/renderer/src/styles/app-shell.css
[error] 319-319: Expected empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
packages/renderer/src/styles/markdown-preview.css
[error] 3-3: Expected empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
packages/renderer/src/styles/find-in-files.css
[error] 5-5: Expected empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🔇 Additional comments (50)
packages/renderer/src/lib/defaultCommands.ts (1)
123-131: LGTM! Correctly removes dead code.The previous
'error' in resultcheck was unreachable sinceGitignoreAuditResult(defined inpackages/shared/src/index.ts) only containsmissingandtotalproperties—never anerrorfield. The backendauditGitignorethrows on I/O failures rather than returning error objects, so this simplification correctly aligns the runtime behavior with the type system.LSPPLAN.md (2)
1-717: Well-structured architecture plan with clear phased execution.This is a strong planning document: clear boundaries (renderer/main/shared), good rollout sequencing, and explicit risk tracking.
1-1: No action needed—no files were changed in this PR.The git diff shows zero changed files, so the requirement to update
IDE_BUILD_PLAN.mddoes not apply. Please verify that the correct branch/diff was provided for review.> Likely an incorrect or invalid review comment.packages/renderer/src/components/panes/TerminalPane.tsx (1)
161-172: Zoom application flow in terminal pane looks solidThe update order here (font size update, fit, then PTY resize) is correct and keeps terminal geometry in sync after zoom changes.
packages/renderer/src/components/FileTree/FileTypeIcon.tsx (1)
6-59: Type update foriconPathis appropriateUsing
ReactNodehere is a good fit for the mixed SVG return shapes in the switch cases.packages/renderer/src/components/DockviewContainer.tsx (1)
10-22: Browser pane registration is correctly wired
browserPaneis registered consistently with the panel component key used in panel creation.packages/renderer/src/lib/workspaceRuntimeSnapshots.ts (1)
40-40: PassingworkspaceIdinto serialization is the right moveThis makes snapshot capture workspace-aware at serialization time and matches the new serializer signature.
tests/unit/editorTheme.test.ts (1)
4-16: Good targeted coverage for editor metric scalingThis test directly validates the font-size to line-height mapping used by zoom-driven editor metrics.
packages/renderer/src/styles/dockview-theme.css (1)
21-27: LGTM!The tighter tab bar sizing (28px height, 10px font, 8px padding) is a reasonable density adjustment. The file consistently uses CSS variable tokens for theming.
packages/renderer/src/styles/find-in-files.css (1)
4-10: LGTM!The
--panel-zoomCSS custom property with default1andcalc()font scaling is correctly implemented. This pattern is consistent with other zoom-aware panes in the PR.packages/renderer/src/components/panes/FindInFilesPane.tsx (2)
6-9: LGTM!The
zoomFactoroptional param follows the established pattern used across other panes.
178-179: LGTM!The inline style correctly sets
--panel-zoomwith a fallback to1, matching the pattern inPlaceholderPaneandMarkdownPreviewPane.packages/renderer/src/components/panes/MarkdownPreviewPane.tsx (2)
38-41: LGTM!The
zoomFactoroptional param is correctly added to the interface.
117-122: LGTM!The
--panel-zoomCSS variable is correctly applied via inline style with appropriate fallback.packages/renderer/src/styles/app-shell.css (2)
257-263: LGTM!Adding
min-width: 0to flex containers is a standard fix to allow proper shrinking behavior, preventing overflow issues in the status bar.
316-326: LGTM!The
.placeholder-panecorrectly implements the--panel-zoompattern with default1andcalc()font scaling, consistent with other zoom-aware panes.packages/renderer/src/styles/file-tree.css (3)
48-53: LGTM!The font size reduction from 12px to 11px aligns with the PR's UI density adjustments.
87-100: LGTM!The filter input font size reduction to 10px is consistent with the overall UI density tightening.
137-141: LGTM!The empty hint font size reduction is consistent with other sidebar typography changes.
packages/renderer/src/styles/markdown-preview.css (2)
1-11: LGTM!The
--panel-zoomcustom property with default1andcalc()scaling for the base font size is correctly implemented, following the established pattern.
50-60: LGTM!Code block font size correctly scales with
--panel-zoom, ensuring consistent zoom behavior across all text elements in the preview.packages/renderer/src/components/Sidebar.tsx (1)
30-36: LGTM!The multi-line destructuring improves readability with no functional changes.
packages/renderer/src/components/panes/PlaceholderPane.tsx (1)
3-5: LGTM!The zoom factor integration follows the established pattern: typed panel params, inline CSS custom property with sensible default, consistent with other CSS-based panes.
packages/renderer/src/styles/welcome-pane.css (1)
2-10: LGTM!The
--panel-zoomCSS variable withcalc()font scaling is well-implemented. The default value of1on the selector allows the inline style fromWelcomePane.tsxto override it, and all typography elements scale consistently.packages/renderer/src/components/panes/WelcomePane.tsx (1)
8-13: LGTM!The zoom integration is consistent with other CSS-based panes. The
params?.zoomFactor ?? 1fallback correctly handles the initialparams: {}state (per context snippet atAppShell.tsx:150-151) until a zoom command updates the panel parameters.tests/unit/browserState.test.ts (1)
11-37: LGTM!Good coverage of the happy path. The test validates that browser pane state is correctly extracted from Dockview panels.
Consider adding a test case verifying that panels with a different
workspaceIdare filtered out byserializeBrowserPaneState.IDE_BUILD_PLAN.md (1)
1217-1217: LGTM!The progress tracker entry comprehensively documents the per-panel zoom implementation, covering all key aspects: shared utilities, IPC channels, per-pane-type scaling mechanisms, and state persistence. This aligns with the retrieved learning to keep
IDE_BUILD_PLAN.mdupdated with codebase changes.packages/renderer/src/components/panes/EditorPane.tsx (3)
1-26: LGTM!Imports and interface extension are well-structured. The
EDITOR_BASE_FONT_SIZEconstant appropriately centralizes the base value for zoom calculations. Based on learnings, CodeMirror 6 usage is correct per the coding guidelines.
88-91: LGTM!The metrics compartment is correctly added to the initial extensions list for new editor states, properly incorporating the zoom factor into font size calculations.
263-272: LGTM!The effect correctly reconfigures the metrics compartment when params change and calls
requestMeasure()to ensure CodeMirror updates its internal measurements after the font size adjustment.packages/renderer/src/styles/browser-pane.css (1)
1-87: LGTM!The CSS correctly uses CSS variable tokens throughout for theming support. The structure is clean and the focus state styling (lines 48-50) maintains accessibility after removing the default outline. As per coding guidelines, this follows the CSS variable token system with
data-themeattribute support.tests/unit/app.test.tsx (1)
18-21: LGTM!The mock implementations correctly match the
WindowApiinterface signatures. The zoom methods return appropriate default values (1for zoom factor), and browser pane lifecycle mocks properly return the expected types. The asyncrenderAppwithactwrapper correctly handles React effects that fire on mount.Also applies to: 112-126
packages/shared/src/zoom.ts (1)
1-38: LGTM!Clean, pure utility functions with good defensive coding. The
Number.isFinitecheck inclampZoomFactorproperly handles edge cases likeNaNandInfinity. The rounding strategy prevents floating-point precision issues.packages/main/src/index.ts (3)
30-33: LGTM!The
BrowserPaneManagerinstantiation correctly uses getter functions to lazily resolvemainWindowandcontentView?.webContents, handling the case where these don't exist at module initialization time.
79-93: LGTM!The custom zoom menu items correctly replace the built-in role-based zoom (which would affect the entire window) with per-panel zoom commands routed through IPC. Platform-specific accelerators are properly configured.
444-483: LGTM!The browser pane IPC handlers correctly distinguish between
ipcMain.handle(for operations requiring a return value likeBROWSER_CREATEandBROWSER_NAVIGATE) andipcMain.on(for fire-and-forget operations likeBROWSER_DESTROYand navigation controls). All handlers properly delegate tobrowserPaneManager.packages/renderer/src/lib/editorTheme.ts (1)
22-52: LGTM!The
getEditorMetricsfunction provides a clean abstraction for calculating font metrics, andgetEditorMetricsExtensioncomprehensively applies these to all relevant CodeMirror selectors (content, lines, gutters, gutter elements). The 1.6× line-height ratio is a standard choice for code readability. Based on learnings, the CodeMirror 6 Compartment pattern is correctly applied per the coding guidelines.packages/renderer/src/lib/browserState.ts (1)
1-59: LGTM!The browser state utilities are well-structured:
randomId()has a sensible fallback for environments withoutcrypto.randomUUIDcreateBrowserPanelParamsinitializes defaults correctlyisBrowserPanelprovides a proper type guard checking essential fieldsserializeBrowserPaneStatecorrectly filters by workspace and extracts the relevant statepackages/main/src/browserPaneManager.ts (2)
52-174: Well-structured pane lifecycle and event handling.The
create()method properly:
- Handles existing pane re-creation with workspace/session validation
- Configures secure
webPreferences(sandbox, contextIsolation, no nodeIntegration)- Sets up comprehensive event handlers for navigation, title, loading, and focus state
- Handles external link opening appropriately
260-285: No DPR scaling issue exists.getBoundingClientRect()returns device-independent pixels (CSS pixels), which is the correct coordinate system thatWebContentsView.setBounds()expects. Both APIs use the same DIP standard, so the bounds values flow through without needing any scaling adjustment.> Likely an incorrect or invalid review comment.packages/renderer/src/components/panes/BrowserPane.tsx (1)
256-332: Browser chrome UI implementation looks solid.The component correctly:
- Provides accessible navigation buttons with
aria-labelattributes- Uses controlled form submission for URL navigation
- Integrates zoom controls using shared utilities (
adjustZoomFactor,resetZoomFactor,zoomFactorToPercent)- Shows loading state and page title appropriately
packages/main/src/preload.ts (2)
27-35: LGTM!Zoom control IPC methods follow established patterns with proper event subscription cleanup.
228-273: LGTM!Browser pane IPC surface is well-structured:
- Lifecycle methods (
browserCreate,browserDestroy,browserDestroyWorkspace) properly useinvokefor async operations andsendfor fire-and-forget- Navigation and state methods follow existing PTY/terminal patterns
- Event subscriptions return cleanup functions consistently
packages/renderer/src/components/AppShell.tsx (4)
337-344: Good overlay suppression coordination.The effect correctly suppresses browser overlays when any modal is open (command palette, quick open, gitignore modal, task input, new browser modal), preventing browser panes from obscuring modal content.
362-391: Well-implemented per-panel zoom handling.The zoom implementation correctly:
- Distinguishes browser panes from other panel types
- Uses shared zoom utilities (
adjustZoomFactor,resetZoomFactor,getPanelZoomFactor)- Persists zoom state to both the panel parameters and workspace runtime
- Applies zoom via appropriate API (
setBrowserZoomfor browser,updateParametersfor others)
708-723: LGTM!Browser pane creation follows established Dockview patterns with proper parameter generation and positioning relative to the active panel.
453-460: The race condition concern is not substantiated by evidence in the codebase. The current guard adequately protects against synchronous events (the expected behavior), as theisSwitchingWorkspaceRefremainstruethroughout the synchronousfromJSON()→onAfterRestorePanels()sequence. No TODOs, warnings, or issues in the codebase indicate a known async event problem with Dockview'sfromJSON().packages/shared/src/index.ts (3)
7-16: LGTM!Clean re-export of zoom utilities from the dedicated module.
389-394: LGTM!
ZoomCommandPayloadis well-typed with a clear discriminator (target: 'panel') for future extensibility.
616-631: LGTM!Browser pane WindowApi methods are comprehensive and match the preload implementation exactly.
| ``` | ||
| ┌─────────────────────────────┐ | ||
| │ ◀ ▶ ↻ [ URL bar ] │ ← nav chrome (React, measured height = chromeHeight) | ||
| ├─────────────────────────────┤ | ||
| │ │ | ||
| │ placeholder div │ ← colored div, native overlay covers this area | ||
| │ (ResizeObserver) │ | ||
| │ │ | ||
| └─────────────────────────────┘ | ||
| ``` |
There was a problem hiding this comment.
Add a language tag to the fenced code block
The fence starting at Line 124 is missing a language identifier (MD040).
Suggested fix
-```
+```text
┌─────────────────────────────┐
│ ◀ ▶ ↻ [ URL bar ] │ ← nav chrome (React, measured height = chromeHeight)
├─────────────────────────────┤
│ │
│ placeholder div │ ← colored div, native overlay covers this area
│ (ResizeObserver) │
│ │
└─────────────────────────────┘</details>
<details>
<summary>🧰 Tools</summary>
<details>
<summary>🪛 markdownlint-cli2 (0.22.0)</summary>
[warning] 124-124: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
</details>
</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
Verify each finding against the current code and only fix it if needed.
In @browserPanes.md around lines 124 - 133, The fenced ASCII-art block is
missing a language tag; update the fence that begins with the ┌ box (the
ASCII-art placeholder div block) to include a language identifier (e.g., add
text instead of ) so the Markdown linter rule MD040 is satisfied and the
block is treated as plain text.
</details>
<!-- fingerprinting:phantom:poseidon:hawk -->
<!-- This is an auto-generated comment by CodeRabbit -->
| function normalizeUrl(input: string): string { | ||
| const trimmed = input.trim() | ||
| if (!trimmed) return '' | ||
|
|
||
| try { | ||
| return new URL(trimmed).toString() | ||
| } catch { | ||
| return new URL(`https://${trimmed}`).toString() | ||
| } | ||
| } |
There was a problem hiding this comment.
URL normalization can throw on malformed input.
If trimmed is truly malformed (e.g., "://"), the fallback new URL(\https://${trimmed}`)` will also throw, causing an unhandled exception.
🛡️ Proposed fix to handle malformed URLs
function normalizeUrl(input: string): string {
const trimmed = input.trim()
if (!trimmed) return ''
try {
return new URL(trimmed).toString()
} catch {
- return new URL(`https://${trimmed}`).toString()
+ try {
+ return new URL(`https://${trimmed}`).toString()
+ } catch {
+ return ''
+ }
}
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/main/src/browserPaneManager.ts` around lines 32 - 41, The
normalizeUrl function can still throw when the fallback new
URL(`https://${trimmed}`) is given a completely malformed input like "://";
update normalizeUrl to catch errors from the fallback attempt as well and return
a safe default (e.g., empty string) instead of letting an exception propagate.
Specifically, keep the initial trim and empty check, attempt new URL(trimmed) in
a try, and if that fails attempt new URL(`https://${trimmed}`) inside a second
try/catch (or a single try with nested catches) and return '' on any remaining
error; refer to the normalizeUrl function and the trimmed variable to locate the
change.
| if (cached) { | ||
| view.dispatch({ | ||
| effects: StateEffect.appendConfig.of([ | ||
| editorMetricsCompartment.of( | ||
| getEditorMetricsExtension(Math.round(EDITOR_BASE_FONT_SIZE * getPanelZoomFactor(params))), | ||
| ), | ||
| ]), | ||
| }) | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check how compartments are handled elsewhere in the codebase for cached states
rg -n "appendConfig|reconfigure" --type=ts -C3 packages/renderer/srcRepository: Cheezeiii365/aIDE
Length of output: 2623
🏁 Script executed:
#!/bin/bash
# Find where compartments are created and initialized
rg -n "editorMetricsCompartment|wrapCompartment|themeCompartment" --type=ts packages/renderer/src/components/panes/EditorPane.tsx | head -20Repository: Cheezeiii365/aIDE
Length of output: 702
🏁 Script executed:
#!/bin/bash
# Search for where initial extensions are constructed (likely where compartments are added)
rg -n "extensions.*=.*\[|getEditorExtensions" --type=ts packages/renderer/src -B2 -A5Repository: Cheezeiii365/aIDE
Length of output: 817
🏁 Script executed:
#!/bin/bash
# Check StateEffect.appendConfig documentation and usage patterns
rg -n "StateEffect.appendConfig" --type=ts packages/renderer/src -B3 -A3Repository: Cheezeiii365/aIDE
Length of output: 721
Use conditional logic to handle both pre- and post-feature cached states when restoring editorMetricsCompartment.
Using StateEffect.appendConfig unconditionally on cached states creates duplicate editorMetricsCompartment instances when restoring states cached after this PR (which already contain the compartment). Conversely, directly using reconfigure would fail on states cached before this feature existed.
Check if the compartment exists in the cached state and use reconfigure if present, or appendConfig if absent. Alternatively, consider whether stripping and rebuilding the extension is viable for your backward compatibility requirements.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/renderer/src/components/panes/EditorPane.tsx` around lines 151 -
159, When restoring a cached editor state in the view.dispatch block, detect
whether the cached state already contains the editorMetricsCompartment and use
StateEffect.reconfigure (or the compartment.reconfigure effect) in that case,
otherwise use StateEffect.appendConfig.of(...) as current code does;
specifically, inspect the cached state's extensions for editorMetricsCompartment
(the compartment symbol) and then call either a reconfigure effect with
getEditorMetricsExtension(Math.round(EDITOR_BASE_FONT_SIZE *
getPanelZoomFactor(params))) or
appendConfig.of([...editorMetricsCompartment.of(getEditorMetricsExtension(...))])
to avoid duplicating compartments or failing for older cached states.
|
Note Docstrings generation - SUCCESS |
Docstrings generation was requested by @Cheezeiii365. The following files were modified: * `packages/main/src/browserPaneManager.ts` * `packages/renderer/src/components/FileTree/FileTypeIcon.tsx` * `packages/renderer/src/components/NewBrowserPaneModal.tsx` * `packages/renderer/src/components/Sidebar.tsx` * `packages/renderer/src/components/panes/BrowserPane.tsx` * `packages/renderer/src/components/panes/EditorPane.tsx` * `packages/renderer/src/components/panes/MarkdownPreviewPane.tsx` * `packages/renderer/src/components/panes/PlaceholderPane.tsx` * `packages/renderer/src/components/panes/WelcomePane.tsx` * `packages/renderer/src/lib/browserState.ts` * `packages/renderer/src/lib/editorTheme.ts` * `packages/renderer/src/lib/panelZoom.ts` * `packages/renderer/src/lib/terminalState.ts` * `packages/renderer/src/lib/workspaceRuntimeSnapshots.ts` * `packages/renderer/src/lib/workspaceStateSerializer.ts` * `packages/shared/src/zoom.ts` These files were kept as they were: * `packages/main/src/index.ts` * `packages/renderer/src/components/AppShell.tsx` * `packages/renderer/src/components/panes/FindInFilesPane.tsx` * `packages/renderer/src/components/panes/TerminalPane.tsx` * `packages/renderer/src/lib/defaultCommands.ts` These files were ignored: * `packages/shared/src/index.test.ts` * `tests/unit/app.test.tsx` * `tests/unit/browserState.test.ts` * `tests/unit/editorTheme.test.ts` * `tests/unit/panelZoom.test.ts` * `tests/unit/workspaceStateSerializer.test.ts` These file types are not supported: * `IDE_BUILD_PLAN.md` * `LSPPLAN.md` * `browserPanes.md` * `packages/renderer/src/styles/app-shell.css` * `packages/renderer/src/styles/browser-pane.css` * `packages/renderer/src/styles/dockview-theme.css` * `packages/renderer/src/styles/file-tree.css` * `packages/renderer/src/styles/find-in-files.css` * `packages/renderer/src/styles/markdown-preview.css` * `packages/renderer/src/styles/welcome-pane.css`
Clamp values through clampZoomFactor in getPanelZoomFactor and updatePanelZoomParams to prevent invalid zoom from persisted or externally mutated params. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
webContents.setZoomFactor()with toolbar +/-/readout controls and dedicated IPC channels--panel-zoomCSS variable withcalc()scaling@aide/shared(adjustZoomFactor,clampZoomFactor,resetZoomFactor,zoomFactorToPercent)Issues
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation