fix: include floating keyboard prefs in backup, use synchronous commit on restore#115
Merged
Merged
Conversation
When long-pressing a letter, the popup keyboard now includes all
symbols defined at the corresponding position in the symbols layout,
not just the primary label. Previously a symbols-layout entry such as
`% per` or `( < { [` only contributed its first label to the
letter's popup; the symbol key's own popup keys were discarded.
addSymbolPopupKeys (and the number-row-in-symbols branch of
addNumberRowOrPopupKeys) now collect both the symbol key's label and
its popup labels via PopupSet.getPopupKeyLabels. PopupSet.symbol is
renamed to PopupSet.symbols and changed from String? to
Collection<String>?. createPopupKeysArray addAll's them; getHintLabel
keeps a single-character hint via firstOrNull().
Fixes LeanBitLab#113
Assisted-by: GitHub Copilot CLI
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…us commit The settings backup/restore previously only included the main SharedPreferences (device-protected) and the "protected" SharedPreferences, missing the separate loating_keyboard_prefs file used by FloatingKeyboardManager. After import on a fresh install, that file would stay empty and the floating-keyboard window position would silently reset. Now also back up and restore loating_keyboard_prefs via a new loating_keyboard_preferences.json zip entry. Encrypted gemini_prefs (EncryptedSharedPreferences holding device-bound API keys) is intentionally excluded, both because the master key is device-specific and because we don't want plain backups of credentials. Also switch the SharedPreferences writes during restore from �pply() to commit(). The post-restore code path runs `AppUpgrade.checkVersionUpgrade`, `Settings.startListener()`, etc. immediately afterwards, and can also be terminated by the user closing the activity. `commit()` guarantees the new preferences are persisted before any of that happens. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The settings export/import flow had two bugs that caused user-visible data loss after restoring on a fresh install.
1.
floating_keyboard_prefswas never backed upFloatingKeyboardManagerstores the floating-window position (floating_x,floating_y) in its own SharedPreferences file (floating_keyboard_prefs) viaDeviceProtectedUtils.getSharedPreferences(ctx, ""floating_keyboard_prefs""). The backup code only serialized the main prefs and the protected prefs — that auxiliary file was silently ignored on both export and import, so users would lose their floating-window position whenever they restored a backup.This PR introduces a small
auxiliaryPrefsToBackUp(ctx)map and wires both the export and import loops through it. Today it has one entry (floating_keyboard_prefs→floating_keyboard_preferences.json); it's structured this way so future feature-local SharedPreferences files can be added by adding one map entry.gemini_prefs(ProofreadService'sEncryptedSharedPreferences) is intentionally not in the map, with a comment explaining why: the values are encrypted under a device-bound master key and would be unreadable on any other device, and they hold API credentials we don't want in a plaintext backup zip.2. Restore used
apply()instead ofcommit()After clearing and refilling the SharedPreferences on restore, the code immediately runs
AppUpgrade.checkVersionUpgrade(ctx),Settings.startListener(), broadcasts the new-dictionary intent, etc., and the user may also close the settings activity as soon as the ""Backup restored"" feedback shows.apply()writes asynchronously, so there was a real race where the upgrade/listener code (or the next launch of the IME) could read partially-applied prefs, and a process kill right after the toast could lose writes entirely. Switched toe.commit().Testing
./gradlew :app:compileStandardDebugKotlin— clean build.settingsToJsonStream/readJsonLinesToSettingspair in a standalone harness to confirm there's no regression in the existing serialization.Note for users seeing ""my toggles flipped after restore""
Some users (myself initially) thought the boolean
remember_toolbar_state/var_toolbar_directionweren't being restored. They actually are — what's happening is that Android'sSharedPreferences.getAll()only returns explicitly-written keys, and if the source device left a switch at its default it isn't in the backup at all. After restore, the new install simply uses the default value, which happens to differ from the displayed value on the source (e.g.var_toolbar_directiondefaults totrue). This is a separate UX issue and isn't fixed here; the right fix would be a full enumeration of known prefs at export time and is more invasive.