Skip to content

Comments

feat: Restructure Codebase#161

Merged
iamEvanYT merged 51 commits intomainfrom
evan/restructure
Oct 29, 2025
Merged

feat: Restructure Codebase#161
iamEvanYT merged 51 commits intomainfrom
evan/restructure

Conversation

@iamEvanYT
Copy link
Member

@iamEvanYT iamEvanYT commented Sep 20, 2025

Goals

  • Remove @/browser
  • Introduce Controllers at @/controllers
  • Streamline operations with OOP for each controller
  • Add in-memory caching to Profile & Space operations to improve performance

Summary by CodeRabbit

Release Notes

  • Build & Configuration

    • Updated build pipeline with improved TypeScript checking and production-optimized compilation.
    • Enhanced build system reliability and performance.
  • New Features

    • Improved auto-update system with better status tracking and mock data support for testing.
    • Enhanced default browser functionality with platform-aware detection.
  • Improvements

    • Refined profile, space, and window management systems for better stability.
    • Optimized menu system and IPC communication architecture.
    • Enhanced session and extension handling with improved lifecycle management.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 20, 2025

Caution

Review failed

Failed to post review comments

Walkthrough

This PR implements a major architectural refactor of the Electron app's main process, replacing a centralized Browser singleton pattern with a modular controller-based architecture. It introduces controllers for windows, tabs, profiles, sessions, spaces, menus, and updates, removes the old Browser, WindowManager, and ProfileManager classes, updates all IPC handlers to use the new controllers, and adds platform-specific initialization flows for app lifecycle and onboarding.

Changes

Cohort / File(s) Summary
Build & Configuration Updated package.json scripts to use bun, added cross-env for PRODUCTION_BUILD flag, added postinstall script. Updated electron.vite.config.ts to conditionally apply minification based on PRODUCTION_BUILD environment variable. Added TypeScript SDK path in .vscode/settings.json.
App Initialization & Lifecycle Added new app setup modules: src/main/browser.ts (main orchestrator), src/main/app/instance.ts (second-instance handling), src/main/app/lifecycle.ts (app lifecycle events), src/main/app/onboarding.ts (onboarding flow), src/main/app/platform.ts (platform-specific UI), src/main/app/urls.ts (URL validation and handling). Significantly simplified src/main/index.ts, removing initialization logic and deferring to new browser module.
Deleted Old Architecture Removed src/main/browser/browser.ts (Browser class), src/main/browser/window-manager.ts (WindowManager), src/main/browser/window.ts (TabbedBrowserWindow), src/main/browser/profile-manager.ts, src/main/browser/events.ts, all old menu utilities, old protocol/session modules, and old quit handlers.
New Controllers — Core Added src/main/controllers/windows-controller/* with WindowsController, window type managers (BrowserWindow, SettingsWindow, OnboardingWindow, ExtensionPopupWindow), and browser window interface. Added src/main/controllers/tabs-controller/ with TabsController, replacing TabManager pattern.
New Controllers — Data & Sessions Added src/main/controllers/profiles-controller/ with ProfilesController and RawProfilesController for CRUD and caching. Added src/main/controllers/spaces-controller/ with SpacesController and RawSpacesController. Added src/main/controllers/sessions-controller/ with SessionsController, protocol handlers, intercept rules, web-requests, and preload scripts.
New Controllers — Lifecycle & Services Added src/main/controllers/loaded-profiles-controller/ for managing per-profile extensions. Added src/main/controllers/quit-controller/ for Electron quit flow. Added src/main/controllers/app-menu-controller/ with dynamic menu rendering and item generators.
New Controllers — Integrations Added src/main/controllers/auto-update-controller/ replacing module-based auto-update with mock/real update handling. Added src/main/controllers/default-browser-controller/ for OS-aware default browser setting. Added src/main/controllers/posthog-controller/ with analytics integration and error tracking.
IPC Updates Updated all src/main/ipc/** handlers to use new controllers instead of global browser: app, browser, browser/interface, browser/navigation, browser/page, browser/tabs, session/profiles, session/spaces, window/omnibox, window/settings.
Utilities & Modules Added src/main/modules/pdf-cache.ts for PDF response caching. Updated src/main/modules/content-blocker.ts to use loadedProfilesController. Updated src/main/modules/icons.ts to use windowsController. Updated src/main/modules/extensions/main.ts to use sessionsController. Updated src/main/modules/output.ts with WINDOWS debug area. Removed old src/main/modules/auto-update.ts, src/main/modules/default-browser.ts, src/main/modules/posthog.ts, src/main/modules/quit-handlers/.
Documentation Added README files in src/main/controllers/ directories documenting architecture, dependencies, and usage patterns.

Sequence Diagram(s)

sequenceDiagram
    participant App as Electron App
    participant Browser as browser.ts
    participant LC as lifecycle
    participant Inst as instance
    participant Platform as platform
    participant Onboarding as onboarding
    participant Windows as windows-controller
    participant Menus as app-menu
    
    App->>Browser: (import)
    Browser->>Browser: processInitialUrl()
    Browser->>Inst: setupSecondInstanceHandling()
    Browser->>Platform: setupPlatformIntegration()
    Browser->>Onboarding: runOnboardingOrInitialWindow()
    Onboarding->>Windows: create browser/onboarding window
    Browser->>LC: setupAppLifecycle()
    LC->>App: on window-all-closed
    LC->>App: on ready
    LC->>App: on open-url
    note over App,Browser: App now runs under<br/>controller-based architecture
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • Controller initialization order & dependency graph — Verify that all controllers initialize in the correct sequence (e.g., windows-controller before tabs-controller, sessions-controller before loaded-profiles-controller). Check src/main/controllers/index.ts import ordering and comments.
  • Window lifecycle & destruction — Review src/main/controllers/windows-controller/ and ensure all window types (browser, settings, onboarding, extension-popup) properly emit/handle lifecycle events and clean up resources.
  • Tab & spaces integration — Verify src/main/controllers/tabs-controller/index.ts correctly resolves spaces and profiles via controllers; check tab group creation, active tab tracking, and persistence.
  • Session & profile per-instance setup — Confirm src/main/controllers/sessions-controller/ properly registers protocols, preload scripts, intercept rules, and handlers for each profile session.
  • IPC handler updates — Spot-check several IPC modules (src/main/ipc/browser/tabs.ts, src/main/ipc/session/spaces.ts, src/main/ipc/session/profiles.ts) for correct controller usage and null-check guards; verify no race conditions or missing awaits on async operations.
  • Omnibox & menu interaction — Review src/main/controllers/windows-controller/utils/browser/omnibox.ts and app-menu-controller menu items for proper window focus, state consistency, and event emission.
  • Auto-update, PostHog, and quit flows — Verify mock vs. real execution paths in auto-update-controller; check PostHog async identifier fetching and error capture initialization; confirm quit-controller state machine prevents double-quit.

Possibly related PRs

  • Major Rewrite #20 — Major architectural refactor replacing Browser/Window/Tab classes with controller-based modules and updating IPC accordingly.
  • feat: introduce windows controller #162 — Overlapping refactor to windows-controller, browserWindowsController, and conversion of TabbedBrowserWindow usages throughout IPC and app modules.
  • Add Posthog Error Logging #32 — Replaces old PostHog module (src/main/modules/posthog.ts) with new controller-based implementation (src/main/controllers/posthog-controller/).

Suggested labels

architecture, refactor, enhancement

Poem

🐰 Hop into the future! Controllers now reign,
no more monolithic Browser to strain.
Windows, tabs, profiles in harmony bound,
modular and clean—the architecture's found!
Events and lifecycle flow smooth as a breeze,
Electron app refactored to please! 🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.12% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "feat: Restructure Codebase" is directly related to the main change in the pull request. The changeset demonstrates a comprehensive architectural restructuring that removes the centralized Browser module (@/browser) and replaces it with a controller-based architecture (@/controllers), introducing multiple specialized controllers for different domains like windows, tabs, spaces, profiles, and sessions. While the title is somewhat broad and doesn't specify the exact nature of the architectural shift, it accurately conveys that this is a major structural reorganization rather than a targeted feature or fix. The title is sufficiently descriptive to distinguish it from generic or vague terms like "misc updates" or "stuff."
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch evan/restructure

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.

❤️ Share

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

@github-actions
Copy link
Contributor

github-actions bot commented Sep 20, 2025

Build artifacts for all platforms are ready! 🚀

Download the artifacts from:

(execution 18892620143 / attempt 1)

@iamEvanYT iamEvanYT marked this pull request as ready for review October 28, 2025 23:57
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 89

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (14)
src/main/controllers/sessions-controller/protocols/utils.ts (4)

27-37: Block path traversal; validate resolved path stays within baseDir.

path.join with untrusted filePath/extraDir allows .. escapes. Resolve and enforce baseDir containment before reading.

-  if (extraDir) {
-    transformedPath = path.join(extraDir, transformedPath);
-  }
-
-  const fullFilePath = path.join(baseDir, transformedPath);
+  const base = path.resolve(baseDir);
+  const joined = extraDir ? path.join(extraDir, transformedPath) : transformedPath;
+  const fullFilePath = path.resolve(base, joined);
+  // Ensure the resolved path is inside base
+  const baseWithSep = base.endsWith(path.sep) ? base : base + path.sep;
+  if (!(fullFilePath === base || fullFilePath.startsWith(baseWithSep))) {
+    return new Response("File not found", { status: 404 });
+  }

38-46: Hot-reload setup should be idempotent and cheap.

setupHotReloadFileDescriptors() runs on every request in dev mode. Ensure it’s idempotent or move behind a one‑time guard.

I can add a simple module‑level initialized flag in ./hot-reload if needed.


60-65: Optional: add caching headers for static assets.

Consider Cache-Control (e.g., public, max-age=31536000, immutable) for hashed assets, and no-store for HTML. This materially improves load times.


49-55: Minor: prefer streaming for large files.

For big assets, fsPromises.readFile buffers whole files. A fs.createReadStream or Bun.file() Response would reduce memory spikes. If Bun is available per guidelines, return new Response(Bun.file(fullFilePath));

Confirm whether the main process runs under Bun in production; if not, keep Node streams.

src/main/controllers/quit-controller/handlers/before-quit.ts (1)

29-37: Simplify promise handling.

The Promise.all with a single-element array and .every() check are unnecessary for a single promise that already resolves to boolean.

Apply this diff:

 export function beforeQuit(): boolean | Promise<boolean> {
-  const flushSessionsDataPromise = flushSessionsData()
+  return flushSessionsData()
     .then(() => true)
     .catch(() => true);
-
-  return Promise.all([flushSessionsDataPromise]).then((results) => {
-    return results.every((result) => result);
-  });
 }
src/main/ipc/app/updates.ts (1)

21-22: Consider logging errors in update check.

The empty catch block silently swallows all errors from checkForUpdates(). This could hide important issues like network failures or invalid update manifests.

Consider logging the error:

  } catch {
+   console.error('[Updates] Failed to check for updates:', error);
    return false;
  }

Or better yet, with the error parameter:

- } catch {
+ } catch (error) {
+   console.error('[Updates] Failed to check for updates:', error);
    return false;
  }
src/main/controllers/windows-controller/utils/close-preventer.ts (1)

11-16: Tidy listener lifecycle and key detection; avoid shadowing

  • Don’t shadow the imported webContents; rename param.
  • Remove IDs on destroyed to prevent growth.
  • Normalize key and ignore auto‑repeat to avoid multiple closes on long press.
-function newWebContents(webContents: WebContents) {
+function newWebContents(contents: WebContents) {
   if (!enabled) return;
 
-  if (registeredWebContentIds.has(webContents.id)) return;
-  registeredWebContentIds.add(webContents.id);
+  if (registeredWebContentIds.has(contents.id)) return;
+  registeredWebContentIds.add(contents.id);
 
-  webContents.on("before-input-event", (event, input) => {
-    if (input.key === "w" && input.control) {
+  contents.on("before-input-event", (event, input) => {
+    if (input.key?.toLowerCase() === "w" && input.control) {
       event.preventDefault();
 
-      if (input.type === "keyDown") {
+      if (input.type === "keyDown" && !input.isAutoRepeat) {
         menuCloseTab();
       }
     }
   });
+  contents.once("destroyed", () => {
+    registeredWebContentIds.delete(contents.id);
+  });
 }
@@
-  app.on("web-contents-created", (_event, webContents) => {
-    newWebContents(webContents);
+  app.on("web-contents-created", (_event, contents) => {
+    newWebContents(contents);
   });

Also applies to: 17-23, 28-39

src/main/controllers/tabs-controller/context-menu.ts (2)

80-84: Dictionary suggestions visibility check may hide valid items

Some suggestion items may not set .visible; using .some(s => s.visible) can return false when items are usable. Prefer length check.

-      const hasDictionarySuggestions = dictionarySuggestions.some((suggestion) => suggestion.visible);
-      if (hasDictionarySuggestions) {
+      if (dictionarySuggestions.length > 0) {
         sections.push(dictionarySuggestions);
       }

186-191: Remove ts-expect-error by typing extensions context menu API

Leaning on @ts-expect-error hides real issues. Add an interface for getContextMenuItems.

// e.g., somewhere in extensions types
export interface ExtensionsApi {
  getContextMenuItems: (wc: Electron.WebContents, params: Electron.ContextMenuParams) => Electron.MenuItemConstructorOptions[];
}

Then type loadedProfile.extensions accordingly and drop the ts-expect-error.

src/main/controllers/windows-controller/utils/browser/omnibox.ts (1)

213-219: Cleanup: destroy view and remove map entry to prevent leaks

Ensure Omnibox fully cleans up resources.

   destroy() {
     this.assertNotDestroyed();
 
     this.isDestroyed = true;
-    this.webContents.close();
+    const win = this.window;
+    try {
+      this.view?.destroy?.();
+    } catch {}
+    try {
+      if (!this.webContents.isDestroyed()) this.webContents.destroy();
+    } catch {}
+    omniboxes.delete(win);
   }
src/main/controllers/tabs-controller/tab-groups/index.ts (2)

142-147: Undefined windowId can propagate into setWindow().

const newWindowId = tab.getWindow()?.id; may be undefined. The comparison still passes and setWindow(undefined) throws. Guard before calling.

-      const newWindowId = tab.getWindow()?.id;
-      if (newWindowId !== this.windowId) {
-        this.setWindow(newWindowId);
-      }
+      const maybeWindowId = tab.getWindow()?.id;
+      if (typeof maybeWindowId === "number" && maybeWindowId !== this.windowId) {
+        this.setWindow(maybeWindowId);
+      }

211-214: position accessor can throw for empty groups.

If all tabs are removed, this.tabs[0] is undefined. Return a sentinel or throw a clear error.

-    return this.tabs[0].position;
+    if (this.tabs.length === 0) throw new Error("TabGroup has no tabs");
+    return this.tabs[0].position;
src/main/controllers/tabs-controller/tab.ts (1)

270-273: Redundant assignment

this.setWindow(window) already assigns this.window; the extra set is unnecessary.

Apply:

     // Setup window
     this.setWindow(window);
-    this.window = window;
src/main/controllers/tabs-controller/index.ts (1)

96-149: Create-tab flow is clear; consider friendlier errors

Thrown errors bubble to callers. For UX, log and return a structured result or map to IPC error codes; keep throws for truly exceptional states.

If you want, I can add a Result<T, E> style return and update IPC handlers accordingly.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 41571d7 and 63ac595.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (107)
  • .vscode/settings.json (1 hunks)
  • electron.vite.config.ts (2 hunks)
  • package.json (2 hunks)
  • src/main/app/instance.ts (1 hunks)
  • src/main/app/lifecycle.ts (1 hunks)
  • src/main/app/onboarding.ts (1 hunks)
  • src/main/app/platform.ts (1 hunks)
  • src/main/app/urls.ts (1 hunks)
  • src/main/browser.ts (1 hunks)
  • src/main/browser/browser.ts (0 hunks)
  • src/main/browser/events.ts (0 hunks)
  • src/main/browser/profile-manager.ts (0 hunks)
  • src/main/browser/utility/intercept-rules.ts (0 hunks)
  • src/main/browser/utility/menu.ts (0 hunks)
  • src/main/browser/utility/menu/helpers.ts (0 hunks)
  • src/main/browser/utility/menu/items/file.ts (0 hunks)
  • src/main/browser/utility/protocols/index.ts (0 hunks)
  • src/main/browser/window-manager.ts (0 hunks)
  • src/main/browser/window.ts (0 hunks)
  • src/main/controllers/README.md (1 hunks)
  • src/main/controllers/app-menu-controller/index.ts (1 hunks)
  • src/main/controllers/app-menu-controller/menu/helpers.ts (1 hunks)
  • src/main/controllers/app-menu-controller/menu/items/app.ts (2 hunks)
  • src/main/controllers/app-menu-controller/menu/items/archive.ts (2 hunks)
  • src/main/controllers/app-menu-controller/menu/items/edit.ts (2 hunks)
  • src/main/controllers/app-menu-controller/menu/items/file.ts (1 hunks)
  • src/main/controllers/app-menu-controller/menu/items/spaces.ts (4 hunks)
  • src/main/controllers/app-menu-controller/menu/items/view.ts (4 hunks)
  • src/main/controllers/auto-update-controller/index.ts (1 hunks)
  • src/main/controllers/default-browser-controller/index.ts (1 hunks)
  • src/main/controllers/index.ts (1 hunks)
  • src/main/controllers/loaded-profiles-controller/index.ts (1 hunks)
  • src/main/controllers/posthog-controller/identify.ts (1 hunks)
  • src/main/controllers/posthog-controller/index.ts (1 hunks)
  • src/main/controllers/posthog-controller/posthog-error-capture-sdk/index.ts (1 hunks)
  • src/main/controllers/profiles-controller/index.ts (1 hunks)
  • src/main/controllers/profiles-controller/raw.ts (1 hunks)
  • src/main/controllers/quit-controller/README.md (1 hunks)
  • src/main/controllers/quit-controller/handlers/before-quit.ts (1 hunks)
  • src/main/controllers/quit-controller/index.ts (1 hunks)
  • src/main/controllers/sessions-controller/README.md (1 hunks)
  • src/main/controllers/sessions-controller/default-session/index.ts (1 hunks)
  • src/main/controllers/sessions-controller/handlers/index.ts (1 hunks)
  • src/main/controllers/sessions-controller/index.ts (1 hunks)
  • src/main/controllers/sessions-controller/intercept-rules/better-pdf-viewer.ts (1 hunks)
  • src/main/controllers/sessions-controller/intercept-rules/cors-bypass-custom-protocols.ts (1 hunks)
  • src/main/controllers/sessions-controller/intercept-rules/index.ts (1 hunks)
  • src/main/controllers/sessions-controller/intercept-rules/user-agent-transformer.ts (1 hunks)
  • src/main/controllers/sessions-controller/preload-scripts/index.ts (1 hunks)
  • src/main/controllers/sessions-controller/protocols/_protocols/flow-external.ts (1 hunks)
  • src/main/controllers/sessions-controller/protocols/_protocols/flow-internal.ts (3 hunks)
  • src/main/controllers/sessions-controller/protocols/_protocols/flow.ts (2 hunks)
  • src/main/controllers/sessions-controller/protocols/hot-reload.ts (2 hunks)
  • src/main/controllers/sessions-controller/protocols/index.ts (1 hunks)
  • src/main/controllers/sessions-controller/protocols/utils.ts (1 hunks)
  • src/main/controllers/sessions-controller/web-requests/index.ts (2 hunks)
  • src/main/controllers/spaces-controller/index.ts (1 hunks)
  • src/main/controllers/spaces-controller/raw.ts (1 hunks)
  • src/main/controllers/tabs-controller/bounds.ts (1 hunks)
  • src/main/controllers/tabs-controller/context-menu.ts (5 hunks)
  • src/main/controllers/tabs-controller/index.ts (12 hunks)
  • src/main/controllers/tabs-controller/tab-groups/glance.ts (1 hunks)
  • src/main/controllers/tabs-controller/tab-groups/index.ts (9 hunks)
  • src/main/controllers/tabs-controller/tab-groups/split.ts (1 hunks)
  • src/main/controllers/tabs-controller/tab.ts (20 hunks)
  • src/main/controllers/windows-controller/README.md (1 hunks)
  • src/main/controllers/windows-controller/index.ts (1 hunks)
  • src/main/controllers/windows-controller/interfaces/browser.ts (1 hunks)
  • src/main/controllers/windows-controller/interfaces/onboarding.ts (1 hunks)
  • src/main/controllers/windows-controller/interfaces/settings.ts (1 hunks)
  • src/main/controllers/windows-controller/type-manager.ts (1 hunks)
  • src/main/controllers/windows-controller/types/base.ts (1 hunks)
  • src/main/controllers/windows-controller/types/browser.ts (1 hunks)
  • src/main/controllers/windows-controller/types/extension-popup.ts (1 hunks)
  • src/main/controllers/windows-controller/types/index.ts (1 hunks)
  • src/main/controllers/windows-controller/types/onboarding.ts (1 hunks)
  • src/main/controllers/windows-controller/types/settings.ts (1 hunks)
  • src/main/controllers/windows-controller/utils/browser/omnibox.ts (4 hunks)
  • src/main/controllers/windows-controller/utils/browser/portal-component-windows.ts (3 hunks)
  • src/main/controllers/windows-controller/utils/close-preventer.ts (2 hunks)
  • src/main/index.ts (2 hunks)
  • src/main/ipc/README.md (1 hunks)
  • src/main/ipc/app/actions.ts (1 hunks)
  • src/main/ipc/app/app.ts (2 hunks)
  • src/main/ipc/app/extensions.ts (7 hunks)
  • src/main/ipc/app/new-tab.ts (1 hunks)
  • src/main/ipc/app/updates.ts (2 hunks)
  • src/main/ipc/browser/browser.ts (1 hunks)
  • src/main/ipc/browser/interface.ts (1 hunks)
  • src/main/ipc/browser/navigation.ts (2 hunks)
  • src/main/ipc/browser/page.ts (2 hunks)
  • src/main/ipc/browser/tabs.ts (11 hunks)
  • src/main/ipc/listeners-manager.ts (1 hunks)
  • src/main/ipc/session/profiles.ts (1 hunks)
  • src/main/ipc/session/spaces.ts (1 hunks)
  • src/main/ipc/window/omnibox.ts (1 hunks)
  • src/main/ipc/window/settings.ts (1 hunks)
  • src/main/modules/auto-update.ts (0 hunks)
  • src/main/modules/content-blocker.ts (4 hunks)
  • src/main/modules/default-browser.ts (0 hunks)
  • src/main/modules/extensions/main.ts (2 hunks)
  • src/main/modules/icons.ts (3 hunks)
  • src/main/modules/output.ts (1 hunks)
  • src/main/modules/pdf-cache.ts (1 hunks)
  • src/main/modules/posthog.ts (0 hunks)
  • src/main/modules/quit-handlers/index.ts (0 hunks)
  • src/main/modules/typed-event-emitter.ts (1 hunks)
⛔ Files not processed due to max files limit (11)
  • src/main/modules/utils.ts
  • src/main/modules/windows.ts
  • src/main/onboarding/main.ts
  • src/main/saving/datastore.ts
  • src/main/saving/onboarding.ts
  • src/main/saving/tabs.ts
  • src/main/sessions/profiles.ts
  • src/main/sessions/spaces.ts
  • src/main/settings/main.ts
  • src/preload/index.ts
  • src/renderer/src/router/provider.tsx
💤 Files with no reviewable changes (14)
  • src/main/browser/events.ts
  • src/main/browser/utility/menu.ts
  • src/main/browser/utility/intercept-rules.ts
  • src/main/modules/auto-update.ts
  • src/main/browser/utility/protocols/index.ts
  • src/main/browser/window-manager.ts
  • src/main/browser/utility/menu/items/file.ts
  • src/main/modules/quit-handlers/index.ts
  • src/main/modules/default-browser.ts
  • src/main/modules/posthog.ts
  • src/main/browser/utility/menu/helpers.ts
  • src/main/browser/browser.ts
  • src/main/browser/window.ts
  • src/main/browser/profile-manager.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{js,jsx,ts,tsx}: Use bun <file> instead of node <file> or ts-node <file>
Bun automatically loads .env, so don't use dotenv.
Use Bun.serve() for HTTP servers and WebSockets instead of express.
Use bun:sqlite for SQLite instead of better-sqlite3.
Use Bun.redis for Redis instead of ioredis.
Use Bun.sql for Postgres instead of pg or postgres.js.
Use built-in WebSocket instead of ws.
Prefer Bun.file over node:fs's readFile/writeFile.
Use Bun.$ for shell commands instead of execa.

Files:

  • src/main/controllers/sessions-controller/preload-scripts/index.ts
  • src/main/app/lifecycle.ts
  • src/main/app/instance.ts
  • src/main/controllers/tabs-controller/bounds.ts
  • src/main/controllers/windows-controller/types/extension-popup.ts
  • src/main/controllers/tabs-controller/tab-groups/split.ts
  • src/main/controllers/sessions-controller/default-session/index.ts
  • src/main/controllers/posthog-controller/posthog-error-capture-sdk/index.ts
  • src/main/controllers/app-menu-controller/menu/items/file.ts
  • src/main/controllers/tabs-controller/tab-groups/glance.ts
  • src/main/controllers/app-menu-controller/menu/items/archive.ts
  • src/main/modules/typed-event-emitter.ts
  • src/main/controllers/sessions-controller/protocols/hot-reload.ts
  • src/main/controllers/sessions-controller/intercept-rules/cors-bypass-custom-protocols.ts
  • src/main/controllers/windows-controller/types/settings.ts
  • src/main/controllers/app-menu-controller/index.ts
  • src/main/ipc/listeners-manager.ts
  • src/main/controllers/sessions-controller/web-requests/index.ts
  • src/main/controllers/quit-controller/index.ts
  • src/main/controllers/sessions-controller/handlers/index.ts
  • src/main/controllers/sessions-controller/intercept-rules/index.ts
  • src/main/controllers/windows-controller/index.ts
  • src/main/app/urls.ts
  • src/main/ipc/browser/tabs.ts
  • src/main/controllers/windows-controller/utils/close-preventer.ts
  • src/main/controllers/app-menu-controller/menu/items/spaces.ts
  • src/main/modules/output.ts
  • src/main/controllers/windows-controller/utils/browser/portal-component-windows.ts
  • src/main/controllers/windows-controller/interfaces/settings.ts
  • src/main/ipc/app/new-tab.ts
  • src/main/controllers/sessions-controller/protocols/_protocols/flow.ts
  • src/main/controllers/index.ts
  • src/main/controllers/sessions-controller/intercept-rules/user-agent-transformer.ts
  • src/main/modules/pdf-cache.ts
  • src/main/controllers/sessions-controller/intercept-rules/better-pdf-viewer.ts
  • src/main/controllers/windows-controller/types/index.ts
  • electron.vite.config.ts
  • src/main/ipc/browser/browser.ts
  • src/main/controllers/sessions-controller/protocols/_protocols/flow-external.ts
  • src/main/controllers/default-browser-controller/index.ts
  • src/main/controllers/profiles-controller/raw.ts
  • src/main/ipc/browser/interface.ts
  • src/main/ipc/browser/page.ts
  • src/main/app/platform.ts
  • src/main/controllers/tabs-controller/context-menu.ts
  • src/main/controllers/loaded-profiles-controller/index.ts
  • src/main/controllers/sessions-controller/index.ts
  • src/main/controllers/spaces-controller/raw.ts
  • src/main/controllers/posthog-controller/identify.ts
  • src/main/ipc/window/omnibox.ts
  • src/main/ipc/window/settings.ts
  • src/main/controllers/windows-controller/interfaces/onboarding.ts
  • src/main/controllers/windows-controller/types/onboarding.ts
  • src/main/controllers/app-menu-controller/menu/items/edit.ts
  • src/main/ipc/app/extensions.ts
  • src/main/controllers/sessions-controller/protocols/index.ts
  • src/main/controllers/windows-controller/interfaces/browser.ts
  • src/main/controllers/app-menu-controller/menu/items/view.ts
  • src/main/modules/extensions/main.ts
  • src/main/browser.ts
  • src/main/controllers/windows-controller/type-manager.ts
  • src/main/controllers/spaces-controller/index.ts
  • src/main/app/onboarding.ts
  • src/main/controllers/tabs-controller/tab-groups/index.ts
  • src/main/ipc/app/updates.ts
  • src/main/controllers/quit-controller/handlers/before-quit.ts
  • src/main/controllers/tabs-controller/tab.ts
  • src/main/controllers/profiles-controller/index.ts
  • src/main/ipc/session/profiles.ts
  • src/main/modules/content-blocker.ts
  • src/main/ipc/app/app.ts
  • src/main/controllers/windows-controller/types/base.ts
  • src/main/controllers/posthog-controller/index.ts
  • src/main/controllers/sessions-controller/protocols/utils.ts
  • src/main/controllers/windows-controller/types/browser.ts
  • src/main/ipc/session/spaces.ts
  • src/main/controllers/auto-update-controller/index.ts
  • src/main/controllers/app-menu-controller/menu/helpers.ts
  • src/main/ipc/app/actions.ts
  • src/main/controllers/sessions-controller/protocols/_protocols/flow-internal.ts
  • src/main/index.ts
  • src/main/modules/icons.ts
  • src/main/controllers/app-menu-controller/menu/items/app.ts
  • src/main/ipc/browser/navigation.ts
  • src/main/controllers/tabs-controller/index.ts
  • src/main/controllers/windows-controller/utils/browser/omnibox.ts
**/*.{html,ts,css}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file.html|file.ts|file.css> instead of webpack or esbuild

Files:

  • src/main/controllers/sessions-controller/preload-scripts/index.ts
  • src/main/app/lifecycle.ts
  • src/main/app/instance.ts
  • src/main/controllers/tabs-controller/bounds.ts
  • src/main/controllers/windows-controller/types/extension-popup.ts
  • src/main/controllers/tabs-controller/tab-groups/split.ts
  • src/main/controllers/sessions-controller/default-session/index.ts
  • src/main/controllers/posthog-controller/posthog-error-capture-sdk/index.ts
  • src/main/controllers/app-menu-controller/menu/items/file.ts
  • src/main/controllers/tabs-controller/tab-groups/glance.ts
  • src/main/controllers/app-menu-controller/menu/items/archive.ts
  • src/main/modules/typed-event-emitter.ts
  • src/main/controllers/sessions-controller/protocols/hot-reload.ts
  • src/main/controllers/sessions-controller/intercept-rules/cors-bypass-custom-protocols.ts
  • src/main/controllers/windows-controller/types/settings.ts
  • src/main/controllers/app-menu-controller/index.ts
  • src/main/ipc/listeners-manager.ts
  • src/main/controllers/sessions-controller/web-requests/index.ts
  • src/main/controllers/quit-controller/index.ts
  • src/main/controllers/sessions-controller/handlers/index.ts
  • src/main/controllers/sessions-controller/intercept-rules/index.ts
  • src/main/controllers/windows-controller/index.ts
  • src/main/app/urls.ts
  • src/main/ipc/browser/tabs.ts
  • src/main/controllers/windows-controller/utils/close-preventer.ts
  • src/main/controllers/app-menu-controller/menu/items/spaces.ts
  • src/main/modules/output.ts
  • src/main/controllers/windows-controller/utils/browser/portal-component-windows.ts
  • src/main/controllers/windows-controller/interfaces/settings.ts
  • src/main/ipc/app/new-tab.ts
  • src/main/controllers/sessions-controller/protocols/_protocols/flow.ts
  • src/main/controllers/index.ts
  • src/main/controllers/sessions-controller/intercept-rules/user-agent-transformer.ts
  • src/main/modules/pdf-cache.ts
  • src/main/controllers/sessions-controller/intercept-rules/better-pdf-viewer.ts
  • src/main/controllers/windows-controller/types/index.ts
  • electron.vite.config.ts
  • src/main/ipc/browser/browser.ts
  • src/main/controllers/sessions-controller/protocols/_protocols/flow-external.ts
  • src/main/controllers/default-browser-controller/index.ts
  • src/main/controllers/profiles-controller/raw.ts
  • src/main/ipc/browser/interface.ts
  • src/main/ipc/browser/page.ts
  • src/main/app/platform.ts
  • src/main/controllers/tabs-controller/context-menu.ts
  • src/main/controllers/loaded-profiles-controller/index.ts
  • src/main/controllers/sessions-controller/index.ts
  • src/main/controllers/spaces-controller/raw.ts
  • src/main/controllers/posthog-controller/identify.ts
  • src/main/ipc/window/omnibox.ts
  • src/main/ipc/window/settings.ts
  • src/main/controllers/windows-controller/interfaces/onboarding.ts
  • src/main/controllers/windows-controller/types/onboarding.ts
  • src/main/controllers/app-menu-controller/menu/items/edit.ts
  • src/main/ipc/app/extensions.ts
  • src/main/controllers/sessions-controller/protocols/index.ts
  • src/main/controllers/windows-controller/interfaces/browser.ts
  • src/main/controllers/app-menu-controller/menu/items/view.ts
  • src/main/modules/extensions/main.ts
  • src/main/browser.ts
  • src/main/controllers/windows-controller/type-manager.ts
  • src/main/controllers/spaces-controller/index.ts
  • src/main/app/onboarding.ts
  • src/main/controllers/tabs-controller/tab-groups/index.ts
  • src/main/ipc/app/updates.ts
  • src/main/controllers/quit-controller/handlers/before-quit.ts
  • src/main/controllers/tabs-controller/tab.ts
  • src/main/controllers/profiles-controller/index.ts
  • src/main/ipc/session/profiles.ts
  • src/main/modules/content-blocker.ts
  • src/main/ipc/app/app.ts
  • src/main/controllers/windows-controller/types/base.ts
  • src/main/controllers/posthog-controller/index.ts
  • src/main/controllers/sessions-controller/protocols/utils.ts
  • src/main/controllers/windows-controller/types/browser.ts
  • src/main/ipc/session/spaces.ts
  • src/main/controllers/auto-update-controller/index.ts
  • src/main/controllers/app-menu-controller/menu/helpers.ts
  • src/main/ipc/app/actions.ts
  • src/main/controllers/sessions-controller/protocols/_protocols/flow-internal.ts
  • src/main/index.ts
  • src/main/modules/icons.ts
  • src/main/controllers/app-menu-controller/menu/items/app.ts
  • src/main/ipc/browser/navigation.ts
  • src/main/controllers/tabs-controller/index.ts
  • src/main/controllers/windows-controller/utils/browser/omnibox.ts
package.json

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

package.json: Use bun install instead of npm install or yarn install or pnpm install
Use bun run <script> instead of npm run <script> or yarn run <script> or pnpm run <script>

Files:

  • package.json
🧠 Learnings (2)
📚 Learning: 2025-07-24T08:49:07.217Z
Learnt from: CR
PR: MultiboxLabs/flow-browser#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-24T08:49:07.217Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>`

Applied to files:

  • package.json
📚 Learning: 2025-03-21T23:17:56.301Z
Learnt from: iamEvanYT
PR: MultiboxLabs/flow-browser#2
File: electron/browser/menu.ts:36-47
Timestamp: 2025-03-21T23:17:56.301Z
Learning: The `setOmniboxBounds` function accepts `null` as a valid argument, which means "use the default bounds" rather than requiring explicit bounds.

Applied to files:

  • src/main/controllers/windows-controller/utils/browser/omnibox.ts
🧬 Code graph analysis (66)
src/main/controllers/sessions-controller/preload-scripts/index.ts (1)
src/main/modules/paths.ts (1)
  • PATHS (18-23)
src/main/app/lifecycle.ts (3)
src/main/saving/onboarding.ts (1)
  • hasCompletedOnboarding (9-12)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/app/urls.ts (1)
  • handleOpenUrl (15-30)
src/main/app/instance.ts (2)
src/main/app/urls.ts (2)
  • isValidOpenerUrl (5-13)
  • handleOpenUrl (15-30)
src/main/modules/output.ts (1)
  • debugPrint (29-35)
src/main/controllers/sessions-controller/default-session/index.ts (5)
src/main/controllers/sessions-controller/protocols/index.ts (1)
  • registerProtocolsWithSession (24-36)
src/main/controllers/sessions-controller/intercept-rules/index.ts (1)
  • setupInterceptRules (7-16)
src/main/controllers/sessions-controller/preload-scripts/index.ts (1)
  • registerPreloadScripts (4-10)
src/main/controllers/sessions-controller/index.ts (1)
  • isDefaultSessionReady (51-53)
src/main/modules/utils.ts (1)
  • sleep (65-67)
src/main/controllers/app-menu-controller/menu/items/file.ts (4)
src/main/modules/shortcuts.ts (1)
  • getCurrentShortcut (107-111)
src/main/controllers/app-menu-controller/menu/helpers.ts (1)
  • getFocusedBrowserWindow (10-19)
src/main/ipc/app/new-tab.ts (1)
  • openNewTab (8-30)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/app-menu-controller/menu/items/archive.ts (2)
src/main/modules/shortcuts.ts (1)
  • getCurrentShortcut (107-111)
src/main/controllers/app-menu-controller/menu/helpers.ts (1)
  • getTabWcFromFocusedWindow (49-53)
src/main/controllers/sessions-controller/protocols/hot-reload.ts (1)
src/main/modules/utils.ts (1)
  • sleep (65-67)
src/main/controllers/sessions-controller/intercept-rules/cors-bypass-custom-protocols.ts (1)
src/main/controllers/sessions-controller/web-requests/index.ts (1)
  • createBetterWebRequest (675-780)
src/main/controllers/windows-controller/types/settings.ts (1)
src/main/controllers/windows-controller/types/base.ts (1)
  • BaseWindow (14-115)
src/main/controllers/app-menu-controller/index.ts (4)
src/main/controllers/spaces-controller/index.ts (1)
  • spacesController (229-229)
src/main/saving/shortcuts.ts (1)
  • shortcutsEmitter (18-18)
src/main/controllers/windows-controller/index.ts (1)
  • windowsController (110-110)
src/main/controllers/app-menu-controller/menu/items/spaces.ts (1)
  • createSpacesMenu (144-198)
src/main/controllers/quit-controller/index.ts (2)
src/main/controllers/quit-controller/handlers/can-quit.ts (1)
  • canQuit (2-4)
src/main/controllers/quit-controller/handlers/before-quit.ts (1)
  • beforeQuit (29-37)
src/main/controllers/sessions-controller/intercept-rules/index.ts (4)
src/main/controllers/sessions-controller/intercept-rules/user-agent-transformer.ts (1)
  • setupUserAgentTransformer (5-32)
src/main/controllers/sessions-controller/intercept-rules/cors-bypass-custom-protocols.ts (1)
  • setupCorsBypassForCustomProtocols (8-36)
src/main/controllers/sessions-controller/intercept-rules/better-pdf-viewer.ts (1)
  • setupBetterPdfViewer (7-56)
src/main/browser/utility/intercept-rules.ts (1)
  • setupInterceptRules (120-129)
src/main/controllers/windows-controller/index.ts (4)
src/main/controllers/windows-controller/types/base.ts (2)
  • id (37-39)
  • BaseWindow (14-115)
src/main/modules/typed-event-emitter.ts (1)
  • TypedEventEmitter (11-114)
src/main/controllers/windows-controller/type-manager.ts (1)
  • WindowTypeManager (13-115)
src/main/modules/output.ts (1)
  • debugPrint (29-35)
src/main/app/urls.ts (3)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/tabs-controller/index.ts (1)
  • tabsController (758-758)
src/main/modules/output.ts (1)
  • debugPrint (29-35)
src/main/ipc/browser/tabs.ts (5)
src/main/controllers/windows-controller/types/browser.ts (1)
  • BrowserWindow (31-183)
src/main/controllers/tabs-controller/index.ts (1)
  • tabsController (758-758)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/spaces-controller/index.ts (1)
  • spacesController (229-229)
src/main/controllers/tabs-controller/tab.ts (1)
  • Tab (115-989)
src/main/controllers/windows-controller/utils/close-preventer.ts (1)
src/main/controllers/app-menu-controller/menu/items/view.ts (1)
  • menuCloseTab (7-27)
src/main/controllers/app-menu-controller/menu/items/spaces.ts (4)
src/main/controllers/app-menu-controller/menu/helpers.ts (1)
  • getFocusedBrowserWindow (10-19)
src/main/ipc/session/spaces.ts (1)
  • setWindowSpace (52-55)
src/main/controllers/spaces-controller/index.ts (1)
  • spacesController (229-229)
src/main/controllers/windows-controller/index.ts (2)
  • windowsController (110-110)
  • browserWindowsManager (111-111)
src/main/controllers/windows-controller/utils/browser/portal-component-windows.ts (1)
src/main/controllers/windows-controller/types/browser.ts (1)
  • BrowserWindow (31-183)
src/main/controllers/windows-controller/interfaces/settings.ts (1)
src/main/controllers/windows-controller/index.ts (1)
  • windowsController (110-110)
src/main/ipc/app/new-tab.ts (5)
src/main/controllers/windows-controller/types/browser.ts (1)
  • BrowserWindow (31-183)
src/main/saving/settings.ts (1)
  • getSettingValueById (54-56)
src/main/controllers/spaces-controller/index.ts (1)
  • spacesController (229-229)
src/main/controllers/tabs-controller/index.ts (1)
  • tabsController (758-758)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/sessions-controller/protocols/_protocols/flow.ts (1)
src/main/controllers/loaded-profiles-controller/index.ts (1)
  • loadedProfilesController (325-325)
src/main/controllers/sessions-controller/intercept-rules/user-agent-transformer.ts (2)
src/main/controllers/sessions-controller/web-requests/index.ts (1)
  • createBetterWebRequest (675-780)
src/main/modules/user-agent.ts (1)
  • transformUserAgentHeader (6-48)
src/main/controllers/sessions-controller/intercept-rules/better-pdf-viewer.ts (4)
src/main/controllers/sessions-controller/web-requests/index.ts (1)
  • createBetterWebRequest (675-780)
src/main/saving/settings.ts (1)
  • getSettingValueById (54-56)
src/main/modules/utils.ts (1)
  • generateID (73-75)
src/main/modules/pdf-cache.ts (1)
  • addPdfResponseToCache (8-10)
src/main/ipc/browser/browser.ts (2)
src/main/controllers/loaded-profiles-controller/index.ts (1)
  • loadedProfilesController (325-325)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/default-browser-controller/index.ts (1)
src/main/controllers/default-browser-controller/windows-handler.ts (1)
  • registerAppForCurrentUserOnWindows (48-144)
src/main/controllers/profiles-controller/raw.ts (6)
src/main/modules/paths.ts (1)
  • FLOW_DATA_DIR (16-16)
src/main/controllers/profiles-controller/index.ts (1)
  • profilesController (182-182)
src/main/saving/datastore.ts (2)
  • getDatastore (310-324)
  • DataStoreData (14-14)
src/main/modules/utils.ts (2)
  • getCurrentTimestamp (92-94)
  • getAllDirectories (101-108)
src/main/modules/output.ts (1)
  • debugError (37-45)
src/main/controllers/spaces-controller/index.ts (1)
  • spacesController (229-229)
src/main/ipc/browser/interface.ts (2)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/windows-controller/types/browser.ts (1)
  • BrowserWindow (31-183)
src/main/ipc/browser/page.ts (1)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/app/platform.ts (2)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/modules/output.ts (1)
  • debugPrint (29-35)
src/main/controllers/tabs-controller/context-menu.ts (3)
src/main/controllers/tabs-controller/index.ts (2)
  • tabsController (758-758)
  • TabsController (757-757)
src/main/controllers/tabs-controller/tab.ts (1)
  • Tab (115-989)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/loaded-profiles-controller/index.ts (10)
src/main/modules/extensions/management.ts (1)
  • ExtensionManager (153-466)
src/main/modules/typed-event-emitter.ts (1)
  • TypedEventEmitter (11-114)
src/main/controllers/profiles-controller/index.ts (1)
  • profilesController (182-182)
src/main/controllers/sessions-controller/index.ts (1)
  • sessionsController (59-59)
src/main/modules/user-agent.ts (1)
  • transformUserAgentHeader (6-48)
src/main/controllers/tabs-controller/index.ts (2)
  • tabsController (758-758)
  • NEW_TAB_URL (15-15)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/ipc/session/spaces.ts (1)
  • setWindowSpace (52-55)
src/main/controllers/windows-controller/index.ts (1)
  • windowsController (110-110)
src/main/saving/settings.ts (1)
  • getSettingValueById (54-56)
src/main/controllers/sessions-controller/index.ts (7)
src/main/controllers/profiles-controller/index.ts (1)
  • profilesController (182-182)
src/main/controllers/sessions-controller/protocols/index.ts (1)
  • registerProtocolsWithSession (24-36)
src/main/controllers/sessions-controller/handlers/index.ts (1)
  • registerHandlersWithSession (5-55)
src/main/controllers/sessions-controller/preload-scripts/index.ts (1)
  • registerPreloadScripts (4-10)
src/main/controllers/sessions-controller/intercept-rules/index.ts (1)
  • setupInterceptRules (7-16)
src/main/controllers/sessions-controller/default-session/index.ts (2)
  • isDefaultSessionReady (16-16)
  • defaultSessionReady (18-26)
src/main/controllers/sessions-controller/web-requests/index.ts (2)
  • createBetterWebRequest (675-780)
  • createBetterSession (785-823)
src/main/controllers/spaces-controller/raw.ts (5)
src/main/controllers/spaces-controller/index.ts (1)
  • spacesController (229-229)
src/main/saving/datastore.ts (2)
  • getDatastore (310-324)
  • DataStoreData (14-14)
src/main/modules/output.ts (1)
  • debugError (37-45)
src/main/controllers/profiles-controller/index.ts (1)
  • profilesController (182-182)
src/main/modules/utils.ts (1)
  • getAllDirectories (101-108)
src/main/controllers/posthog-controller/identify.ts (1)
src/main/saving/settings.ts (1)
  • SettingsDataStore (7-7)
src/main/ipc/window/omnibox.ts (2)
src/main/modules/output.ts (1)
  • debugPrint (29-35)
src/main/controllers/windows-controller/index.ts (2)
  • windowsController (110-110)
  • browserWindowsManager (111-111)
src/main/controllers/windows-controller/interfaces/onboarding.ts (1)
src/main/controllers/windows-controller/index.ts (1)
  • windowsController (110-110)
src/main/controllers/app-menu-controller/menu/items/edit.ts (2)
src/main/controllers/app-menu-controller/menu/helpers.ts (1)
  • getFocusedBrowserWindow (10-19)
src/main/ipc/app/actions.ts (1)
  • fireCopyLinkAction (4-6)
src/main/ipc/app/extensions.ts (3)
src/main/controllers/loaded-profiles-controller/index.ts (1)
  • loadedProfilesController (325-325)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/spaces-controller/index.ts (1)
  • spacesController (229-229)
src/main/controllers/sessions-controller/protocols/index.ts (3)
src/main/controllers/sessions-controller/protocols/_protocols/flow.ts (1)
  • registerFlowProtocol (22-165)
src/main/controllers/sessions-controller/protocols/_protocols/flow-internal.ts (1)
  • registerFlowInternalProtocol (26-98)
src/main/controllers/sessions-controller/protocols/_protocols/flow-external.ts (1)
  • registerFlowExternalProtocol (15-36)
src/main/controllers/windows-controller/interfaces/browser.ts (4)
src/main/controllers/windows-controller/index.ts (2)
  • browserWindowsManager (111-111)
  • windowsController (110-110)
src/main/modules/output.ts (1)
  • debugPrint (29-35)
src/main/modules/electron-components.ts (1)
  • waitForElectronComponentsToBeReady (1-15)
src/main/controllers/windows-controller/types/browser.ts (2)
  • BrowserWindowType (14-14)
  • BrowserWindowCreationOptions (16-21)
src/main/controllers/app-menu-controller/menu/items/view.ts (4)
src/main/controllers/app-menu-controller/menu/helpers.ts (4)
  • getFocusedWindow (6-8)
  • getTab (21-35)
  • getFocusedBrowserWindow (10-19)
  • getTabWcFromFocusedWindow (49-53)
src/main/controllers/windows-controller/index.ts (1)
  • browserWindowsManager (111-111)
src/main/modules/shortcuts.ts (1)
  • getCurrentShortcut (107-111)
src/main/ipc/browser/interface.ts (1)
  • toggleSidebar (20-22)
src/main/modules/extensions/main.ts (1)
src/main/controllers/sessions-controller/index.ts (1)
  • sessionsController (59-59)
src/main/browser.ts (5)
src/main/app/urls.ts (1)
  • processInitialUrl (32-39)
src/main/app/instance.ts (1)
  • setupSecondInstanceHandling (9-19)
src/main/app/platform.ts (1)
  • setupPlatformIntegration (44-52)
src/main/app/onboarding.ts (1)
  • runOnboardingOrInitialWindow (6-18)
src/main/app/lifecycle.ts (1)
  • setupAppLifecycle (6-31)
src/main/controllers/windows-controller/type-manager.ts (2)
src/main/controllers/windows-controller/types/base.ts (2)
  • BaseWindow (14-115)
  • id (37-39)
src/main/controllers/windows-controller/index.ts (3)
  • WindowsController (109-109)
  • WindowType (14-14)
  • windowsController (110-110)
src/main/controllers/spaces-controller/index.ts (5)
src/main/controllers/spaces-controller/raw.ts (2)
  • SpaceData (37-37)
  • RawSpacesController (62-197)
src/main/modules/typed-event-emitter.ts (1)
  • TypedEventEmitter (11-114)
src/main/modules/utils.ts (1)
  • generateID (73-75)
src/main/controllers/profiles-controller/index.ts (1)
  • profilesController (182-182)
src/main/modules/output.ts (1)
  • debugError (37-45)
src/main/app/onboarding.ts (4)
src/main/modules/output.ts (1)
  • debugPrint (29-35)
src/main/saving/onboarding.ts (1)
  • hasCompletedOnboarding (9-12)
src/main/controllers/windows-controller/interfaces/onboarding.ts (1)
  • onboarding (6-34)
src/main/saving/tabs.ts (1)
  • createInitialWindow (153-163)
src/main/ipc/app/updates.ts (3)
src/main/controllers/auto-update-controller/index.ts (1)
  • autoUpdateController (217-217)
src/shared/types/updates.ts (1)
  • UpdateStatus (3-7)
src/main/ipc/listeners-manager.ts (1)
  • sendMessageToListeners (35-44)
src/main/controllers/quit-controller/handlers/before-quit.ts (1)
src/main/controllers/loaded-profiles-controller/index.ts (1)
  • loadedProfilesController (325-325)
src/main/controllers/tabs-controller/tab.ts (5)
src/main/modules/utils.ts (1)
  • getCurrentTimestamp (92-94)
src/main/controllers/tabs-controller/context-menu.ts (1)
  • createTabContextMenu (33-126)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/ipc/session/spaces.ts (1)
  • setWindowSpace (52-55)
src/main/controllers/tabs-controller/tab-groups/glance.ts (1)
  • GlanceTabGroup (3-21)
src/main/controllers/profiles-controller/index.ts (4)
src/main/controllers/profiles-controller/raw.ts (2)
  • ProfileData (37-37)
  • RawProfilesController (57-171)
src/main/modules/typed-event-emitter.ts (1)
  • TypedEventEmitter (11-114)
src/main/modules/utils.ts (1)
  • generateID (73-75)
src/main/modules/output.ts (1)
  • debugError (37-45)
src/main/ipc/session/profiles.ts (4)
src/main/controllers/profiles-controller/index.ts (2)
  • profilesController (182-182)
  • ProfileData (21-21)
src/main/controllers/profiles-controller/raw.ts (1)
  • ProfileData (37-37)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/spaces-controller/index.ts (1)
  • spacesController (229-229)
src/main/modules/content-blocker.ts (3)
src/main/controllers/sessions-controller/index.ts (1)
  • unifiedWebRequests (61-64)
src/main/saving/settings.ts (1)
  • getSettingValueById (54-56)
src/main/controllers/loaded-profiles-controller/index.ts (1)
  • loadedProfilesController (325-325)
src/main/ipc/app/app.ts (1)
src/main/controllers/default-browser-controller/index.ts (1)
  • defaultBrowserController (46-46)
src/main/controllers/windows-controller/types/base.ts (4)
src/main/modules/typed-event-emitter.ts (1)
  • TypedEventEmitter (11-114)
src/main/controllers/windows-controller/index.ts (1)
  • WindowType (14-14)
src/main/controllers/windows-controller/types/browser.ts (1)
  • BrowserWindow (31-183)
src/main/ipc/listeners-manager.ts (1)
  • sendMessageToListenersWithWebContents (46-61)
src/main/controllers/posthog-controller/index.ts (2)
src/main/controllers/posthog-controller/posthog-error-capture-sdk/index.ts (1)
  • ErrorTracking (12-74)
src/main/controllers/posthog-controller/identify.ts (1)
  • _getPosthogIdentifier (12-17)
src/main/controllers/windows-controller/types/browser.ts (11)
src/main/controllers/windows-controller/types/base.ts (2)
  • BaseWindow (14-115)
  • BaseWindowEvents (6-8)
src/main/ipc/browser/page.ts (1)
  • PageBounds (4-9)
src/main/controllers/windows-controller/utils/view-manager.ts (1)
  • ViewManager (3-87)
src/main/controllers/windows-controller/utils/browser/omnibox.ts (1)
  • Omnibox (10-238)
src/main/controllers/sessions-controller/index.ts (1)
  • sessionsController (59-59)
src/main/ipc/browser/interface.ts (1)
  • fireWindowStateChanged (105-107)
src/main/controllers/spaces-controller/index.ts (1)
  • spacesController (229-229)
src/main/controllers/windows-controller/utils/browser/portal-component-windows.ts (1)
  • initializePortalComponentWindows (8-102)
src/main/ipc/listeners-manager.ts (1)
  • sendMessageToListenersWithWebContents (46-61)
src/main/controllers/tabs-controller/index.ts (1)
  • tabsController (758-758)
src/main/controllers/app-menu-controller/index.ts (1)
  • appMenuController (48-48)
src/main/ipc/session/spaces.ts (4)
src/main/controllers/spaces-controller/index.ts (3)
  • spacesController (229-229)
  • SpaceData (23-23)
  • SpaceOrderMap (11-11)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/windows-controller/types/browser.ts (1)
  • BrowserWindow (31-183)
src/main/ipc/listeners-manager.ts (1)
  • sendMessageToListeners (35-44)
src/main/controllers/auto-update-controller/index.ts (6)
src/renderer/src/components/main/platform.tsx (1)
  • Platform (6-6)
src/main/modules/typed-event-emitter.ts (1)
  • TypedEventEmitter (11-114)
src/main/modules/output.ts (1)
  • debugPrint (29-35)
src/main/modules/utils.ts (1)
  • sleep (65-67)
src/shared/types/updates.ts (1)
  • UpdateStatus (3-7)
src/main/saving/settings.ts (3)
  • getSettingValueById (54-56)
  • onSettingsCached (51-51)
  • settingsEmitter (12-12)
src/main/controllers/app-menu-controller/menu/helpers.ts (3)
src/main/controllers/windows-controller/index.ts (2)
  • windowsController (110-110)
  • browserWindowsManager (111-111)
src/main/controllers/windows-controller/types/base.ts (1)
  • BaseWindow (14-115)
src/main/controllers/tabs-controller/index.ts (1)
  • tabsController (758-758)
src/main/ipc/app/actions.ts (1)
src/main/controllers/windows-controller/types/browser.ts (1)
  • BrowserWindow (31-183)
src/main/controllers/sessions-controller/protocols/_protocols/flow-internal.ts (1)
src/main/controllers/tabs-controller/index.ts (1)
  • tabsController (758-758)
src/main/modules/icons.ts (2)
src/main/controllers/windows-controller/index.ts (1)
  • windowsController (110-110)
src/main/controllers/windows-controller/types/base.ts (1)
  • id (37-39)
src/main/controllers/app-menu-controller/menu/items/app.ts (1)
src/main/controllers/default-browser-controller/index.ts (1)
  • defaultBrowserController (46-46)
src/main/ipc/browser/navigation.ts (2)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/tabs-controller/index.ts (1)
  • tabsController (758-758)
src/main/controllers/tabs-controller/index.ts (8)
src/main/modules/typed-event-emitter.ts (1)
  • TypedEventEmitter (11-114)
src/main/controllers/tabs-controller/tab.ts (1)
  • Tab (115-989)
src/main/controllers/tabs-controller/tab-groups/index.ts (1)
  • TabGroup (26-26)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/controllers/spaces-controller/index.ts (1)
  • spacesController (229-229)
src/main/controllers/loaded-profiles-controller/index.ts (1)
  • loadedProfilesController (325-325)
src/main/controllers/tabs-controller/tab-groups/glance.ts (1)
  • GlanceTabGroup (3-21)
src/main/controllers/tabs-controller/tab-groups/split.ts (1)
  • SplitTabGroup (3-7)
src/main/controllers/windows-controller/utils/browser/omnibox.ts (2)
src/main/controllers/windows-controller/interfaces/browser.ts (1)
  • browserWindowsController (30-86)
src/main/modules/output.ts (1)
  • debugPrint (29-35)
🪛 LanguageTool
src/main/controllers/sessions-controller/README.md

[style] ~17-~17: This phrase is redundant. Consider using “outside”.
Context: ... The only thing that should be required outside of this controller is the index.ts file....

(OUTSIDE_OF)


[style] ~18-~18: This phrase is redundant. Consider using “outside”.
Context: ...les are internal and should not be used outside of this controller.

(OUTSIDE_OF)

src/main/controllers/quit-controller/README.md

[style] ~12-~12: This phrase is redundant. Consider using “outside”.
Context: ... The only thing that should be required outside of this controller is the index.ts file....

(OUTSIDE_OF)


[style] ~13-~13: This phrase is redundant. Consider using “outside”.
Context: ...les are internal and should not be used outside of this controller.

(OUTSIDE_OF)

src/main/controllers/windows-controller/README.md

[grammar] ~3-~3: Ensure spelling is correct
Context: ...ll BrowserWindows from electron and seperates them into different types of windows to...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[style] ~15-~15: This phrase is redundant. Consider using “outside”.
Context: ... The only thing that should be required outside of this controller is the index.ts file ...

(OUTSIDE_OF)


[style] ~16-~16: This phrase is redundant. Consider using “outside”.
Context: ...les are internal and should not be used outside of this controller.

(OUTSIDE_OF)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build (ubuntu-latest)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (windows-latest)
  • GitHub Check: build (ubuntu-24.04-arm)
  • GitHub Check: build (macos-15-intel)

Comment on lines 8 to +11
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
},
"typescript.tsdk": "node_modules/typescript/lib"
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Minor: Consider grouping the TypeScript SDK setting with language-scoped settings.

The new typescript.tsdk setting is currently at the root level, separate from the language-specific formatter configurations. While this is functionally correct, consider organizing it within a "[typescript]" scope or adding a comment to clarify its purpose, for better maintainability as the configuration grows.

Example refactor (optional):

  "[typescript]": {
-   "editor.defaultFormatter": "esbenp.prettier-vscode"
+   "editor.defaultFormatter": "esbenp.prettier-vscode",
+   "typescript.tsdk": "node_modules/typescript/lib"
  },

Alternatively, you can keep it at the root level if you prefer global scope; this is purely a matter of organization preference.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
.vscode/settings.json around lines 8 to 11: the typescript.tsdk setting is at
the root while formatter settings are language-scoped; to improve organization
either move "typescript.tsdk" into a "[typescript]" scope alongside
language-specific settings or add an inline comment above the root-level setting
explaining it is intentionally global, ensuring consistency and maintainability
as the config grows.

Comment on lines +10 to +15
app.on("second-instance", async (_event, commandLine) => {
const url = commandLine.pop();
if (url && isValidOpenerUrl(url)) {
const shouldCreate = shouldCreateNewWindow(commandLine);
handleOpenUrl(shouldCreate, url);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Don't mutate argv; robustly detect URL and flag.

Using commandLine.pop() can drop --new-window (if last) or grab the working directory instead of the URL. Parse without mutation and find the first valid URL. Also await and guard handleOpenUrl to avoid unhandled rejections.

Apply:

-  app.on("second-instance", async (_event, commandLine) => {
-    const url = commandLine.pop();
-    if (url && isValidOpenerUrl(url)) {
-      const shouldCreate = shouldCreateNewWindow(commandLine);
-      handleOpenUrl(shouldCreate, url);
-    }
-  });
+  app.on("second-instance", async (_event, commandLine) => {
+    const args = [...commandLine]; // do not mutate
+    const useNewWindow = shouldCreateNewWindow(args);
+    const urlArg = args.find((a) => isValidOpenerUrl(a));
+    if (!urlArg) return;
+    try {
+      await handleOpenUrl(useNewWindow, urlArg);
+    } catch (err) {
+      console.error("second-instance open failed:", err);
+    }
+  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
app.on("second-instance", async (_event, commandLine) => {
const url = commandLine.pop();
if (url && isValidOpenerUrl(url)) {
const shouldCreate = shouldCreateNewWindow(commandLine);
handleOpenUrl(shouldCreate, url);
}
app.on("second-instance", async (_event, commandLine) => {
const args = [...commandLine]; // do not mutate
const useNewWindow = shouldCreateNewWindow(args);
const urlArg = args.find((a) => isValidOpenerUrl(a));
if (!urlArg) return;
try {
await handleOpenUrl(useNewWindow, urlArg);
} catch (err) {
console.error("second-instance open failed:", err);
}
});
🤖 Prompt for AI Agents
In src/main/app/instance.ts around lines 10 to 15, the handler mutates
commandLine with commandLine.pop() and may drop flags like --new-window or
misidentify the working directory as the URL; instead, do not mutate argv — scan
commandLine for the first element that passes isValidOpenerUrl and separately
detect the presence of the --new-window flag (or other flags) without removing
items; call handleOpenUrl with await and wrap it in a try/catch to handle and
log any rejection so there are no unhandled promise rejections.

Comment on lines +6 to +18
export function runOnboardingOrInitialWindow() {
debugPrint("INITIALIZATION", "grabbing hasCompletedOnboarding()");
hasCompletedOnboarding().then((completed) => {
debugPrint("INITIALIZATION", "grabbed hasCompletedOnboarding()", completed);
if (!completed) {
onboarding.show();
debugPrint("INITIALIZATION", "show onboarding window");
} else {
createInitialWindow();
debugPrint("INITIALIZATION", "show browser window");
}
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add error handling for the promise chain.

The function doesn't handle potential rejections from hasCompletedOnboarding(). If the promise rejects, it will result in an unhandled promise rejection, potentially causing the app to fail silently during initialization.

Consider one of these approaches:

Option 1: Add error handling to the promise chain

 export function runOnboardingOrInitialWindow() {
   debugPrint("INITIALIZATION", "grabbing hasCompletedOnboarding()");
   hasCompletedOnboarding().then((completed) => {
     debugPrint("INITIALIZATION", "grabbed hasCompletedOnboarding()", completed);
     if (!completed) {
       onboarding.show();
       debugPrint("INITIALIZATION", "show onboarding window");
     } else {
       createInitialWindow();
       debugPrint("INITIALIZATION", "show browser window");
     }
+  }).catch((error) => {
+    debugPrint("INITIALIZATION", "Error during onboarding check:", error);
+    // Fallback: show onboarding window or handle gracefully
+    onboarding.show();
   });
 }

Option 2: Make the function async and return the promise

-export function runOnboardingOrInitialWindow() {
+export async function runOnboardingOrInitialWindow() {
   debugPrint("INITIALIZATION", "grabbing hasCompletedOnboarding()");
-  hasCompletedOnboarding().then((completed) => {
+  try {
+    const completed = await hasCompletedOnboarding();
     debugPrint("INITIALIZATION", "grabbed hasCompletedOnboarding()", completed);
     if (!completed) {
       onboarding.show();
       debugPrint("INITIALIZATION", "show onboarding window");
     } else {
       createInitialWindow();
       debugPrint("INITIALIZATION", "show browser window");
     }
-  });
+  } catch (error) {
+    debugPrint("INITIALIZATION", "Error during onboarding check:", error);
+    onboarding.show();
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function runOnboardingOrInitialWindow() {
debugPrint("INITIALIZATION", "grabbing hasCompletedOnboarding()");
hasCompletedOnboarding().then((completed) => {
debugPrint("INITIALIZATION", "grabbed hasCompletedOnboarding()", completed);
if (!completed) {
onboarding.show();
debugPrint("INITIALIZATION", "show onboarding window");
} else {
createInitialWindow();
debugPrint("INITIALIZATION", "show browser window");
}
});
}
export function runOnboardingOrInitialWindow() {
debugPrint("INITIALIZATION", "grabbing hasCompletedOnboarding()");
hasCompletedOnboarding().then((completed) => {
debugPrint("INITIALIZATION", "grabbed hasCompletedOnboarding()", completed);
if (!completed) {
onboarding.show();
debugPrint("INITIALIZATION", "show onboarding window");
} else {
createInitialWindow();
debugPrint("INITIALIZATION", "show browser window");
}
}).catch((error) => {
debugPrint("INITIALIZATION", "Error during onboarding check:", error);
// Fallback: show onboarding window or handle gracefully
onboarding.show();
});
}
Suggested change
export function runOnboardingOrInitialWindow() {
debugPrint("INITIALIZATION", "grabbing hasCompletedOnboarding()");
hasCompletedOnboarding().then((completed) => {
debugPrint("INITIALIZATION", "grabbed hasCompletedOnboarding()", completed);
if (!completed) {
onboarding.show();
debugPrint("INITIALIZATION", "show onboarding window");
} else {
createInitialWindow();
debugPrint("INITIALIZATION", "show browser window");
}
});
}
export async function runOnboardingOrInitialWindow() {
debugPrint("INITIALIZATION", "grabbing hasCompletedOnboarding()");
try {
const completed = await hasCompletedOnboarding();
debugPrint("INITIALIZATION", "grabbed hasCompletedOnboarding()", completed);
if (!completed) {
onboarding.show();
debugPrint("INITIALIZATION", "show onboarding window");
} else {
createInitialWindow();
debugPrint("INITIALIZATION", "show browser window");
}
} catch (error) {
debugPrint("INITIALIZATION", "Error during onboarding check:", error);
onboarding.show();
}
}
🤖 Prompt for AI Agents
In src/main/app/onboarding.ts around lines 6 to 18, the call to
hasCompletedOnboarding() lacks rejection handling and can trigger an unhandled
promise rejection; either add a .catch handler to the existing promise chain
that logs the error (with context) and falls back to createInitialWindow() (so
the app still starts), or convert runOnboardingOrInitialWindow to async, await
hasCompletedOnboarding() inside a try/catch, handle errors by logging and
creating the initial window, and ensure the function returns the resulting
promise so callers can await it.

Comment on lines +5 to +16
function setupWindowsUserTasks() {
app.setUserTasks([
{
program: process.execPath,
arguments: "--new-window",
iconPath: process.execPath,
iconIndex: 0,
title: "New Window",
description: "Create a new window"
}
]);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Set Windows user tasks after app is ready; add cleanup on quit

Safer to configure tasks post‑ready and clear on quit.

-function setupWindowsUserTasks() {
-  app.setUserTasks([
+function setupWindowsUserTasks() {
+  app.whenReady().then(() => app.setUserTasks([
     {
       program: process.execPath,
       arguments: "--new-window",
       iconPath: process.execPath,
       iconIndex: 0,
       title: "New Window",
       description: "Create a new window"
-    }
-  ]);
+    }
+  ]));
+  app.on("before-quit", () => app.setUserTasks([]));
 }
🤖 Prompt for AI Agents
In src/main/app/platform.ts around lines 5 to 16, the user task setup is
currently executed immediately; move the setup to run after Electron app is
ready and add cleanup on quit. Wrap the setUserTasks call inside
app.whenReady().then(...) (or await app.whenReady()) so tasks are configured
only after readiness, and register an app.on('will-quit' or 'quit') handler that
clears tasks via app.setUserTasks([]) to remove them on exit.

Comment on lines +21 to +27
dockMenu.append(
new MenuItem({
label: "New Window",
click: () => {
browserWindowsController.create();
}
})
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Avoid floating promise on window creation

If lint rules enforce no‑floating‑promises, discard explicitly.

-      click: () => {
-        browserWindowsController.create();
-      }
+      click: () => {
+        void browserWindowsController.create();
+      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
dockMenu.append(
new MenuItem({
label: "New Window",
click: () => {
browserWindowsController.create();
}
})
dockMenu.append(
new MenuItem({
label: "New Window",
click: () => {
void browserWindowsController.create();
}
})
🤖 Prompt for AI Agents
In src/main/app/platform.ts around lines 21 to 27, the click handler calls
browserWindowsController.create() and leaves its returned promise unhandled;
update the handler to explicitly discard or handle the promise to satisfy
no‑floating‑promises lint rules — e.g. prefix the call with "void" to
intentionally ignore the result or attach a .catch(...) to log/handle errors so
the promise is not left floating.

Comment on lines +48 to 50
ipcMain.handle("spaces:reorder", async (_event, orderMap: SpaceOrderMap) => {
return await spacesController.reorder(orderMap);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate reorder payload server-side

orderMap contains profileId and spaceId pairs from the renderer. Validate each entry against the authoritative space profile before calling reorder to prevent cross-profile tampering.

Example guard inside the handler:

const validated = [];
for (const item of orderMap) {
  const space = await spacesController.get(item.spaceId);
  if (!space || space.profileId !== item.profileId) {
    throw new Error("Invalid reorder entry");
  }
  validated.push(item);
}
return await spacesController.reorder(validated);
🤖 Prompt for AI Agents
In src/main/ipc/session/spaces.ts around lines 48-50, the handler accepts an
orderMap from the renderer without server-side validation, allowing potential
cross-profile tampering; for each item in orderMap, fetch the authoritative
space (await spacesController.get(item.spaceId)), verify it exists and that its
profileId matches item.profileId, accumulate only the validated items into a new
array, and if any entry is missing or mismatched throw an error (or return a
clear IPC error) instead of calling reorder; finally call
spacesController.reorder with the validated array and ensure awaits and errors
are propagated properly.

Comment on lines +60 to +62
spacesController.on("space-created", fireOnSpacesChanged);
spacesController.on("space-updated", fireOnSpacesChanged);
spacesController.on("space-deleted", fireOnSpacesChanged);
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

LGTM: spaces change events wiring

Broadcasts on created/updated/deleted via listeners manager. Consider including minimal payloads later for selective updates.

🤖 Prompt for AI Agents
In src/main/ipc/session/spaces.ts around lines 60–62 the three space events are
correctly wired to fireOnSpacesChanged; to support selective updates, change the
emitter and handler to pass a minimal payload (e.g., { id, action, meta })
instead of no args: update emit sites to include that payload, update the
spacesController.on callbacks to forward the payload to fireOnSpacesChanged
(fireOnSpacesChanged(payload)), and update fireOnSpacesChanged to accept and
propagate the payload to listeners so consumers can react only to relevant
changes.

const blocker = await this.blockerInstancePromise;
for (const session of this.blockedSessions) {
blocker.disableBlockingInSession(createBetterSession(session, SESSION_KEY));
blocker.disableBlockingInSession(unifiedWebRequests.createSession(session, SESSION_KEY));
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Document the SESSION_KEY constant usage.

The SESSION_KEY constant is passed to createSession() but its purpose and behavior are not documented. Based on the relevant code snippets, it appears to be used for caching/deduplication, but this should be clarified.

Add a comment explaining the SESSION_KEY:

 type BlockerInstanceType = "all" | "adsAndTrackers" | "adsOnly";
 
+// Used to create a unified session wrapper for consistent content blocking across profiles
 const SESSION_KEY = "content-blocker";

Also applies to: 85-85

🤖 Prompt for AI Agents
In src/main/modules/content-blocker.ts around lines 63 and 85, the SESSION_KEY
passed to unifiedWebRequests.createSession(session, SESSION_KEY) is
undocumented; add a concise inline comment explaining that SESSION_KEY is the
session identifier used by createSession for caching and deduplication of
request/state across calls (e.g., must be unique per logical browsing session,
stable for dedupe, not secret), note expected format and lifetime (how long
entries are cached) and any security/privacy considerations (don’t use PII), and
place the comment immediately where SESSION_KEY is defined or immediately above
these createSession usages so future readers understand its purpose and
constraints.

Comment on lines +123 to 125
loadedProfilesController.on("profile-loaded", () => {
this.updateConfig();
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider handling profile unloading events.

The code subscribes to profile-loaded events but doesn't handle profile unloading. When profiles are unloaded, their sessions should be removed from this.blockedSessions to prevent memory leaks and avoid attempting to apply blocking to destroyed sessions.

Check if loadedProfilesController emits a profile unload event and subscribe to it:

#!/bin/bash
# Search for profile unload/remove events in the controller
ast-grep --pattern 'emit($$$, "profile-$_", $$$)'
rg -A 3 'profile-.*(?:unload|remove|destroy|close)' src/main/controllers/loaded-profiles-controller/

If such an event exists, add a handler:

loadedProfilesController.on("profile-unloaded", (profileId) => {
  // Remove the session from blockedSessions
  const profile = loadedProfilesController.get(profileId);
  if (profile) {
    const index = this.blockedSessions.indexOf(profile.session);
    if (index > -1) {
      this.blockedSessions.splice(index, 1);
    }
  }
});
🤖 Prompt for AI Agents
In src/main/modules/content-blocker.ts around lines 123 to 125, the code
subscribes to loadedProfilesController "profile-loaded" events but does not
handle profile unload/removal, which can leave stale sessions in
this.blockedSessions; add a listener for the controller's profile
unload/remove/close event (match the actual event name used by
loadedProfilesController) and in that handler remove the corresponding
profile.session from this.blockedSessions (lookup the profile by id via
loadedProfilesController.get(id), find the session index in this.blockedSessions
and splice it out) so blockedSessions does not retain destroyed sessions.

Comment on lines +6 to +18
const PDF_CACHE = new Map<string, Response>();

export function addPdfResponseToCache(key: string, response: Response) {
PDF_CACHE.set(key, response);
}

export function getPdfResponseFromCache(key: string): Response | undefined {
return PDF_CACHE.get(key);
}

export function removePdfResponseFromCache(key: string) {
PDF_CACHE.delete(key);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add cache size limit or eviction policy to prevent memory leak.

The PDF cache has no size limit or eviction policy, which could lead to unbounded memory growth if many PDFs are cached. Since Response objects can hold large binary data, this could become a significant memory leak.

Consider implementing one of these strategies:

Option 1: Add a maximum cache size with LRU eviction

+const MAX_CACHE_SIZE = 50; // Adjust based on requirements
 const PDF_CACHE = new Map<string, Response>();
+const cacheAccessOrder: string[] = [];

 export function addPdfResponseToCache(key: string, response: Response) {
+  if (PDF_CACHE.size >= MAX_CACHE_SIZE && !PDF_CACHE.has(key)) {
+    const oldestKey = cacheAccessOrder.shift();
+    if (oldestKey) PDF_CACHE.delete(oldestKey);
+  }
   PDF_CACHE.set(key, response);
+  // Move to end (most recently used)
+  const index = cacheAccessOrder.indexOf(key);
+  if (index > -1) cacheAccessOrder.splice(index, 1);
+  cacheAccessOrder.push(key);
 }

 export function getPdfResponseFromCache(key: string): Response | undefined {
+  const response = PDF_CACHE.get(key);
+  if (response) {
+    // Move to end (most recently used)
+    const index = cacheAccessOrder.indexOf(key);
+    if (index > -1) cacheAccessOrder.splice(index, 1);
+    cacheAccessOrder.push(key);
+  }
-  return PDF_CACHE.get(key);
+  return response;
 }

Option 2: Add a cache clearing function

+export function clearPdfCache() {
+  PDF_CACHE.clear();
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const PDF_CACHE = new Map<string, Response>();
export function addPdfResponseToCache(key: string, response: Response) {
PDF_CACHE.set(key, response);
}
export function getPdfResponseFromCache(key: string): Response | undefined {
return PDF_CACHE.get(key);
}
export function removePdfResponseFromCache(key: string) {
PDF_CACHE.delete(key);
}
const PDF_CACHE = new Map<string, Response>();
export function addPdfResponseToCache(key: string, response: Response) {
PDF_CACHE.set(key, response);
}
export function getPdfResponseFromCache(key: string): Response | undefined {
return PDF_CACHE.get(key);
}
export function removePdfResponseFromCache(key: string) {
PDF_CACHE.delete(key);
}
export function clearPdfCache() {
PDF_CACHE.clear();
}
🤖 Prompt for AI Agents
In src/main/modules/pdf-cache.ts around lines 6 to 18, the in-memory PDF_CACHE
currently has no size limit or eviction policy which can cause unbounded memory
growth; implement a bounded cache with an LRU eviction policy (or at minimum a
clear function) by: replace the simple Map with an LRU-capable structure (either
implement a small LRU using a Map + usage order tracking or import a lightweight
LRU cache lib), add a MAX_ENTRIES constant, on addPdfResponseToCache check if
cache size >= MAX_ENTRIES and evict the least-recently-used entry before
inserting, update getPdfResponseFromCache to mark entries as recently used, and
provide an exported clearPdfCache() function to allow manual clearing; ensure
removePdfResponseFromCache still deletes specific keys and that response bodies
are properly released/closed if needed to avoid retaining large buffers.

@iamEvanYT iamEvanYT merged commit 1729c42 into main Oct 29, 2025
9 of 10 checks passed
@iamEvanYT iamEvanYT deleted the evan/restructure branch October 29, 2025 00:24
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