Conversation
📝 WalkthroughWalkthroughThis PR implements server-side JSON file-backed preferences storage and integrates URL persistence across the application. It adds a new Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan for PR comments
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
frontend/viewer/src/AppRoutes.svelte (1)
25-28: Avoid magic number for debounce delay.
200should be a named constant so this behavior is easier to tune and reason about.💡 Suggested tweak
+ const URL_SAVE_DEBOUNCE_MS = 200; onMount(() => { let timeout: ReturnType<typeof setTimeout>; const saveUrl = () => { clearTimeout(timeout); timeout = setTimeout(() => { const { pathname, search, hash } = document.location; void appStorage.lastUrl.set(pathname + search + hash); - }, 200); + }, URL_SAVE_DEBOUNCE_MS); };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/viewer/src/AppRoutes.svelte` around lines 25 - 28, Replace the magic number 200 with a named constant (e.g., URL_SAVE_DEBOUNCE_MS) declared in module scope of AppRoutes.svelte and use that constant when creating the timeout; update the timeout logic that references the variable timeout and the call to appStorage.lastUrl.set(pathname + search + hash) to use the new constant so the debounce delay is easy to find and tune.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/FwLite/FwLiteShared/Services/JsonFilePreferencesService.cs`:
- Around line 76-90: Save() currently catches and logs all exceptions, causing
Set()/Remove() to appear successful even when disk writes fail; change Save() to
surface failures instead of swallowing them by either rethrowing the caught
exception after logging (throw;) or returning a failure result that callers must
check, and update Set() and Remove() to propagate that failure (i.e., throw on
Save failure or return/propagate a false result) so callers get an exception or
error when File.WriteAllText/File.Move fails; reference Save(), Set(), Remove(),
_logger and _filePath when making the change.
In `@frontend/viewer/src/lib/utils/storage-prop.svelte.ts`:
- Line 27: The constructor currently calls void this.load() and other spots
(lines ~48-54) fire-and-forget the async load which can leave this.loading true
and produce unhandled rejections if backend.get() rejects; update the code so
the load() promise is observed and errors are handled: either add a .catch(...)
to the void this.load() call(s) in the constructor and at the other
fire-and-forget sites to log/handle the error, and/or modify the load() method
(the function named load that calls backend.get()) to wrap its await in
try/catch and a finally that always sets this.loading = false; ensure references
to backend.get() remain and use the class method names (constructor, load) so
the loading flag cannot remain true and no unhandled rejection escapes.
---
Nitpick comments:
In `@frontend/viewer/src/AppRoutes.svelte`:
- Around line 25-28: Replace the magic number 200 with a named constant (e.g.,
URL_SAVE_DEBOUNCE_MS) declared in module scope of AppRoutes.svelte and use that
constant when creating the timeout; update the timeout logic that references the
variable timeout and the call to appStorage.lastUrl.set(pathname + search +
hash) to use the new constant so the debounce delay is easy to find and tune.
ℹ️ Review info
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
backend/FwLite/FwLiteMaui/App.xaml.csbackend/FwLite/FwLiteShared/Services/JsonFilePreferencesService.csbackend/FwLite/FwLiteShared/Services/PreferenceKey.csbackend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.csbackend/FwLite/FwLiteWeb/FwLiteWebKernel.csbackend/FwLite/FwLiteWeb/Program.csfrontend/viewer/src/AppRoutes.sveltefrontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/PreferenceKey.tsfrontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/index.tsfrontend/viewer/src/lib/services/service-provider.tsfrontend/viewer/src/lib/utils/app-storage.svelte.tsfrontend/viewer/src/lib/utils/project-storage.svelte.tsfrontend/viewer/src/lib/utils/storage-prop.svelte.ts
backend/FwLite/FwLiteShared/Services/JsonFilePreferencesService.cs
Outdated
Show resolved
Hide resolved
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
ab65466 to
1545e20
Compare
8ba07d0 to
fb7c92c
Compare
1545e20 to
5f944e1
Compare
- Listen for hashchange events in url-tracker (fragment-only navigations like #sense links don't fire pushState/replaceState) - Remove catch in StorageProp.load() — let global error handler surface failures instead of silently warning - Include linter fixes: readonly _cache, static JsonSerializerOptions, collection expression syntax https://claude.ai/code/session_01JSLxGWSPJ55fLLLb5CKQye
18fca29 to
0760e11
Compare
The trackUrl feature added initAppStorage() to AppRoutes, which requires a PreferencesService. The demo setup used by Playwright tests was missing this service registration, causing all tests to crash on startup. https://claude.ai/code/session_01JSLxGWSPJ55fLLLb5CKQye
When running without a .NET host (e.g. Vite dev server, demo, tests), app-level services like PreferencesService were not available early enough — AppRoutes calls initAppStorage() before any route component can register mocks. Now main.ts detects whether FwLiteProvider was set by dotnet and, if not, registers browser-local implementations (e.g. localStorage-backed PreferencesService) before mounting the app. https://claude.ai/code/session_01JSLxGWSPJ55fLLLb5CKQye
…vices The hardcoded no-op JsEventListener default in LexboxServiceProvider silently masked missing service registrations. Now it lives alongside the browser PreferencesService in setupBrowserAppServices(), making the contract explicit: dotnet must provide the real one, and the browser-only path gets the no-op. https://claude.ai/code/session_01JSLxGWSPJ55fLLLb5CKQye
Storybook runs without a dotnet host, so it needs browser app services (JsEventListener, PreferencesService) registered before InMemoryDemoApi setup, just like main.ts does. https://claude.ai/code/session_01JSLxGWSPJ55fLLLb5CKQye
…stored URL - Rename isDotnetHosted → IsDotnetHosted (PascalCase to match Lexbox interface convention) and make it optional (undefined = not dotnet hosted), removing the redundant explicit false from setupServiceProvider - Fix bind/apply redundancy in url-tracker.ts: origPushState is already bound via .bind(history), so .apply(this, args) is misleading — use spread instead - Validate stored lastUrl starts with '/' before using it in both FwLiteWeb/Program.cs and FwLiteMaui/App.xaml.cs, guarding against corrupt preference values https://claude.ai/code/session_01JSLxGWSPJ55fLLLb5CKQye
- Restore missing closing braces from module script functions - Remove duplicate setupBrowserAppServices() call - Use camelCase local variable isDotnetHosted with explicit IsDotnetHosted property assignment to satisfy eslint naming-convention rule https://claude.ai/code/session_01JSLxGWSPJ55fLLLb5CKQye
Resolves #2210