feat: store all user settings in local files instead of browser localStorage#7821
feat: store all user settings in local files instead of browser localStorage#7821louis-jan merged 9 commits intojanhq:mainfrom
Conversation
…to local JSON file via @tauri-apps/plugin-store
|
@louis-jan @Vanalite Please review this PR. welcome to any feedbacks |
|
@bittoby We need to do the migration so that users who update the app will not lose all of their data. |
|
@louis-jan Thanks for your feedback. I've added migration function. It is safe now. No data loss. Please review again. |
Thanks for reviewing again. Actually these are not bug.
|
Code ReviewSummaryIntroduces a Key Findings
Recommendation: fix neededResolve |
|
@louis-jan @qnixsynapse what else should I update more? please let me know. thanks |
|
I see, this makes very sense |
|
@louis-jan would you please merge this PR? |
|
@Vanalite would you please review this PR? |
Follow-up Review (new discussion since last review)Discussion Summary
Previous Concerns Status
AssessmentCode quality and migration are solid. Two items remain: (1) the Final recommendation: fix needed |
Follow-up Review (new commits since last review)New Commits
AssessmentBoth commits are merge/conflict-resolution only. The conflict resolution integrates the recently-merged configurable toast placement feature (#7886) — adding new files ( Previous Findings Status
RecommendationNo new functional changes — the merge commits just keep the branch up to date. Previous concerns about Final recommendation: fix needed (pending |
|
@bittoby it should be under the application data folder (see attached) |
|
@bittoby can you help correct the setting file to the correct location. Then it's good to go |
|
@louis-jan Thanks. I updated. please check again |
|
I'm having some difficulties with this PR. Specifically the "last-used-assistant" is disappearing when I type "make dev" as is the "llamacpp_env" (the setting for the llama.cpp engine). It's like all settings are constantly being reverted. I am also having trouble quitting Jan - it just hangs forever. Not really sure what to make of it all. Reverting the PR both the quitting and saved settings work again. Not quite sure what's going on. 😕 I haven't run any updates just "make dev". I'm on macOS 26.3.1. Sorry to be the bearer of bad news. |
|
Deleting the |
|
@markmehere If possible, could you share recording video or screenshot here? Then I will try to fix. Thanks for reporting error |
| for (const key of keys) { | ||
| // Skip keys already being migrated by a concurrent getItem call | ||
| if (migrationPromises.has(key)) continue | ||
|
|
There was a problem hiding this comment.
If you add if (key === localStorageKey.lastUsedAssistant) continue here (and the relevant import), it seems to restore the "last-used-assistant" to working order. Alternatively I'll write a comment on where it is set in case you want to fix it by using fileStorage.
There was a problem hiding this comment.
@bittoby see this comment and my comment on the conversation page - hopefully those help 🙂
|
I think there are still a few uses of Fortunately the assistant ones are all in this file: https://github.com/janhq/jan/blob/main/web-app/src/hooks/useAssistant.ts On line 24, line 68, line 89, line 100 and line 103. One big gotcha is that some of these are called really early on. If you search for "localStorage." you may find a few more in the code base. Hope this helps! |
|
@markmehere Thanks for providing guidance. I created new pr for missing migration parts. Pls test with this and let me know. thanks |
After #7821, migrateAllLocalStorageKeys() moves every localStorage key (including each extension's settings bag) into the Tauri plugin-store file on startup — but BaseExtension was still reading and writing localStorage directly. Consequences: - On upgrade, extension settings disappear: the migration evicts the key from localStorage, and the next registerSettings() sees no oldSettings and writes defaults back. - Within a session the extension writes to localStorage, but on the next boot migrateAllLocalStorageKeys finds the key already in the file store and deletes the localStorage copy without updating the file — silently discarding whatever the user changed (e.g. the llamacpp auto_update_engine toggle). Introduce an ExtensionStorage abstraction in @janhq/core with a localStorage default, and inject the app's fileStorage adapter from main.tsx so BaseExtension and the Zustand stores share one source of truth. Also narrow the provider settings UI to write only the key the user actually changed, so a stale in-memory snapshot can't overwrite unrelated keys via BaseExtension.updateSettings' full-array merge.



Describe Your Changes
Replace browser localStorage with file-based storage for all user settings. Settings now persist to a local
settings.jsonfile via@tauri-apps/plugin-store(already a project dependency).What changed:
fileStorageadapter (web-app/src/lib/fileStorage.ts) that implements zustand'sStateStorageinterface backed by@tauri-apps/plugin-storecreateJSONStorage(() => localStorage)tocreateJSONStorage(() => fileStorage)i18n/setup.tsupdated to read language from the zustand store instead of raw localStorageSettings file location:
~/.local/share/jan.ai.app/settings.json(Linux)Why this matters:
Fixes Issues
Self Checklist