Skip to content

fix(settings): enhance navigation handling and normalize payload stru… - #1513

Merged
zerob13 merged 1 commit into
devfrom
spotlight-fix
Apr 22, 2026
Merged

fix(settings): enhance navigation handling and normalize payload stru…#1513
zerob13 merged 1 commit into
devfrom
spotlight-fix

Conversation

@zhangmo8

@zhangmo8 zhangmo8 commented Apr 22, 2026

Copy link
Copy Markdown
Collaborator

…cture

Summary by CodeRabbit

  • Bug Fixes

    • Improved settings window navigation reliability with enhanced URL routing
    • Better handling of pending navigation requests during settings window initialization
    • Strengthened validation and normalization of navigation parameters
  • Improvements

    • Optimized settings window startup sequence for more consistent performance across states

@coderabbitai

coderabbitai Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The changes enhance settings window navigation by introducing URL-based navigation interception, message queuing, and payload validation. The main process now validates navigation requests early, computes appropriate target URLs, and can reload the settings window with queued messages before the window fully initializes.

Changes

Cohort / File(s) Summary
Settings Window Navigation Refactor
src/main/presenter/windowPresenter/index.ts
Introduced early navigation interception in sendToWindow() and refactored createSettingsWindow() to support URL-based navigation reloads. Added three new helpers: tryNavigateSettingsWindowByUrl() (validates window, converts/filters payloads, manages reloads), toSettingsNavigationPayload() (extracts/validates route names and params), and getSettingsWindowTargetUrl() (centralizes dev/packaged URL construction). Settings window can now reload with navigation data via URL queuing before becoming fully ready.
Settings Navigation Payload Normalization
src/renderer/api/SettingsClient.ts
Added normalizeSettingsNavigationPayload() helper to sanitize navigation payloads by converting all params to strings and omitting empty params. Updated openSettings() to use the normalized payload instead of passing raw navigation data.

Sequence Diagram(s)

sequenceDiagram
    participant Main as Main Process<br/>(windowPresenter)
    participant Validate as Payload<br/>Validation
    participant Window as Settings<br/>Window
    participant Queue as Message<br/>Queue

    Main->>Validate: tryNavigateSettingsWindowByUrl(args)
    Validate->>Validate: toSettingsNavigationPayload(args[0])
    alt Valid & matches 'settings-provider'
        Validate->>Main: payload extracted
        Main->>Main: getSettingsWindowTargetUrl(navigation)
        Main->>Window: loadURL(targetUrl)
        activate Window
        Window-->>Main: success/failure
        deactivate Window
        Main->>Queue: queue {channel, args:[navigation]}
    else Invalid or filtered out
        Validate-->>Main: null
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

codex

Poem

🐰 A settings window now bends to our will,
With URLs queuing and validation to fill,
Navigation flows smoother through payload-cleaned streams,
The presenter refactors our digital dreams! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: enhancing settings navigation handling and normalizing payload structure, which aligns with both file modifications.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch spotlight-fix

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (2)
src/main/presenter/windowPresenter/index.ts (2)

16-19: ⚠️ Potential issue | 🟡 Minor

Validate routeName before casting it to SettingsNavigationPayload.

Line 1544 accepts any string and then casts it to the route union, so malformed IPC payloads can still be queued/sent as “typed” navigation. Reject route names that are not in the shared settings navigation registry.

🛡️ Proposed fix
 import {
+  SETTINGS_NAVIGATION_ITEMS,
   resolveSettingsNavigationPath,
   type SettingsNavigationPayload
 } from '@shared/settingsNavigation'
@@
-    if (typeof candidate.routeName !== 'string') {
+    if (
+      typeof candidate.routeName !== 'string' ||
+      !SETTINGS_NAVIGATION_ITEMS.some((item) => item.routeName === candidate.routeName)
+    ) {
       return null
     }

Also applies to: 1544-1564

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

In `@src/main/presenter/windowPresenter/index.ts` around lines 16 - 19, The
handler currently casts an arbitrary string variable routeName to
SettingsNavigationPayload and enqueues/sends it without validation; change that
code to validate routeName against the shared registry before casting by calling
resolveSettingsNavigationPath(routeName) (or checking membership in the registry
it uses) and ensure the result is non-undefined/valid; if
resolveSettingsNavigationPath returns nothing (or the name is not in the allowed
set) then reject/log and return early and do not construct/cast the
SettingsNavigationPayload or enqueue the navigation. Update the block that
creates the SettingsNavigationPayload (the variable named routeName and the cast
to SettingsNavigationPayload) to perform this runtime check and handle invalid
input safely.

1479-1489: ⚠️ Potential issue | 🟠 Major

Handle stale pending messages after hash-only URL navigations

When tryNavigateSettingsWindowByUrl loads a hash-only URL (same base path, different hash), Electron triggers did-start-navigation with isSameDocument=true, which causes handleSettingsWindowNavigationStart to return early. Since same-document navigations don't reload the renderer, no READY event is emitted. The message queued before loadURL remains pending and can replay against stale state later.

Ensure pending messages are flushed when the window was already ready before a same-document navigation, and clean up orphaned messages on load failure.

🔁 Proposed guard
     this.pendingSettingsMessages.push({ channel, args: [navigation] })
+    const wasReady = this.settingsWindowReady
     console.log(`Reloading settings window to target URL: ${targetUrl}`)
     console.info('[Startup][Settings][Main] loadURL start', targetUrl)
     void this.settingsWindow.webContents
       .loadURL(targetUrl)
       .then(() => {
@@
 
+        if (wasReady && this.settingsWindowReady) {
+          this.flushPendingSettingsMessages()
+        }
+
         console.info(
           `[Startup][Settings][Main] loadURL end windowId=${this.settingsWindow.id} target=${targetUrl}`
         )
       })
       .catch((error) => {
+        this.pendingSettingsMessages = this.pendingSettingsMessages.filter(
+          (message) => message.channel !== channel || message.args[0] !== navigation
+        )
         console.error(`Failed to reload settings window for navigation: ${targetUrl}`, error)
       })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/presenter/windowPresenter/index.ts` around lines 1479 - 1489, When
handleSettingsWindowNavigationStart sees a same-document navigation
(isSameDocument === true) for the active settings window, if settingsWindowReady
was true before navigation you must flush/clear any queued pending settings
messages (the same logic the READY event handler uses to dispatch queued
messages) and mark the window as not ready so messages do not replay against
stale renderer state; likewise, in tryNavigateSettingsWindowByUrl ensure that on
load failure (the promise rejection or navigation error path after calling
loadURL) you also clear the pending-queue to avoid orphaned messages. Locate the
queued message handling code that runs when the READY event is received and
invoke or reuse that to flush/clear the queue from
handleSettingsWindowNavigationStart and the loadURL error path, updating
settingsWindowReady appropriately.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/main/presenter/windowPresenter/index.ts`:
- Around line 16-19: The handler currently casts an arbitrary string variable
routeName to SettingsNavigationPayload and enqueues/sends it without validation;
change that code to validate routeName against the shared registry before
casting by calling resolveSettingsNavigationPath(routeName) (or checking
membership in the registry it uses) and ensure the result is
non-undefined/valid; if resolveSettingsNavigationPath returns nothing (or the
name is not in the allowed set) then reject/log and return early and do not
construct/cast the SettingsNavigationPayload or enqueue the navigation. Update
the block that creates the SettingsNavigationPayload (the variable named
routeName and the cast to SettingsNavigationPayload) to perform this runtime
check and handle invalid input safely.
- Around line 1479-1489: When handleSettingsWindowNavigationStart sees a
same-document navigation (isSameDocument === true) for the active settings
window, if settingsWindowReady was true before navigation you must flush/clear
any queued pending settings messages (the same logic the READY event handler
uses to dispatch queued messages) and mark the window as not ready so messages
do not replay against stale renderer state; likewise, in
tryNavigateSettingsWindowByUrl ensure that on load failure (the promise
rejection or navigation error path after calling loadURL) you also clear the
pending-queue to avoid orphaned messages. Locate the queued message handling
code that runs when the READY event is received and invoke or reuse that to
flush/clear the queue from handleSettingsWindowNavigationStart and the loadURL
error path, updating settingsWindowReady appropriately.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8cdb9bab-8979-40c5-9e63-6e9b0e167367

📥 Commits

Reviewing files that changed from the base of the PR and between ba780ee and 87b8e3f.

📒 Files selected for processing (2)
  • src/main/presenter/windowPresenter/index.ts
  • src/renderer/api/SettingsClient.ts

@zerob13
zerob13 merged commit 8e8229e into dev Apr 22, 2026
3 checks passed
@zhangmo8
zhangmo8 deleted the spotlight-fix branch April 24, 2026 08:51
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.

2 participants