Skip to content

fix: route legacy shared_preferences writes through the desktop store - #3287

Open
ianneub wants to merge 1 commit into
BlueBubblesApp:masterfrom
ianneub:ian/bug/legacy-prefs-clobber
Open

ianneub wants to merge 1 commit into
BlueBubblesApp:masterfrom
ianneub:ian/bug/legacy-prefs-clobber

Conversation

@ianneub

@ianneub ianneub commented Sep 24, 2026 •

Copy link
Copy Markdown

Fixes #3286

Problem
DesktopSharedPreferencesStore replaced only the async prefs backend. The legacy SharedPreferences API, which emoji_picker_flutter still uses to save recent emojis, went to the stock Linux/Windows backend. That backend rewrites the whole shared shared_preferences.json from a snapshot taken when the isolate started. One emoji pick could revert or wipe every setting written since then, including serverAddress and finishedSetup. On the next launch the app then cleared the database and returned to setup.

Solution
DesktopSharedPreferencesStore.register() now also installs _DesktopLegacySharedPreferencesStore, a small SharedPreferencesStorePlatform adapter that reuses the store's existing _readFile/_mutate. Legacy calls re-read the file, and legacy writes go through the existing lock + atomic write + .bak path. Legacy keys stay as they are (flutter.-prefixed, same file), so the legacy→async migration and existing data are unaffected. _mutate/_atomicWrite now report whether the file was written, so legacy writes return false on failure like the stock backends. Also updated settings/CLAUDE.md.

Testing (Linux, Flutter 3.44.6)

  • Throwaway flutter test repro (not committed; the repo has no test suite). It seeds the prefs file, calls register() and SharedPreferences.getInstance(), writes lastOpenedChat via SharedPreferencesAsync, then calls legacy.setString('recent', '[]'). On this branch it also checks remove, setStringList, clear, the deprecated *WithPrefix methods, and that a forced write failure returns false without touching the file:
    • master @ e2eaced: file ends as [serverAddress, finishedSetup, flutter.recent], so lastOpenedChat is lost ❌
    • this branch: [serverAddress, finishedSetup, lastOpenedChat, flutter.recent] ✅
  • flutter build linux --release, run against a copy of a real profile (146 keys) and a real server. The app starts with setup intact and syncs. After opening a chat and picking an emoji, flutter.recent updated, lastOpenedChat kept its new value, and no keys were lost.
  • flutter analyze on lib/services/backend/settings/: no issues.
  • Not tested on Windows. It uses the same registration path.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AyxJz1fsojfXbxJUBBsivy

@ianneub
ianneub marked this pull request as draft September 24, 2026 23:19
@ianneub
ianneub force-pushed the ian/bug/legacy-prefs-clobber branch from c579c80 to c0ca4ad Compare September 24, 2026 23:20
DesktopSharedPreferencesStore only replaced the async prefs backend. The
legacy SharedPreferences API (used by the legacy->async migration in
SharedPreferencesService.init() and by emoji_picker_flutter to save
recent emojis) went to the stock Linux/Windows backend, which rewrites
the whole shared file from a per-isolate snapshot taken at startup. One
emoji pick could revert or wipe every setting written since then,
including serverAddress and finishedSetup, and the next launch cleared
the database and returned to setup.

register() now also installs a legacy SharedPreferencesStorePlatform
adapter that reads and writes through the same lock + atomic-write store.
_mutate/_atomicWrite now report whether the file was written, so legacy
writes return false on failure like the stock backends did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AyxJz1fsojfXbxJUBBsivy
@ianneub
ianneub force-pushed the ian/bug/legacy-prefs-clobber branch from c0ca4ad to 157f21b Compare September 24, 2026 23:36
@ianneub
ianneub marked this pull request as ready for review September 24, 2026 23:37

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Linux] Picking an emoji can wipe settings (legacy SharedPreferences bypasses DesktopSharedPreferencesStore)

2 participants