Skip to content

fix(desktop): Tauri boot hydration, flush-on-quit, and Settings re-render perf (#332) - #345

Merged
qnbs merged 6 commits into
mainfrom
fix/332-tauri-desktop-reliability
Aug 13, 2026
Merged

fix(desktop): Tauri boot hydration, flush-on-quit, and Settings re-render perf (#332)#345
qnbs merged 6 commits into
mainfrom
fix/332-tauri-desktop-reliability

Conversation

@qnbs

@qnbs qnbs commented Aug 12, 2026

Copy link
Copy Markdown
Owner

User description

Summary

Root-causes and fixes the concrete, code-provable defects behind issue #332 (Tauri desktop reliability/perf on Linux), plus the settings-persistence half of #333 item 2.

  • D1 (critical) — desktop cold boot never read persisted state back. index.tsx's bootApp() called the raw IndexedDB-only dbService.loadState() unconditionally at boot, with zero Tauri branching, while every save path (app/listenerMiddleware.ts autosaves, the visibilitychange flush) already routed through the Tauri-aware storageService. Every desktop launch hydrated as a brand-new user regardless of what was actually saved to disk — a strict superset of the reported "appearance preference doesn't persist" symptom (the entire project/settings state, not just appearancePreset). Extracted the boot-hydration logic to services/appBootstrap.ts (out of index.tsx, a side-effect-heavy entry module that boots the whole app on import, so it's directly unit-testable) and it now branches on isTauriRuntime(), mirroring the save path.
  • D2 — settings-default mismatch. idbProjectStore.ts's normalizePersistedSettings backstop default for appearancePreset was still 'default', disagreeing with settingsSlice.ts's deliberate 'sepia' initial state (changed in v1.21). Reconciled — only matters for a genuine first-ever launch.
  • D3 — no flush-on-quit for the 1s debounced autosave. services/desktop/desktopTray.ts's onCloseRequested handler only intercepted close when minimize-to-tray was enabled (default off) — with it off, the window could close mid-debounce, silently dropping the last edit. It now unconditionally awaits a flush of any pending project/settings state (app/persistedStateFlush.ts, shared with the existing visibilitychange flush) before allowing a real quit to proceed — confirmed via the installed Tauri .d.ts that onCloseRequested supports and awaits async handlers.
  • D4 — backdrop-blur GPU compositing cost. The existing prefers-reduced-transparency CSS mitigation only swapped --glass-* color tokens; it never touched the 24 files using backdrop-blur-* Tailwind utilities directly (including 8 shared UI primitives used throughout Settings). Extended the mitigation to also strip backdrop-filter on those utility classes (no !important needed — Tailwind v4 emits utilities inside a cascade layer, so unlayered custom CSS already outranks them), and added a manual "Reduce transparency effects" toggle (Settings › Accessibility, default off) for desktops/DEs that don't expose the OS preference.
  • D5 — SettingsView re-rendered its whole tree on every unrelated Redux state change. useSettingsView() returned a fresh object every render (no memoization), so any background write anywhere in the app (autosave, AI copilot, progress tracker) forced every Settings component to re-render. The returned context value is now memoized against its actual dependencies.

Per docs/ISSUES-332-333-PERFORMANCE-LEDGER.md's own closure bar, the reporter's sluggishness cannot be claimed "resolved" without a packaged .deb measurement on the actual hardware/DE combination — this PR provides concrete, code-provable fixes for confirmed root causes, not a substitute for that verification. The ledger is updated with these findings and fixes, keeping the "packaged measurement still required" language intact.

Test plan

  • pnpm run typecheck (exact CI command) — clean
  • pnpm run lint (full project, --error-on-warnings) — clean
  • pnpm run i18n:check — 19 locales, 2905 keys, parity OK; bundles rebuilt
  • New unit tests: services/appBootstrap.ts (Tauri vs. web boot-branch selection), app/persistedStateFlush.ts, services/desktop/desktopTray.ts (await-before-close ordering), accessibilitySchema.ts/AccessibilitySection.tsx (reducedTransparency), useSettingsView.ts (memoized-return-value identity regression)
  • Existing regression suites re-verified together (133 tests across 12 files, all passing): SettingsView, useSettingsView, idbProjectStore, desktopTray, accessibility, plus PR C's Textarea/ContextPanel/ManuscriptEditor suites (unaffected)
  • New tests/e2e/settings-persistence.spec.ts (toggle → reload → assert persisted) — exercises the real Redux → listenerMiddleware → storageService → reload → boot-hydration round trip on the web-build CI runner; cannot verify the Tauri filesystem branch itself (no packaged-desktop-build job in CI) — that remains the ledger's open item
  • CI (this repo is CI-cloud-first on this constrained host per CLAUDE.md)

🤖 Generated with Claude Code

Summary by Sourcery

Align desktop boot, persistence, and accessibility behavior with existing save paths and performance goals, and reduce unnecessary Settings view re-renders.

Bug Fixes:

  • Ensure desktop (Tauri) cold boot hydrates persisted state via storage-aware bootstrap logic instead of IndexedDB-only reads.
  • Flush pending project and settings autosave data before allowing the desktop window to close, avoiding data loss on quit.
  • Align the persisted settings default for appearance preset with the intended initial value and migrate legacy invalid values accordingly.

Enhancements:

  • Memoize the Settings view context value so Settings-related components only re-render when their actual dependencies change.
  • Introduce a manual "Reduce transparency effects" accessibility setting that disables glass/backdrop blur visuals alongside honoring the OS reduced-transparency preference.
  • Share a centralized persisted-state flush helper between visibilitychange handling and desktop quit logic for consistent project/settings persistence.
  • Document confirmed performance-related root causes and fixes for issues [Bug]: Sluggishness? (.deb) #332 and Stability issues with Local AI, Gemini API keys, LM Studio and UI + workflow suggestions #333, including updated desktop UI audit and performance ledger entries.

Documentation:

  • Update changelog, README i18n key counts, desktop UI audit, and performance ledger to reflect new accessibility controls, persistence fixes, and metrics.

Tests:

  • Add unit tests for desktop/web bootstrapping, persisted state flushing, Settings view memoization, accessibility schema behavior, and desktop tray close handling.
  • Add an end-to-end Playwright test that validates settings persistence across reload on the web build.

CodeAnt-AI Description

Restore desktop data after relaunch, protect final edits, and reduce Settings overhead

What Changed

  • Desktop launches now restore saved projects and settings instead of starting with a blank state.
  • Closing the desktop app waits for pending project and settings saves, preventing the latest edit from being lost.
  • Settings now avoids re-rendering its entire view when unrelated app state changes.
  • Added an Accessibility toggle to disable transparency and backdrop blur effects, including on desktops that do not expose an operating-system preference.
  • Aligned the default appearance preset to Sepia and added coverage for persistence, shutdown saving, accessibility behavior, and Settings updates.

Impact

✅ Saved projects and settings restored after desktop relaunch
✅ Fewer edits lost when quitting during autosave
✅ Lower graphics load when transparency effects are disabled

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

  • New Features

    • Added a “Reduce transparency effects” accessibility setting to disable blur and translucent UI effects.
    • Added localized translations for the setting and local connection diagnostics.
  • Bug Fixes

    • Improved state restoration and active-project selection when launching.
    • Ensured pending changes are saved before desktop quit or close-to-tray.
    • Corrected first-launch appearance defaults.
    • Reduced unnecessary settings-screen refreshes and improved notification stability.
  • Documentation

    • Updated accessibility, performance, changelog, and localization documentation.

…nder perf (#332)

Desktop builds never read persisted state back at cold boot: every save routed
through the Tauri-aware storageService, but boot-time hydration called the raw
IndexedDB-only dbService.loadState() unconditionally — every launch loaded as a
brand-new user regardless of what was saved to disk (a strict superset of the
reported "appearance preference doesn't persist" symptom). Boot-time hydration
is extracted to services/appBootstrap.ts and now branches on isTauriRuntime(),
mirroring the save path.

Also:
- Reconciles idbProjectStore.ts's appearancePreset default with
  settingsSlice.ts's deliberate 'sepia' initial state (first-ever-launch only).
- Desktop window close now awaits any pending 1s-debounced autosave
  (app/persistedStateFlush.ts, services/desktop/desktopTray.ts) before the
  process exits, instead of allowing a quit to land mid-debounce.
- Extends the existing prefers-reduced-transparency CSS mitigation to also
  strip backdrop-blur-* Tailwind utilities directly (previously only the
  token layer was covered), and adds a manual "Reduce transparency effects"
  toggle for desktops/DEs that don't expose the OS preference.
- Memoizes useSettingsView's returned context value so SettingsView no longer
  re-renders its whole tree on every unrelated Redux state change.

Per docs/ISSUES-332-333-PERFORMANCE-LEDGER.md's own closure bar, the
reporter's sluggishness cannot be claimed "resolved" without a packaged .deb
measurement — these are concrete, code-provable fixes for confirmed root
causes, not a substitute for that verification.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@codeant-ai

codeant-ai Bot commented Aug 12, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR 7759b6f Aug 12, 2026 · 17:29 17:34

@codeant-ai

codeant-ai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@sourcery-ai

sourcery-ai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Reviewer's Guide

Fixes multiple desktop/Tauri reliability and performance issues: boot-time state hydration now mirrors the Tauri-aware save path, autosaved state is flushed on quit and on visibility change via a shared helper, Settings re-renders are reduced by memoizing the view context, transparency GPU cost is controllable via OS preference and a new accessibility toggle, and settings defaults/persistence behavior are aligned and covered by new tests and docs.

Sequence diagram for boot-time persisted state hydration (web vs Tauri)

sequenceDiagram
  participant Browser
  participant bootApp as bootApp
  participant appBootstrap as loadPersistedRootState
  participant dbService as dbService
  participant storageService as storageService

  Browser->>bootApp: load page / start app
  bootApp->>appBootstrap: loadPersistedRootState()
  alt !isTauriRuntime()
    appBootstrap->>dbService: loadState()
    dbService-->>appBootstrap: PersistedRootState | undefined
  else isTauriRuntime()
    appBootstrap->>storageService: loadSettings()
    appBootstrap->>storageService: listProjects()
    storageService-->>appBootstrap: settings
    storageService-->>appBootstrap: projectIds
    appBootstrap->>storageService: loadProject(projectIds[0])
    storageService-->>appBootstrap: project
  end
  appBootstrap-->>bootApp: preloadedState: PersistedRootState | undefined
  bootApp-->>Browser: render App with isNewUser flag
Loading

Sequence diagram for desktop quit flush using flushPersistedState

sequenceDiagram
  participant User
  participant TauriWindow as TauriWindow
  participant desktopTray as installCloseToTray
  participant App as App
  participant flushPersisted as flushPersistedState
  participant storageService as storageService

  App->>desktopTray: installCloseToTray(shouldMinimizeToTray, flushPendingState)
  desktopTray->>TauriWindow: onCloseRequested(async handler)

  User->>TauriWindow: click close button
  TauriWindow->>desktopTray: invoke close handler
  alt shouldMinimizeToTray() === true
    desktopTray->>TauriWindow: event.preventDefault()
    desktopTray->>TauriWindow: hide()
  else shouldMinimizeToTray() === false
    desktopTray->>flushPersisted: flushPendingState()
    flushPersisted->>App: getState() as RootState
    flushPersisted->>storageService: saveProject(saveEnvelopeFromProjectData(enriched))
    flushPersisted->>storageService: saveSettings(state.settings)
    storageService-->>flushPersisted: settled promises
    flushPersisted-->>desktopTray: Promise<void> resolved
    TauriWindow-->>User: window closes
  end
Loading

Flow diagram for reducedTransparency accessibility toggle affecting backdrop-blur GPU cost

flowchart LR
  settings[settings.accessibility.reducedTransparency]
  appEffect["App useEffect: document.body.classList.toggle(&#39;worldscript-reduced-transparency&#39;)"]
  bodyClass[body.worldscript-reduced-transparency]
  cssTokens[CSS: update --glass-* tokens]
  cssBlur["CSS: [class*=&quot;backdrop-blur-&quot;] { backdrop-filter: none }"]

  settings --> appEffect --> bodyClass --> cssTokens
  bodyClass --> cssBlur
Loading

File-Level Changes

Change Details Files
Boot-time persisted state hydration is centralized and made Tauri-aware so desktop launches read the same state that all save paths write.
  • Introduced services/appBootstrap.loadPersistedRootState() to encapsulate boot hydration and branch on isTauriRuntime().
  • On web, loadPersistedRootState() continues to use dbService.loadState() for IndexedDB-only state.
  • On desktop, loadPersistedRootState() uses storageService.loadSettings()/listProjects()/loadProject() and constructs a flat PersistedRootState with project.data.
  • index.tsx bootApp() now calls loadPersistedRootState() instead of dbService.loadState(), preserving the existing redux-undo envelope construction.
  • Added unit tests for loadPersistedRootState to verify web vs desktop branching and single-project behavior.
services/appBootstrap.ts
index.tsx
tests/unit/services/appBootstrap.test.ts
Persisted state flushing (project + settings) is factored into a shared helper and wired into both visibilitychange and desktop quit so debounced autosaves cannot be lost.
  • Created app/persistedStateFlush.flushPersistedState() to enrich project.present.data with versionControl and save via storageService.saveProject/saveSettings.
  • Updated index.tsx visibilitychange handler to delegate to flushPersistedState instead of inlining the save logic.
  • Extended desktopTray.installCloseToTray() to accept a flushPendingState callback and await it before allowing non-minimize-to-tray closes.
  • App.tsx passes a flushPersistedState-based callback (using current RootState) into installCloseToTray and keeps minimizeToTray gating behavior.
  • Added unit tests for flushPersistedState (no-op when no project; correct enrichment and saves) and for desktopTray close behavior including async flush ordering.
app/persistedStateFlush.ts
index.tsx
services/desktop/desktopTray.ts
App.tsx
tests/unit/persistedStateFlush.test.ts
tests/unit/desktopTray.test.ts
SettingsView performance is improved by stabilizing the useSettingsView context value with memoization and aligning tests/mocks with the new identity guarantees.
  • Refactored useSettingsView to define handleLockSession separately with useCallback and then wrap the returned context object in useMemo keyed to its real dependencies.
  • Ensured project and related fields remain dependencies so genuine project edits still re-memoize the context while unrelated state changes no longer force a full Settings tree re-render.
  • Updated useSettingsView unit tests to use stable translation, toast, and selector mocks so the memoization identity tests are meaningful.
  • Added tests that assert the returned object reference is stable across rerenders with unchanged inputs and changes when project data mutates.
hooks/useSettingsView.ts
tests/unit/hooks/useSettingsView.test.ts
Transparency/backdrop-blur GPU cost mitigation is expanded to cover direct Tailwind utilities and exposed as a user-facing accessibility setting, with schema, CSS, and tests updated accordingly.
  • Extended the prefers-reduced-transparency CSS block to also neutralize backdrop-blur-* utilities via a body.is-desktop [class*="backdrop-blur-"] selector.
  • Added a worldscript-reduced-transparency body class with matching CSS to strip glass/background translucency independent of OS preference.
  • Hooked a new settings.accessibility.reducedTransparency flag in App.tsx to toggling the worldscript-reduced-transparency body class via useEffect.
  • Introduced reducedTransparency boolean to the accessibilitySettings schema, default normalized accessibility settings, and AccessibilitySettings type.
  • Surfaced a "Reduce transparency effects" ToggleSwitch in AccessibilitySection, wiring it through patchA11y/handleSettingChange.
  • Updated accessibilitySchema and AccessibilitySection tests to cover the new field’s default behavior and change handling.
  • Adjusted desktop UI audit and performance ledger docs to describe the shipped D4 mitigation and the remaining need for packaged GPU measurements.
index.css
App.tsx
features/settings/accessibilitySchema.ts
types.ts
components/settings/AccessibilitySection.tsx
tests/unit/accessibilitySchema.test.ts
tests/unit/settings/AccessibilitySection.test.tsx
docs/DESKTOP-UI-AUDIT.md
docs/ISSUES-332-333-PERFORMANCE-LEDGER.md
Settings persistence defaults and migrations are aligned with the current product defaults, and end-to-end persistence for accessibility settings is exercised in E2E tests.
  • Changed idbProjectStore.normalizePersistedSettings default appearancePreset from 'default' to 'sepia' to match settingsSlice initial state.
  • Added migration logic to normalizePersistedSettings to move legacy/invalid appearancePreset values to the new default while preserving explicit valid values.
  • Extended idbProjectStore unit tests to cover the new default, migration, and explicit-value preservation semantics.
  • Introduced a Playwright E2E test that toggles the "Reduce transparency effects" setting, waits for debounced autosave, reloads, and asserts the setting and corresponding body class persist.
  • Updated README badges and i18n key counts to reflect the additional settings string, and updated CHANGELOG to document these persistence and transparency fixes.
services/storage/idbProjectStore.ts
tests/unit/services/storage/idbProjectStore.test.ts
tests/e2e/settings-persistence.spec.ts
README.md
CHANGELOG.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
worldscript-studio Ready Ready Preview Aug 13, 2026 4:50am

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 44 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ec8b2a5b-8961-4145-8c9d-8ab6d2262943

📥 Commits

Reviewing files that changed from the base of the PR and between 6a22df2 and 84c57b0.

📒 Files selected for processing (53)
  • AUDIT.md
  • App.tsx
  • CHANGELOG.md
  • README.md
  • components/ui/Toast.tsx
  • hooks/useSettingsView.ts
  • locales/ar/settings.json
  • locales/de/settings.json
  • locales/el/settings.json
  • locales/en/settings.json
  • locales/es/settings.json
  • locales/eu/settings.json
  • locales/fa/settings.json
  • locales/fi/settings.json
  • locales/fr/settings.json
  • locales/he/settings.json
  • locales/hu/settings.json
  • locales/is/settings.json
  • locales/it/settings.json
  • locales/ja/settings.json
  • locales/ko/settings.json
  • locales/pt/settings.json
  • locales/ru/settings.json
  • locales/sv/settings.json
  • locales/zh/settings.json
  • public/locales/ar/bundle.json
  • public/locales/de/bundle.json
  • public/locales/el/bundle.json
  • public/locales/en/bundle.json
  • public/locales/es/bundle.json
  • public/locales/eu/bundle.json
  • public/locales/fa/bundle.json
  • public/locales/fi/bundle.json
  • public/locales/fr/bundle.json
  • public/locales/he/bundle.json
  • public/locales/hu/bundle.json
  • public/locales/is/bundle.json
  • public/locales/it/bundle.json
  • public/locales/ja/bundle.json
  • public/locales/ko/bundle.json
  • public/locales/pt/bundle.json
  • public/locales/ru/bundle.json
  • public/locales/sv/bundle.json
  • public/locales/zh/bundle.json
  • services/fs/projectFsStore.ts
  • services/storageService.ts
  • tests/unit/Toast.test.tsx
  • tests/unit/desktopTray.test.ts
  • tests/unit/hooks/useSettingsView.test.ts
  • tests/unit/persistedStateFlush.test.ts
  • tests/unit/services/appBootstrap.test.ts
  • tests/unit/services/fs/fsStores.test.ts
  • types/tauri-plugins.d.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 373557ad-c7d6-444e-8d82-f4a782deb197

📥 Commits

Reviewing files that changed from the base of the PR and between 2915297 and 6a22df2.

📒 Files selected for processing (2)
  • AUDIT.md
  • src-tauri/osv-scanner.toml

📝 Walkthrough

Walkthrough

The PR adds reduced-transparency accessibility support, centralized persisted-state hydration and flushing, desktop quit coordination, appearance-default migration, context memoization, localization updates, and security review records.

Changes

Accessibility and persistence

Layer / File(s) Summary
Reduced-transparency setting and styling
types.ts, features/settings/..., components/settings/..., App.tsx, index.css, locales/*, public/locales/*
Adds the reducedTransparency setting, toggle, body class, opaque glass tokens, blur suppression, translations, and tests.
Runtime hydration and persistence
services/appBootstrap.ts, app/persistedStateFlush.ts, index.tsx, services/desktop/..., services/storage/..., services/fs/..., src-tauri/..., tests/unit/services/*, tests/unit/persistedStateFlush.test.ts, tests/unit/desktop*.test.ts, tests/e2e/settings-persistence.spec.ts
Uses runtime-specific hydration, centralizes project and settings persistence, tracks the active project, flushes state before quit, and normalizes appearance defaults to sepia.
Settings and toast context memoization
hooks/useSettingsView.ts, components/ui/Toast.tsx, tests/unit/hooks/useSettingsView.test.ts, tests/unit/Toast.test.tsx
Memoizes callbacks and context values while preserving updates for changed project data.
Documentation and security records
CHANGELOG.md, README.md, docs/*, AUDIT.md, src-tauri/osv-scanner.toml
Documents the application changes, updated i18n metrics, performance findings, and the remaining development-only advisory.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Mergeability Score: 🟠 High · up to 6a22d

The PR improves desktop state restoration and quit-time persistence, but the current code can still hide failure to record the active project, allowing a later relaunch to open the wrong project. This is a concrete data-integrity risk that should be fixed before merge; scanner-suppression and native-build verification also need explicit follow-up.

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant Bootstrap
  participant Persistence
  participant DesktopQuit
  participant Storage
  App->>Bootstrap: Load persisted root state
  Bootstrap->>Storage: Read settings, projects, and active project
  App->>Persistence: Flush on visibility change
  DesktopQuit->>Persistence: Flush before actual quit
  Persistence->>Storage: Save project and settings
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary changes: Tauri boot hydration, quit-time persistence flushing, and Settings re-render performance.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/332-tauri-desktop-reliability

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

@codeant-ai codeant-ai Bot added the size:XL This PR changes 500-999 lines, ignoring generated files label Aug 12, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • In flushPersistedState you skip saving settings when there is no project.present.data; this means settings changes for users without a project won’t be flushed on quit despite the comment promising project+settings, so consider saving settings independently of project existence or clarifying that behavior.
  • The useMemo dependency list in useSettingsView omits some returned fields (setActiveCategory, setModal, importFileRef, setSnapshotName, setPassphraseModal), which may be stable today but makes the hook more brittle to future changes; it would be safer to either include them in the dependency array or annotate why they are intentionally excluded.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `flushPersistedState` you skip saving settings when there is no `project.present.data`; this means settings changes for users without a project won’t be flushed on quit despite the comment promising project+settings, so consider saving settings independently of project existence or clarifying that behavior.
- The `useMemo` dependency list in `useSettingsView` omits some returned fields (`setActiveCategory`, `setModal`, `importFileRef`, `setSnapshotName`, `setPassphraseModal`), which may be stable today but makes the hook more brittle to future changes; it would be safer to either include them in the dependency array or annotate why they are intentionally excluded.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread index.css Outdated
Comment thread services/appBootstrap.ts Outdated
Comment thread app/persistedStateFlush.ts Outdated
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

fix(desktop): Tauri boot hydration, flush-on-quit, and Settings re-render perf

🐞 Bug fix ✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Fixes desktop cold boot never reading persisted state: bootApp() used IndexedDB-only
 dbService.loadState().
• Extracts boot hydration to services/appBootstrap.ts, branching on isTauriRuntime() to mirror
 saves.
• Flushes pending debounced autosave on desktop quit and on tab hide.
• Adds reduced-transparency toggle and disables backdrop-blur-* under OS/toggle preference.
• Memoizes useSettingsView() context value to avoid Settings re-renders on unrelated state
 changes.
Diagram

graph TD
  A["index.tsx bootApp()"] --> B["appBootstrap.loadPersistedRootState()"]
  B -->|"isTauriRuntime() = false"| C[("dbService IndexedDB")]
  B -->|"isTauriRuntime() = true"| D[("storageService Tauri FS")]
  E["App.tsx quit handler"] --> F["desktopTray.installCloseToTray"] --> G["persistedStateFlush.flushPersistedState()"] --> D
  H["index.tsx visibilitychange"] --> G
  I["useSettingsView() memoized"] --> J["SettingsView tree"]

  subgraph Legend
    direction LR
    _db[(Database)] ~~~ _svc([Service])
  end
Loading
High-Level Assessment

The approach is the minimal consistent fix: it removes a save/load asymmetry (desktop saves via storageService, but used to load via dbService) by mirroring the existing save-path branching at boot. Extracting boot hydration and flush logic into dedicated modules makes the behavior directly testable and reduces risk in the side-effect-heavy entrypoint.

Files changed (24) +585 / -104

Enhancement (6) +124 / -43
App.tsxWire quit-flush callback and reducedTransparency body class toggle +13/-0

Wire quit-flush callback and reducedTransparency body class toggle

• Passes a flushPersistedState-based callback into installCloseToTray and adds a useEffect toggling the worldscript-reduced-transparency body class based on the new accessibility setting.

App.tsx

AccessibilitySection.tsxAdd 'Reduce transparency effects' toggle UI +5/-0

Add 'Reduce transparency effects' toggle UI

• Adds a new ToggleSwitch bound to accessibility.reducedTransparency in the Accessibility settings section.

components/settings/AccessibilitySection.tsx

accessibilitySchema.tsAdd reducedTransparency field to accessibility schema +4/-0

Add reducedTransparency field to accessibility schema

• Adds reducedTransparency boolean to the schema and defaults it to false in DEFAULT_NORMALIZED_ACCESSIBILITY.

features/settings/accessibilitySchema.ts

useSettingsView.tsMemoize useSettingsView's returned context value +78/-40

Memoize useSettingsView's returned context value

• Extracts handleLockSession into a stable callback and wraps the hook’s return object in useMemo keyed on its real dependencies to avoid unnecessary Settings tree re-renders.

hooks/useSettingsView.ts

index.cssStrip backdrop-blur utilities under reduced-transparency preference/toggle +22/-3

Strip backdrop-blur utilities under reduced-transparency preference/toggle

• Extends prefers-reduced-transparency handling to neutralize backdrop-filter for any class containing backdrop-blur-, and adds a body class rule for the manual reduced-transparency toggle.

index.css

types.tsAdd reducedTransparency to AccessibilitySettings type +2/-0

Add reducedTransparency to AccessibilitySettings type

• Extends AccessibilitySettings with reducedTransparency and documents its purpose as a manual GPU-cost relief valve.

types.ts

Bug fix (5) +82 / -27
persistedStateFlush.tsShared awaitable flush helper for project/settings state +26/-0

Shared awaitable flush helper for project/settings state

• Introduces a reusable flushPersistedState(state) helper that enriches project data with version control state and persists project + settings via storageService.

app/persistedStateFlush.ts

index.tsxDelegate boot hydration and visibilitychange flush to new services +4/-23

Delegate boot hydration and visibilitychange flush to new services

• Replaces inline boot hydration with loadPersistedRootState(), and replaces inline visibilitychange persistence logic with flushPersistedState().

index.tsx

appBootstrap.tsNew Tauri-aware boot hydration service +36/-0

New Tauri-aware boot hydration service

• Adds loadPersistedRootState() that branches on isTauriRuntime(): web reads via dbService.loadState(); desktop reads via storageService (settings + single-project load).

services/appBootstrap.ts

desktopTray.tsAwait state flush before allowing desktop window to close +9/-1

Await state flush before allowing desktop window to close

• Updates installCloseToTray to accept a flushPendingState callback and await it for real closes (when not minimizing to tray).

services/desktop/desktopTray.ts

idbProjectStore.tsFix appearancePreset default mismatch to 'sepia' +7/-3

Fix appearancePreset default mismatch to 'sepia'

• Aligns normalizePersistedSettings appearancePreset default and invalid legacy migration target to 'sepia', matching settingsSlice’s intended default.

services/storage/idbProjectStore.ts

Tests (8) +348 / -25
settings-persistence.spec.tsNew e2e test for settings persistence round-trip +46/-0

New e2e test for settings persistence round-trip

• Adds a Playwright test confirming an accessibility toggle persists across reloads, including the body class side effect.

tests/e2e/settings-persistence.spec.ts

accessibilitySchema.test.tsTest default and persisted reducedTransparency values +8/-0

Test default and persisted reducedTransparency values

• Extends schema tests to assert reducedTransparency defaults off and respects persisted true values.

tests/unit/accessibilitySchema.test.ts

desktopTray.test.tsTest await-flush behavior in installCloseToTray +40/-11

Test await-flush behavior in installCloseToTray

• Updates mocks for async close handlers and adds assertions that flush is awaited before allowing a real close.

tests/unit/desktopTray.test.ts

useSettingsView.test.tsTest memoized identity of useSettingsView's return value +47/-13

Test memoized identity of useSettingsView's return value

• Adds tests ensuring the hook returns a stable object across rerenders unless a real dependency (e.g. project title) changes.

tests/unit/hooks/useSettingsView.test.ts

persistedStateFlush.test.tsNew tests for flushPersistedState helper +73/-0

New tests for flushPersistedState helper

• Verifies project+settings saves (with version control enrichment) and confirms no-op behavior when project data is absent.

tests/unit/persistedStateFlush.test.ts

appBootstrap.test.tsNew tests for loadPersistedRootState branching +99/-0

New tests for loadPersistedRootState branching

• Covers web vs desktop branches, empty-state behavior, and single-project mode (loads first project id only).

tests/unit/services/appBootstrap.test.ts

idbProjectStore.test.tsTest corrected appearancePreset default and migration +14/-1

Test corrected appearancePreset default and migration

• Updates and extends tests for 'sepia' default, legacy migration, and preservation of explicitly persisted values.

tests/unit/services/storage/idbProjectStore.test.ts

AccessibilitySection.test.tsxTest reducedTransparency toggle rendering and behavior +21/-0

Test reducedTransparency toggle rendering and behavior

• Adds UI tests validating the new toggle renders and calls handleSettingChange with reducedTransparency updates.

tests/unit/settings/AccessibilitySection.test.tsx

Documentation (5) +31 / -9
CHANGELOG.mdDocument desktop reliability and re-render perf fixes +21/-0

Document desktop reliability and re-render perf fixes

• Adds changelog entries for desktop boot hydration fix, quit flush, SettingsView memoization, and the new reduced-transparency accessibility toggle.

CHANGELOG.md

README.mdBump i18n key count badges +4/-4

Bump i18n key count badges

• Updates i18n key count references from 2904 to 2905 to reflect the new settings translation key.

README.md

DESKTOP-UI-AUDIT.mdUpdate C-6 audit row with shipped fix status +1/-1

Update C-6 audit row with shipped fix status

• Corrects the backdrop-blur usage count and documents the shipped reduced-transparency mitigation and manual toggle.

docs/DESKTOP-UI-AUDIT.md

ISSUES-332-333-PERFORMANCE-LEDGER.mdUpdate performance ledger with confirmed root causes and fixes +4/-4

Update performance ledger with confirmed root causes and fixes

• Updates issue ledger rows with confirmed root cause notes (D1-D5) and the implemented code fixes, while noting packaged-build verification remains pending.

docs/ISSUES-332-333-PERFORMANCE-LEDGER.md

settings.jsonAdd reducedTransparency translation key (and 18 other locales) +1/-0

Add reducedTransparency translation key (and 18 other locales)

• Adds 'settings.accessibility.reducedTransparency' across locales/*/settings.json and corresponding public/locales/*/bundle.json files.

locales/en/settings.json

@codeant-ai

codeant-ai Bot commented Aug 12, 2026

Copy link
Copy Markdown

🏁 CodeAnt Quality Gate Results

Commit: 84c57b0c
Scan Time: 2026-08-13 05:12:00 UTC

✅ Overall Status: PASSED

Quality Gate Details

Quality Gate Status Details
Secrets ✅ PASSED 0 secrets found
Duplicate Code ✅ PASSED 2.7% duplicated
SAST ✅ PASSED No security issues
Bugs ✅ PASSED Rating S: 3 bugs
IAC ✅ PASSED Rating S: No issues

View Full Results

@qodo-code-review

qodo-code-review Bot commented Aug 12, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (2) 📜 Skill insights (0)

Grey Divider


Action required

1. Flush hides save failures ✓ Resolved 🐞 Bug ☼ Reliability
Description
flushPersistedState discards all Promise.allSettled rejection results, so its caller cannot
distinguish failed writes from a successful flush. The close handler consequently proceeds after
storage failures, silently losing the pending project or settings change.
Code

app/persistedStateFlush.ts[R22-25]

+  await Promise.allSettled([
+    storageService.saveProject(saveEnvelopeFromProjectData(enriched)),
+    storageService.saveSettings(state.settings),
+  ]);
Relevance

●● Moderate

Reliability concern seems valid, but no close historical precedent on handling Promise.allSettled
failures.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The helper awaits allSettled without inspecting its results. Filesystem project and settings
writes can reject, but the close listener simply awaits the always-fulfilling helper and then
returns, allowing close to continue.

app/persistedStateFlush.ts[18-25]
services/desktop/desktopTray.ts[134-141]
services/fs/projectFsStore.ts[34-39]
services/fs/settingsFsStore.ts[16-26]
tests/unit/persistedStateFlush.test.ts[43-72]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The shutdown flush always resolves because rejected project and settings saves are ignored.

## Issue Context
Propagate persistence failures, or inspect every settled result and return a failure outcome. The desktop close path must prevent or cancel shutdown on failure and surface an actionable error; retain explicitly documented best-effort behavior only for visibility changes.

## Fix Focus Areas
- app/persistedStateFlush.ts[18-25]
- services/desktop/desktopTray.ts[134-141]
- App.tsx[608-614]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Boot loads arbitrary project ✓ Resolved 🐞 Bug ≡ Correctness
Description
Desktop bootstrap treats the first filesystem-listed project as active even though that list has no
active-project or recency contract. When multiple project directories remain, startup can hydrate an
older project instead of the last edited one.
Code

services/appBootstrap.ts[R27-28]

+  const projectId = projectIds[0];
+  const project = projectId ? await storageService.loadProject(projectId) : null;
Relevance

●● Moderate

Correctness/behavioral change (project selection policy) is product-sensitive; no matching precedent
located.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The bootstrap picks index zero, while the filesystem backend saves each ID into its own directory
and returns raw directory-entry order; imported projects may replace the live ID, so multiple
retained directories are supported without any active-project marker.

services/appBootstrap.ts[22-28]
services/fs/projectFsStore.ts[27-39]
services/fs/projectFsStore.ts[61-72]
features/project/thunks/projectManagementThunks.ts[62-64]
tests/unit/services/appBootstrap.test.ts[91-98]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Desktop boot selects the first listed project even though filesystem listing order does not identify the active or most recently edited project.

## Issue Context
The filesystem backend stores separate directories by project ID, and imports can change the live project ID without removing prior directories. Persist an explicit active-project ID (or reliable last-opened metadata) and use it during hydration, with a safe fallback for legacy installations.

## Fix Focus Areas
- services/appBootstrap.ts[22-28]
- services/fs/projectFsStore.ts[27-39]
- services/fs/projectFsStore.ts[61-72]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Missing QNBS-v3 on toggle ✓ Resolved 📘 Rule violation § Compliance
Description
A substantive TSX logic change adds the reducedTransparency toggle, but the diff introduces no
QNBS-v3 annotation for this change. This violates the requirement that each modified logic-bearing
file include a QNBS-v3 annotation in the diff.
Code

components/settings/AccessibilitySection.tsx[R168-172]

+            <ToggleSwitch
+              label={t('settings.accessibility.reducedTransparency')}
+              checked={accessibility.reducedTransparency}
+              onChange={(v) => patchA11y({ reducedTransparency: v })}
+            />
Relevance

●●● Strong

Team frequently accepts adding required adjacent QNBS-v3 markers for new logic changes.

PR-#284
PR-#297

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2524933 requires at least one QNBS-v3 annotation comment to be present in the
diff for each modified source file with logic changes. The added ToggleSwitch block for
reducedTransparency has no accompanying QNBS-v3 annotation introduced with the change.

Rule 2524933: Require QNBS-v3 annotation comments on all non-trivial code changes
components/settings/AccessibilitySection.tsx[165-172]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
This file contains a non-trivial logic/UI change (new accessibility toggle) but the diff adds no QNBS-v3 annotation comment in this file.

## Issue Context
A new `ToggleSwitch` for `accessibility.reducedTransparency` was added.

## Fix Focus Areas
- components/settings/AccessibilitySection.tsx[165-173]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Quit paths lack flush ✓ Resolved 🐞 Bug ☼ Reliability
Description
The new flush is wired only to the window close-request listener, while the application and tray
predefined Quit items have no explicit flush callback. Those normal quit paths therefore do not
establish that pending debounced state is persisted before termination.
Code

services/desktop/desktopTray.ts[140]

+      await flushPendingState();
Relevance

●● Moderate

Quit/close semantics on desktop are nuanced; history shows mixed decisions around quit-path
behavior.

PR-#190
PR-#189

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The only flush registration is the current window's close-request callback. Both native menus
construct predefined Quit items without an application callback, and the sole installCloseToTray
caller supplies no shared quit command to those menus.

services/desktop/desktopTray.ts[126-141]
services/desktop/desktopTray.ts[59-80]
services/desktop/desktopMenu.ts[49-64]
App.tsx[601-625]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The state flush is attached only to window close requests, but native application-menu and tray-menu Quit actions do not route through the shared flush logic.

## Issue Context
Create one async quit function that flushes state and then exits, and connect every native Quit action to it. Add tests that invoke each quit path and verify flush completion precedes exit.

## Fix Focus Areas
- services/desktop/desktopTray.ts[126-141]
- services/desktop/desktopTray.ts[59-80]
- services/desktop/desktopMenu.ts[49-64]
- App.tsx[601-625]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Malformed // QNBS-v3 format 📘 Rule violation ⚙ Maintainability
Description
New QNBS-v3 annotations in TypeScript/TSX do not comply with the mandated single-line format `//
QNBS-v3: [reason / impact / creative value]` because the annotation both deviates from the required
prefix/payload structure and is spread across multiple comment lines. This weakens
traceability/scanability and violates the required annotation schema.
Code

App.tsx[278]

+  // QNBS-v3 (#332/D4): manual relief valve for backdrop-blur GPU cost, mirroring reducedMotion above —
Relevance

●● Moderate

Mixed precedent on strict QNBS-v3 one-line/bracketed enforcement; similar strict-format request was
rejected recently.

PR-#339
PR-#286

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2524954 specifies that every // QNBS-v3 line comment in TS/TSX must exactly match
// QNBS-v3: [reason / impact / creative value], but the added comment in App.tsx at line 278
uses // QNBS-v3 (#332/D4): ... and does not include the required bracketed three-segment content.
PR Compliance ID 2525103 further requires the QNBS-v3 comment to occupy exactly one physical line,
yet in App.tsx the annotation starts on line 278 and continues on lines 279–280 as additional //
lines, making the annotation multi-line.

Rule 2524954: Enforce QNBS-v3 annotation format in TypeScript and JavaScript files
Rule 2525103: Limit QNBS-v3 comments to a single explanatory line
App.tsx[278-278]
App.tsx[278-280]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
QNBS-v3 annotations added in TS/TSX must be a single physical line and must exactly follow the required schema `// QNBS-v3: [reason / impact / creative value]`, but the current annotation deviates from the required prefix/payload format and is written across multiple comment lines.

## Issue Context
The repository enforces a strict QNBS-v3 annotation schema for TS/JS sources. The new comment uses `// QNBS-v3 (#332/D4): ...` rather than `// QNBS-v3: [reason / impact / creative value]`, and the annotation content continues as multiple `//` lines (only the first line contains the marker), which violates the single-line requirement.

## Fix Focus Areas
- App.tsx[278-280]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (2)
6. Invalid CSS QNBS-v3 marker 📘 Rule violation ⚙ Maintainability
Description
CSS QNBS-v3 markers are not written in the required /* QNBS-v3: ... */ format. This breaks
automated detection/validation of annotations in CSS.
Code

index.css[R1012-1014]

/* QNBS-v3 (D4 / C-6): honor the OS reduced-transparency accessibility preference
   on desktop by making the token-driven glass layer opaque (drops the GPU cost of
-   compositing translucent surfaces). NOTE: components that apply `backdrop-blur-*`
-   Tailwind utilities directly are not covered here — consolidating those onto the
-   `--glass-*` token layer is the remaining C-6 work (see docs/DESKTOP-UI-AUDIT.md). */
+   compositing translucent surfaces). QNBS-v3 (#332/D4): also neutralize direct
Relevance

●● Moderate

CSS QNBS-v3 prefix enforcement has accepted history, but strict-format change was rejected very
recently.

PR-#278
PR-#339

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2525026 requires each QNBS-v3 occurrence in .css files to appear in a block
comment that starts exactly with /* QNBS-v3:. The comment at index.css:1012 starts with `/*
QNBS-v3 (D4 / C-6):`, which does not match the required prefix.

Rule 2525026: Enforce QNBS-v3 CSS annotation format
index.css[1012-1015]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
CSS QNBS-v3 markers must use the exact block-comment form `/* QNBS-v3: ... */`. Current comments include extra text between `QNBS-v3` and the colon.

## Issue Context
The reduced-transparency CSS block begins with `/* QNBS-v3 (D4 / C-6): ...` and also embeds another `QNBS-v3` marker mid-comment.

## Fix Focus Areas
- index.css[1012-1020]
- index.css[1032-1034]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Context memo remains unstable ✓ Resolved 🐞 Bug ➹ Performance
Description
The new context useMemo depends on callbacks that are recreated whenever useSettingsView renders
because production useToast() returns fresh object and method identities. This leaves the intended
Settings-tree rerender optimization incomplete, while the added identity test masks the behavior
with a stable toast mock.
Code

hooks/useSettingsView.ts[R472-473]

+      handlePassphraseConfirm,
+      handleLockSession,
Relevance

●● Moderate

Perf/memoization stability guidance is plausible but subjective; no close precedent found for
toast-identity deps.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Both callbacks included at the end of the new dependency array depend on toast, while useToast
constructs a new object and functions on every invocation. The new unit test explicitly mocks a
stable toast object and documents that the real hook remains unstable.

hooks/useSettingsView.ts[377-406]
hooks/useSettingsView.ts[448-474]
components/ui/Toast.tsx[23-48]
tests/unit/hooks/useSettingsView.test.ts[184-191]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new Settings context memoization is invalidated by callbacks that depend on the unstable production `useToast()` result.

## Issue Context
The toast hook's instability predates this PR, but the new optimization directly depends on stable callback identities. Memoize the toast methods/object, or depend on stable individual methods, and update the test to exercise production-faithful identity behavior rather than substituting a stable object.

## Fix Focus Areas
- hooks/useSettingsView.ts[377-406]
- hooks/useSettingsView.ts[448-474]
- components/ui/Toast.tsx[23-48]
- tests/unit/hooks/useSettingsView.test.ts[184-191]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

8. Untranslated reducedTransparency string in 14 locales ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The new accessibility toggle string 'settings.accessibility.reducedTransparency' was added with the
literal English text 'Reduce transparency effects' instead of a translation in ar, el, eu, fa, fi,
he, hu, is, ja, ko, pt, ru, sv, and zh locale files (and their generated
public/locales/*/bundle.json counterparts), while de, es, fr, and it received proper translations.
Users of these locales will see untranslated English text in the new Settings › Accessibility
toggle.
Code

locales/ar/settings.json[45]

+  "settings.accessibility.reducedTransparency": "Reduce transparency effects",
Relevance

●●● Strong

They routinely fix untranslated locale strings to avoid shipping English copy in non-English
bundles.

PR-#218
PR-#198

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Comparing the added key across locale files shows de/es/fr/it translated correctly (e.g.
'Transparenzeffekte reduzieren', 'Réduire les effets de transparence') while
ar/el/eu/fa/fi/he/hu/is/ja/ko/pt/ru/sv/zh all use the untranslated English string 'Reduce
transparency effects', which is a direct, PR-introduced localization regression for a new
user-facing setting.

locales/ar/settings.json[45-45]
locales/de/settings.json[45-45]
locales/ja/settings.json[45-45]
locales/he/settings.json[45-45]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new i18n key `settings.accessibility.reducedTransparency` was added with the literal English string "Reduce transparency effects" in many non-English locale files instead of a proper translation, while a few locales (de, es, fr, it) did receive translations.

## Issue Context
This key backs the new "Reduce transparency effects" toggle in Settings › Accessibility (part of #332/D4). The same untranslated value was also propagated into the generated `public/locales/*/bundle.json` files.

## Fix Focus Areas
- locales/ar/settings.json[45-45]
- locales/el/settings.json[45-45]
- locales/eu/settings.json[45-45]
- locales/fa/settings.json[45-45]
- locales/fi/settings.json[45-45]
- locales/he/settings.json[45-45]
- locales/hu/settings.json[45-45]
- locales/is/settings.json[45-45]
- locales/ja/settings.json[45-45]
- locales/ko/settings.json[45-45]
- locales/pt/settings.json[45-45]
- locales/ru/settings.json[45-45]
- locales/sv/settings.json[45-45]
- locales/zh/settings.json[45-45]
- public/locales/ar/bundle.json (and other affected locales' bundle.json, same key)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
✅ Compliance rules (platform): 116 rules
Review mode: 🧠 Deep: This PR spans multiple independent reliability, persistence, UI performance, CSS accessibility, localization, and test paths with 220 hunks, creating a high density of subtle defects that benefits from redundant review.

Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread App.tsx Outdated
Comment thread index.css Outdated
Comment thread components/settings/AccessibilitySection.tsx
Comment thread services/appBootstrap.ts Outdated
Comment thread services/desktop/desktopTray.ts Outdated
Comment thread app/persistedStateFlush.ts Outdated
Comment thread hooks/useSettingsView.ts
Comment thread locales/ar/settings.json Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Nitpick comments (2)
app/persistedStateFlush.ts (1)

5-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use one physical line for each QNBS-v3 comment.

The listed QNBS-v3 comments span multiple physical lines. Keep the required QNBS-v3 rationale on one line. Put any extended explanation in ordinary comments.

  • app/persistedStateFlush.ts#L5-L10: reduce the QNBS-v3 rationale to one physical line.
  • services/appBootstrap.ts#L7-L16: reduce the QNBS-v3 rationale to one physical line.
  • services/desktop/desktopTray.ts#L120-L124: reduce the QNBS-v3 rationale to one physical line.
  • services/storage/idbProjectStore.ts#L46-L48: reduce the QNBS-v3 rationale to one physical line.
  • services/storage/idbProjectStore.ts#L62-L63: reduce the QNBS-v3 rationale to one physical line.
  • tests/unit/persistedStateFlush.test.ts#L1-L6: reduce the QNBS-v3 rationale to one physical line.
  • tests/unit/services/appBootstrap.test.ts#L1-L9: reduce the QNBS-v3 rationale to one physical line.
  • tests/unit/services/storage/idbProjectStore.test.ts#L14-L16: reduce the QNBS-v3 rationale to one physical line.

As per coding guidelines: “For every non-trivial code change, add one single-line QNBS-v3 comment explaining why.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/persistedStateFlush.ts` around lines 5 - 10, Reduce each multi-line
QNBS-v3 rationale to one physical line, preserving its explanation and moving
any extra context to ordinary comments if needed: app/persistedStateFlush.ts
lines 5-10; services/appBootstrap.ts lines 7-16; services/desktop/desktopTray.ts
lines 120-124; services/storage/idbProjectStore.ts lines 46-48 and 62-63;
tests/unit/persistedStateFlush.test.ts lines 1-6;
tests/unit/services/appBootstrap.test.ts lines 1-9; and
tests/unit/services/storage/idbProjectStore.test.ts lines 14-16.

Source: Coding guidelines

features/settings/accessibilitySchema.ts (1)

14-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the QNBS-v3 rationale on one physical line.

The TypeScript guideline requires one physical-line QNBS-v3 comments for non-trivial changes. Lines 14-15 split the rationale across two comment lines. Collapse it into one comment line.

Proposed fix
-  // QNBS-v3 (`#332/D4`): manual opt-in for users who want backdrop-blur GPU cost off without relying
-  // on the OS `prefers-reduced-transparency` preference (which the existing CSS block already covers).
+  // QNBS-v3 (`#332/D4`): Manual opt-in disables backdrop blur independently of the OS preference.

As per coding guidelines, non-trivial TypeScript changes must use one physical-line QNBS-v3 comments.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@features/settings/accessibilitySchema.ts` around lines 14 - 15, Collapse the
two-line QNBS-v3 rationale comment in the accessibility schema into a single
physical line, preserving its full wording and meaning.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@App.tsx`:
- Around line 612-613: Update flushPersistedState and the close flow installed
by installCloseToTray so project and settings persistence run independently,
including settings when state.project.present?.data is absent. Propagate any
persistence failure instead of resolving after Promise.allSettled, and ensure
the close handler keeps the window open until the flush completes successfully.

In `@app/persistedStateFlush.ts`:
- Around line 22-25: Preserve save failures across flushPersistedState instead
of silently discarding Promise.allSettled rejection reasons: inspect both
project and settings outcomes and return or reject after all writes settle. In
index.tsx line 257, catch failed best-effort flushes and log sanitized
diagnostic context through logger. In services/desktop/desktopTray.ts line 140,
apply an explicit policy that does not treat a failed flush as a successful
pre-close save. Add tests covering rejected project and settings writes.

In `@hooks/useSettingsView.ts`:
- Around line 402-404: Replace each specified multi-line QNBS-v3 comment with
one concise physical single-line QNBS-v3 comment: hooks/useSettingsView.ts lines
402-404 and 408-414, and tests/unit/hooks/useSettingsView.test.ts lines 15-21,
187-190, and 614-618. Preserve each comment’s rationale while ensuring every
affected site uses exactly one comment line.
- Around line 398-406: Preserve useMemo stability by updating handleLockSession
in hooks/useSettingsView.ts:398-406 to depend on stable toast methods rather
than the unstable toast object, and audit the dependency chain in
hooks/useSettingsView.ts:415-475 to retain only references stable across
unchanged production renders. Update the toast mock contract in
tests/unit/hooks/useSettingsView.test.ts:187-191 to return a fresh object with
stable methods, then adjust tests/unit/hooks/useSettingsView.test.ts:620-634 to
verify callback and memoized-value stability under that production-equivalent
behavior.

In `@public/locales/el/bundle.json`:
- Line 1691: Replace the English settings.accessibility.reducedTransparency
value with the approved locale-specific translations in
public/locales/el/bundle.json#L1691-L1691,
public/locales/eu/bundle.json#L1691-L1691,
public/locales/fa/bundle.json#L1691-L1691, and
public/locales/he/bundle.json#L1691-L1691, then regenerate each runtime bundle
from its source locale.

In `@public/locales/hu/bundle.json`:
- Line 1691: Translate settings.accessibility.reducedTransparency in
locales/hu/settings.json, locales/is/settings.json, locales/ja/settings.json,
locales/ko/settings.json, locales/pt/settings.json, locales/ru/settings.json,
locales/sv/settings.json, and locales/zh/settings.json, and translate
settings.privacy.encryptionSetupFailed in locales/hu/settings.json. Regenerate
the corresponding bundles at public/locales/hu/bundle.json#L1691-L1691 and
`#L2339-L2339`, public/locales/is/bundle.json#L1691-L1691,
public/locales/ja/bundle.json#L1691-L1691,
public/locales/ko/bundle.json#L1691-L1691,
public/locales/pt/bundle.json#L1691-L1691,
public/locales/ru/bundle.json#L1691-L1691,
public/locales/sv/bundle.json#L1691-L1691, and
public/locales/zh/bundle.json#L1691-L1691; ensure all nineteen locale trees
retain the required i18n keys.

In `@tests/e2e/settings-persistence.spec.ts`:
- Line 32: Replace the fixed page.waitForTimeout in the settings persistence
test with deterministic verification of the persistence boundary: wait for the
save-completion signal or poll the persisted record until the expected data is
present, then call page.reload().
- Around line 1-10: Reformat each tagged QNBS-v3 rationale in this
spec—including the comments near the file header and the sections around the
other referenced locations—so the complete why-comment is contained on one
physical line. Keep any additional detailed explanation in separate normal
comments, while preserving the rationale and the required single-line QNBS-v3
comment.

In `@tests/unit/accessibilitySchema.test.ts`:
- Around line 14-15: Keep the QNBS-v3 rationale comment in
accessibilitySchema.test.ts on a single physical line, preserving its
explanation that the manual reduced-transparency toggle defaults off to avoid
changing visual design on upgrade.

---

Nitpick comments:
In `@app/persistedStateFlush.ts`:
- Around line 5-10: Reduce each multi-line QNBS-v3 rationale to one physical
line, preserving its explanation and moving any extra context to ordinary
comments if needed: app/persistedStateFlush.ts lines 5-10;
services/appBootstrap.ts lines 7-16; services/desktop/desktopTray.ts lines
120-124; services/storage/idbProjectStore.ts lines 46-48 and 62-63;
tests/unit/persistedStateFlush.test.ts lines 1-6;
tests/unit/services/appBootstrap.test.ts lines 1-9; and
tests/unit/services/storage/idbProjectStore.test.ts lines 14-16.

In `@features/settings/accessibilitySchema.ts`:
- Around line 14-15: Collapse the two-line QNBS-v3 rationale comment in the
accessibility schema into a single physical line, preserving its full wording
and meaning.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c3d9602b-102d-4b78-b317-71a3c0936242

📥 Commits

Reviewing files that changed from the base of the PR and between dce75b3 and 7759b6f.

📒 Files selected for processing (61)
  • App.tsx
  • CHANGELOG.md
  • README.md
  • app/persistedStateFlush.ts
  • components/settings/AccessibilitySection.tsx
  • docs/DESKTOP-UI-AUDIT.md
  • docs/ISSUES-332-333-PERFORMANCE-LEDGER.md
  • features/settings/accessibilitySchema.ts
  • hooks/useSettingsView.ts
  • index.css
  • index.tsx
  • locales/ar/settings.json
  • locales/de/settings.json
  • locales/el/settings.json
  • locales/en/settings.json
  • locales/es/settings.json
  • locales/eu/settings.json
  • locales/fa/settings.json
  • locales/fi/settings.json
  • locales/fr/settings.json
  • locales/he/settings.json
  • locales/hu/settings.json
  • locales/is/settings.json
  • locales/it/settings.json
  • locales/ja/settings.json
  • locales/ko/settings.json
  • locales/pt/settings.json
  • locales/ru/settings.json
  • locales/sv/settings.json
  • locales/zh/settings.json
  • public/locales/ar/bundle.json
  • public/locales/de/bundle.json
  • public/locales/el/bundle.json
  • public/locales/en/bundle.json
  • public/locales/es/bundle.json
  • public/locales/eu/bundle.json
  • public/locales/fa/bundle.json
  • public/locales/fi/bundle.json
  • public/locales/fr/bundle.json
  • public/locales/he/bundle.json
  • public/locales/hu/bundle.json
  • public/locales/is/bundle.json
  • public/locales/it/bundle.json
  • public/locales/ja/bundle.json
  • public/locales/ko/bundle.json
  • public/locales/pt/bundle.json
  • public/locales/ru/bundle.json
  • public/locales/sv/bundle.json
  • public/locales/zh/bundle.json
  • services/appBootstrap.ts
  • services/desktop/desktopTray.ts
  • services/storage/idbProjectStore.ts
  • tests/e2e/settings-persistence.spec.ts
  • tests/unit/accessibilitySchema.test.ts
  • tests/unit/desktopTray.test.ts
  • tests/unit/hooks/useSettingsView.test.ts
  • tests/unit/persistedStateFlush.test.ts
  • tests/unit/services/appBootstrap.test.ts
  • tests/unit/services/storage/idbProjectStore.test.ts
  • tests/unit/settings/AccessibilitySection.test.tsx
  • types.ts

Comment thread App.tsx
Comment thread app/persistedStateFlush.ts Outdated
Comment thread hooks/useSettingsView.ts
Comment thread hooks/useSettingsView.ts Outdated
Comment thread public/locales/el/bundle.json Outdated
Comment thread public/locales/hu/bundle.json Outdated
Comment thread tests/e2e/settings-persistence.spec.ts Outdated
Comment thread tests/e2e/settings-persistence.spec.ts
Comment thread tests/unit/accessibilitySchema.test.ts Outdated
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.90909% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
services/fs/projectFsStore.ts 78.94% 2 Missing and 2 partials ⚠️
components/ui/Toast.tsx 81.81% 0 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

Addresses all 20 CodeRabbit/CodeAnt/Qodo review findings on PR #345:

- app/persistedStateFlush.ts: fail-closed flush — settings and project
  data now save independently via Promise.all instead of skipping
  settings entirely when project data is absent, and failures now
  propagate instead of being swallowed by Promise.allSettled
- index.tsx: visibilitychange flush now logs failures instead of a
  silent void
- services/desktop/desktopTray.ts + desktopMenu.ts: Quit paths (tray
  icon + File menu) now flush persisted state before exiting via the
  new @tauri-apps/plugin-process wiring; installCloseToTray keeps the
  window open (fail-closed) if the flush rejects instead of quitting
  on a failed save
- App.tsx: shared quitApp callback flushes state then calls
  plugin-process exit(0); aborts the quit if the flush fails
- src-tauri/{Cargo.toml,src/lib.rs,capabilities/default.json}: register
  tauri-plugin-process following the exact pattern of the existing
  notification/fs plugin registrations
- types/tauri-plugins.d.ts: add the missing `exit` export to the
  ambient plugin-process module declaration (was shadowing the real
  package's own types)
- services/appBootstrap.ts + services/fs/projectFsStore.ts +
  services/storageBackend.ts + services/storageService.ts: desktop
  boot now tracks and prefers the last-active project id (persisted
  marker file) instead of arbitrarily picking the first listed project
- components/ui/Toast.tsx: memoize useToast()'s returned methods and
  the context value so consumers relying on referential stability
  (e.g. useSettingsView's own memoization) aren't defeated by a fresh
  object on every render
- index.css: scope the reduced-transparency backdrop-blur override to
  body.is-desktop instead of applying it globally to the web/PWA build
- 14 locales: translate the previously-English-fallback
  reducedTransparency and encryptionSetupFailed settings strings
- QNBS-v3 comment formatting fixes across App.tsx, index.css,
  AccessibilitySection.tsx, and several test files

Rust changes were manually reviewed against the exact patterns of the
existing notification/fs plugin registrations rather than compile-
verified — a full `cargo check` risks OOM on this machine's 3.7GB RAM
during proc-macro2/quote/syn compilation, and Tauri-branch code isn't
exercised by this repo's per-PR CI regardless.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@socket-security

socket-security Bot commented Aug 13, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​tauri-plugin-process@​2.3.189100100100100

View full report

@qnbs

qnbs commented Aug 13, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…able)

Freshly published/reviewed 2026-08-12; latest extract-zip release (2.0.1) has
no patched version to override to. Transitive devDependency of
@puppeteer/browsers (Playwright's browser-binary downloader) — only ever
extracts Playwright/Chromium's own CDN-hosted zip releases, never a user- or
attacker-supplied archive, and ships in no production bundle. Documented in
src-tauri/osv-scanner.toml's IgnoredVulns list (existing pattern for
unfixable transitive findings) and AUDIT.md, matching the identical fix
already applied on the fix/341-writer-studio-rendering and
fix/333-download-progress-metrics sibling branches.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@App.tsx`:
- Around line 584-590: Remove the duplicate useEffect that invokes
installDesktopMenu, leaving the existing desktop-menu installation effect as the
sole caller. Update the executeCommandRef handling so executeCommandRef.current
= executeCommand occurs inside a dedicated effect rather than during render,
while preserving the ref used by the menu command callback.

Apply the same fix in `@App.tsx` around lines 582 - 583.

In `@components/ui/Toast.tsx`:
- Around line 141-143: Rewrite the QNBS-v3 comment in ToastProvider’s
memoization section as one physical line, preserving its rationale and the
existing comment content without changing surrounding code.

Apply the same fix in `@tests/unit/Toast.test.tsx` around lines 208 - 209: The
same single-line comment-formatting requirement applies to the test comment.

In `@services/fs/projectFsStore.ts`:
- Around line 40-41: Update the save flow containing setActiveProjectId to
remove the empty catch and allow marker-write failures to reject saveProject,
preserving the existing fail-closed shutdown behavior. Add a regression test
that makes the active-project marker write reject and verifies saveProject
rejects accordingly.

In `@services/storageService.ts`:
- Around line 85-88: Add one single-line QNBS-v3 rationale comment at each
affected site: services/storageService.ts lines 85-88 should explain null
normalization for single-project backends; types/tauri-plugins.d.ts line 13
should explain typed process exit for coordinated desktop shutdown;
tests/unit/services/appBootstrap.test.ts lines 94-117 should explain
active-project restoration coverage; and tests/unit/desktopTray.test.ts lines
95-117 should explain flush-aware Quit and close coverage.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 498fa5f8-9cad-44c0-a5a1-e40bfffaec22

📥 Commits

Reviewing files that changed from the base of the PR and between 7759b6f and 2915297.

⛔ Files ignored due to path filters (1)
  • src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (54)
  • App.tsx
  • app/persistedStateFlush.ts
  • components/settings/AccessibilitySection.tsx
  • components/ui/Toast.tsx
  • hooks/useSettingsView.ts
  • index.css
  • index.tsx
  • locales/ar/settings.json
  • locales/el/settings.json
  • locales/eu/settings.json
  • locales/fa/settings.json
  • locales/fi/settings.json
  • locales/he/settings.json
  • locales/hu/settings.json
  • locales/is/settings.json
  • locales/ja/settings.json
  • locales/ko/settings.json
  • locales/pt/settings.json
  • locales/ru/settings.json
  • locales/sv/settings.json
  • locales/zh/settings.json
  • public/locales/ar/bundle.json
  • public/locales/el/bundle.json
  • public/locales/eu/bundle.json
  • public/locales/fa/bundle.json
  • public/locales/fi/bundle.json
  • public/locales/he/bundle.json
  • public/locales/hu/bundle.json
  • public/locales/is/bundle.json
  • public/locales/ja/bundle.json
  • public/locales/ko/bundle.json
  • public/locales/pt/bundle.json
  • public/locales/ru/bundle.json
  • public/locales/sv/bundle.json
  • public/locales/zh/bundle.json
  • services/appBootstrap.ts
  • services/desktop/desktopMenu.ts
  • services/desktop/desktopTray.ts
  • services/fs/projectFsStore.ts
  • services/storageBackend.ts
  • services/storageService.ts
  • src-tauri/Cargo.toml
  • src-tauri/capabilities/default.json
  • src-tauri/src/lib.rs
  • tests/e2e/settings-persistence.spec.ts
  • tests/unit/Toast.test.tsx
  • tests/unit/accessibilitySchema.test.ts
  • tests/unit/desktopMenu.test.ts
  • tests/unit/desktopTray.test.ts
  • tests/unit/hooks/useSettingsView.test.ts
  • tests/unit/services/appBootstrap.test.ts
  • tests/unit/services/fs/fsStores.test.ts
  • tests/unit/storageService.test.ts
  • types/tauri-plugins.d.ts
🚧 Files skipped from review as they are similar to previous changes (32)
  • components/settings/AccessibilitySection.tsx
  • tests/unit/accessibilitySchema.test.ts
  • index.css
  • tests/e2e/settings-persistence.spec.ts
  • hooks/useSettingsView.ts
  • locales/ar/settings.json
  • locales/eu/settings.json
  • public/locales/sv/bundle.json
  • locales/pt/settings.json
  • locales/el/settings.json
  • public/locales/ja/bundle.json
  • public/locales/eu/bundle.json
  • index.tsx
  • public/locales/hu/bundle.json
  • public/locales/pt/bundle.json
  • public/locales/ko/bundle.json
  • tests/unit/hooks/useSettingsView.test.ts
  • locales/he/settings.json
  • public/locales/fa/bundle.json
  • locales/sv/settings.json
  • public/locales/is/bundle.json
  • locales/hu/settings.json
  • locales/zh/settings.json
  • locales/ko/settings.json
  • public/locales/he/bundle.json
  • public/locales/ru/bundle.json
  • public/locales/ar/bundle.json
  • locales/fa/settings.json
  • public/locales/zh/bundle.json
  • locales/ru/settings.json
  • public/locales/el/bundle.json
  • locales/fi/settings.json

Comment thread App.tsx
Comment thread components/ui/Toast.tsx Outdated
Comment thread services/fs/projectFsStore.ts Outdated
Comment thread services/storageService.ts
qnbs and others added 2 commits August 13, 2026 03:03
…avior

CI's Quality Gate (Node 22/24) caught a pre-existing test asserting the old,
now-intentionally-changed behavior: 'is a no-op when there is no project data
yet' expected saveSettings NOT to be called, but the fail-closed fix from
2915297 makes flushPersistedState always save settings independently of
project data. Renamed the test to reflect the new contract and updated its
assertion; also added two new tests covering the Promise.all fail-closed
behavior (a rejected saveProject/saveSettings now propagates instead of being
swallowed by the old Promise.allSettled).

This test file wasn't included in the local targeted-vitest verification
pass before the previous commit — a gap in file selection, not a masked
failure — caught by CI as intended.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A fresh CodeRabbit review after the first correction-loop push surfaced 4 new
findings (the PR's own diff introduced these, so they only appear now):

- App.tsx: removed the duplicate installDesktopMenu registration — two
  separate useEffect blocks both built the native menu (one via
  executeCommandRef, one calling executeCommand directly), causing redundant
  menu rebuilds and defeating the ref pattern's whole purpose whenever
  executeCommand's identity changed. Kept the ref-based effect (matches its
  own documented rationale); the ref write also moved out of render into its
  own effect, fixing a bare `ref.current = ...` render-time mutation.
- components/ui/Toast.tsx + tests/unit/Toast.test.tsx: condensed two
  QNBS-v3 comments that wrapped across physical lines.
- services/fs/projectFsStore.ts: the active-project marker write's failure
  is intentionally best-effort (the project data itself already saved
  successfully; failing the whole save over a non-critical marker write
  would block quit for a low-severity degradation, not data loss) — kept
  that design but replaced the silent `.catch(() => {})` with a documented
  abort that logs a warning, satisfying the "no silent swallowing except
  documented aborts" guideline without changing the fail-open marker
  behavior. Added a regression test covering the rejected-write path.
- Added the 4 requested single-line QNBS-v3 rationale comments:
  services/storageService.ts (null-normalization for single-project
  backends), types/tauri-plugins.d.ts (typed exit for coordinated
  shutdown), tests/unit/services/appBootstrap.test.ts and
  tests/unit/desktopTray.test.ts (test-coverage rationale).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@qnbs

qnbs commented Aug 13, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@qnbs
qnbs enabled auto-merge (squash) August 13, 2026 03:20
Real conflicts (not just textual noise) resolved:

- hooks/useSettingsView.ts + tests/unit/hooks/useSettingsView.test.ts: this
  branch's D5 useMemo-wrapped context-value fix was missing `migrationProgress`
  from its returned object — main's independently-added encryption feature had
  it, this branch's earlier refactor didn't carry it forward. Merged both: kept
  the useMemo optimization, added migrationProgress to the memoized object and
  its dependency array. Test mocks reconciled the same way — kept this branch's
  stable-toast pattern (the actual regression test for the D5 fix) while
  aliasing mockToastInfo/mockToastSuccess to stableToast's own methods so the
  existing encryption tests' assertions against those names keep working.
- CHANGELOG.md: two genuinely distinct "### Fixed" entries from different PRs
  (#332's desktop boot/SettingsView fixes vs. #341/#344's AI Writing Studio
  readability fixes) — kept both.
- README.md + locales/*/settings.json (el/fi/hu/is/pt/sv) + their bundles:
  mix of stale i18n key-count badges (regenerated via
  `node scripts/sync-readme-metrics.mjs` post-merge rather than guessing) and
  the same encryptionSetupFailed/providerStatusReady translation conflicts
  already resolved once in the previous merge commit — reapplied the same
  per-key resolution (whichever side has the real, non-English translation).
  Rebuilt all 19 bundles fresh via `pnpm run i18n:check` (2915 keys x 19
  locales, clean) rather than resolving bundle.json conflicts by hand.
- src-tauri/osv-scanner.toml: cosmetic-only comment-header conflict (both
  sides already had the identical extract-zip IgnoredVulns entry) — kept the
  more current review-date comment.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@qnbs
qnbs merged commit b5821b9 into main Aug 13, 2026
29 checks passed
@qnbs
qnbs deleted the fix/332-tauri-desktop-reliability branch August 13, 2026 05:11
qnbs added a commit that referenced this pull request Aug 13, 2026
CHANGELOG.md: two genuinely distinct "### Added" entries (#332's manual
reduced-transparency toggle, already in main, vs. this branch's own
download-progress bytes/speed entry) — kept both.

README.md: stale i18n key-count/test-file-count badges across 5 locations —
regenerated via `node scripts/sync-readme-metrics.mjs` post-merge (2919 keys
x 19 locales, 549 test files) rather than guessing.

All 19 locale source files and public/locales/*/bundle.json merged/rebuilt
cleanly with no manual conflict resolution needed this time.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant