fix(desktop): Tauri boot hydration, flush-on-quit, and Settings re-render perf (#332) - #345
Conversation
…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>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
🤖 CodeAnt AI — Review Status
|
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
Reviewer's GuideFixes 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
Sequence diagram for desktop quit flush using flushPersistedStatesequenceDiagram
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
Flow diagram for reducedTransparency accessibility toggle affecting backdrop-blur GPU costflowchart LR
settings[settings.accessibility.reducedTransparency]
appEffect["App useEffect: document.body.classList.toggle('worldscript-reduced-transparency')"]
bodyClass[body.worldscript-reduced-transparency]
cssTokens[CSS: update --glass-* tokens]
cssBlur["CSS: [class*="backdrop-blur-"] { backdrop-filter: none }"]
settings --> appEffect --> bodyClass --> cssTokens
bodyClass --> cssBlur
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 44 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (53)
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe 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. ChangesAccessibility and persistence
Estimated code review effort: 3 (Moderate) | ~25 minutes Mergeability Score: 🟠 High · up to 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
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- In
flushPersistedStateyou skip saving settings when there is noproject.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
useMemodependency list inuseSettingsViewomits 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.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
PR Summary by Qodofix(desktop): Tauri boot hydration, flush-on-quit, and Settings re-render perf
AI Description
Diagram
High-Level Assessment
Files changed (24)
|
🏁 CodeAnt Quality Gate ResultsCommit: ✅ Overall Status: PASSEDQuality Gate Details
|
Code Review by Qodo
1.
|
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (2)
app/persistedStateFlush.ts (1)
5-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse one physical line for each
QNBS-v3comment.The listed
QNBS-v3comments 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-v3comment 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 winKeep the
QNBS-v3rationale on one physical line.The TypeScript guideline requires one physical-line
QNBS-v3comments 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-v3comments.🤖 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
📒 Files selected for processing (61)
App.tsxCHANGELOG.mdREADME.mdapp/persistedStateFlush.tscomponents/settings/AccessibilitySection.tsxdocs/DESKTOP-UI-AUDIT.mddocs/ISSUES-332-333-PERFORMANCE-LEDGER.mdfeatures/settings/accessibilitySchema.tshooks/useSettingsView.tsindex.cssindex.tsxlocales/ar/settings.jsonlocales/de/settings.jsonlocales/el/settings.jsonlocales/en/settings.jsonlocales/es/settings.jsonlocales/eu/settings.jsonlocales/fa/settings.jsonlocales/fi/settings.jsonlocales/fr/settings.jsonlocales/he/settings.jsonlocales/hu/settings.jsonlocales/is/settings.jsonlocales/it/settings.jsonlocales/ja/settings.jsonlocales/ko/settings.jsonlocales/pt/settings.jsonlocales/ru/settings.jsonlocales/sv/settings.jsonlocales/zh/settings.jsonpublic/locales/ar/bundle.jsonpublic/locales/de/bundle.jsonpublic/locales/el/bundle.jsonpublic/locales/en/bundle.jsonpublic/locales/es/bundle.jsonpublic/locales/eu/bundle.jsonpublic/locales/fa/bundle.jsonpublic/locales/fi/bundle.jsonpublic/locales/fr/bundle.jsonpublic/locales/he/bundle.jsonpublic/locales/hu/bundle.jsonpublic/locales/is/bundle.jsonpublic/locales/it/bundle.jsonpublic/locales/ja/bundle.jsonpublic/locales/ko/bundle.jsonpublic/locales/pt/bundle.jsonpublic/locales/ru/bundle.jsonpublic/locales/sv/bundle.jsonpublic/locales/zh/bundle.jsonservices/appBootstrap.tsservices/desktop/desktopTray.tsservices/storage/idbProjectStore.tstests/e2e/settings-persistence.spec.tstests/unit/accessibilitySchema.test.tstests/unit/desktopTray.test.tstests/unit/hooks/useSettingsView.test.tstests/unit/persistedStateFlush.test.tstests/unit/services/appBootstrap.test.tstests/unit/services/storage/idbProjectStore.test.tstests/unit/settings/AccessibilitySection.test.tsxtypes.ts
Codecov Report❌ Patch coverage is
📢 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>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
…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>
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (1)
src-tauri/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (54)
App.tsxapp/persistedStateFlush.tscomponents/settings/AccessibilitySection.tsxcomponents/ui/Toast.tsxhooks/useSettingsView.tsindex.cssindex.tsxlocales/ar/settings.jsonlocales/el/settings.jsonlocales/eu/settings.jsonlocales/fa/settings.jsonlocales/fi/settings.jsonlocales/he/settings.jsonlocales/hu/settings.jsonlocales/is/settings.jsonlocales/ja/settings.jsonlocales/ko/settings.jsonlocales/pt/settings.jsonlocales/ru/settings.jsonlocales/sv/settings.jsonlocales/zh/settings.jsonpublic/locales/ar/bundle.jsonpublic/locales/el/bundle.jsonpublic/locales/eu/bundle.jsonpublic/locales/fa/bundle.jsonpublic/locales/fi/bundle.jsonpublic/locales/he/bundle.jsonpublic/locales/hu/bundle.jsonpublic/locales/is/bundle.jsonpublic/locales/ja/bundle.jsonpublic/locales/ko/bundle.jsonpublic/locales/pt/bundle.jsonpublic/locales/ru/bundle.jsonpublic/locales/sv/bundle.jsonpublic/locales/zh/bundle.jsonservices/appBootstrap.tsservices/desktop/desktopMenu.tsservices/desktop/desktopTray.tsservices/fs/projectFsStore.tsservices/storageBackend.tsservices/storageService.tssrc-tauri/Cargo.tomlsrc-tauri/capabilities/default.jsonsrc-tauri/src/lib.rstests/e2e/settings-persistence.spec.tstests/unit/Toast.test.tsxtests/unit/accessibilitySchema.test.tstests/unit/desktopMenu.test.tstests/unit/desktopTray.test.tstests/unit/hooks/useSettingsView.test.tstests/unit/services/appBootstrap.test.tstests/unit/services/fs/fsStores.test.tstests/unit/storageService.test.tstypes/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
…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>
|
@coderabbitai review |
|
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>
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>
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.
index.tsx'sbootApp()called the raw IndexedDB-onlydbService.loadState()unconditionally at boot, with zero Tauri branching, while every save path (app/listenerMiddleware.tsautosaves, thevisibilitychangeflush) already routed through the Tauri-awarestorageService. 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 justappearancePreset). Extracted the boot-hydration logic toservices/appBootstrap.ts(out ofindex.tsx, a side-effect-heavy entry module that boots the whole app on import, so it's directly unit-testable) and it now branches onisTauriRuntime(), mirroring the save path.idbProjectStore.ts'snormalizePersistedSettingsbackstop default forappearancePresetwas still'default', disagreeing withsettingsSlice.ts's deliberate'sepia'initial state (changed in v1.21). Reconciled — only matters for a genuine first-ever launch.services/desktop/desktopTray.ts'sonCloseRequestedhandler 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 existingvisibilitychangeflush) before allowing a real quit to proceed — confirmed via the installed Tauri.d.tsthatonCloseRequestedsupports and awaits async handlers.prefers-reduced-transparencyCSS mitigation only swapped--glass-*color tokens; it never touched the 24 files usingbackdrop-blur-*Tailwind utilities directly (including 8 shared UI primitives used throughout Settings). Extended the mitigation to also stripbackdrop-filteron those utility classes (no!importantneeded — 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.SettingsViewre-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.debmeasurement 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) — cleanpnpm run lint(full project,--error-on-warnings) — cleanpnpm run i18n:check— 19 locales, 2905 keys, parity OK; bundles rebuiltservices/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)SettingsView,useSettingsView,idbProjectStore,desktopTray, accessibility, plus PR C's Textarea/ContextPanel/ManuscriptEditor suites (unaffected)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 itemCLAUDE.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:
Enhancements:
Documentation:
Tests:
CodeAnt-AI Description
Restore desktop data after relaunch, protect final edits, and reduce Settings overhead
What Changed
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:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
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:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
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
Bug Fixes
Documentation