84beb60fdb50

read non-secret settings before unlock so the lock screen matches the chosen size (v2.14.79)

The lock screen stayed at the default "auto" and snapped to the user's real choice the moment they authenticated, because settings were only loaded inside the unlock paths. Appearance lives in plain SharedPreferences rather than the sealed vault — VaultStore's own comment notes the prefs hold no secrets — so there is no reason to withhold it while locked. The repository now seeds its settings from the store and reloads them on lock instead of falling back to VaultSettings(). A destroyed vault still yields defaults because clearVault() removes the settings key. Verification: two VaultRepositoryTest cases, both confirmed to fail without this change with expected:<large> but was:<auto>; full JVM suite 1018 tests / 0 failures / 0 errors / 2 skipped; lintDebug clean; signed assembleRelease produced both splits.

time
2026-08-31 18:05 UTC · 1 month ago
machine
koh2
agent
hy4-preview
session
unfolded double lock screen
parent
af7042c15b05
3 files VERSION+1 −1app/src/main/java/com/peachpasswords/vault/VaultRepository.kt+6 −2app/src/test/java/com/peachpasswords/vault/VaultRepositoryTest.kt+27 −0
VERSION+1 −1
@@ -1 +1 @@1-2.14.781+2.14.79

view file

app/src/main/java/com/peachpasswords/vault/VaultRepository.kt+6 −2
@@ -204,7 +204,11 @@204204     /** Active (non-deleted) entryList. */205205     val entries: StateFlow<List<VaultEntry>> = _entries.asStateFlow()206206 207-    private val _settings = MutableStateFlow(VaultSettings())207+    // Settings live in plain prefs, not inside the sealed vault — they hold no208+    // secrets — so they are readable before unlock. Loading them here keeps the209+    // lock screen at the user's chosen appearance instead of the defaults, which210+    // otherwise snap to the real values the moment they authenticate.211+    private val _settings = MutableStateFlow(store.loadSettings())208212     val settings: StateFlow<VaultSettings> = _settings.asStateFlow()209213 210214     /** Clear every in-memory session field while [stateLock] is held. */@@ -219,7 +223,7 @@219223         recoveryWordsSet = false220224         sessionDataAvailable = false221225         decoyMode = false222-        _settings.value = VaultSettings()226+        _settings.value = store.loadSettings()223227         _entries.value = emptyList()224228         _isUnlocked.value = false225229     }

view file

app/src/test/java/com/peachpasswords/vault/VaultRepositoryTest.kt+27 −0
@@ -515,4 +515,31 @@515515         assertFalse(repo.consumeTransientBackgroundSuppression())516516         assertFalse(repo.consumeTransientBackgroundSuppression())517517     }518+519+    /**520+     * Appearance lives in plain prefs rather than the sealed vault, so it must be521+     * readable while locked: otherwise the lock screen renders at the defaults and522+     * snaps to the user's real choice the instant they authenticate.523+     */524+    @Test fun persisted_settings_are_read_before_unlock() = runBlocking {525+        val storage = FakeStorage()526+        VaultRepository(storage).createVault("pw")527+        storage.writeSettings(VaultSettings(uiScale = "large"))528+529+        val restarted = VaultRepository(storage)530+531+        assertFalse(restarted.isUnlocked.value)532+        assertEquals("large", restarted.settings.value.uiScale)533+    }534+535+    @Test fun persisted_settings_survive_locking() = runBlocking {536+        val storage = FakeStorage()537+        val repo = VaultRepository(storage)538+        repo.createVault("pw")539+        repo.updateSettings(repo.settings.value.copy(uiScale = "large"))540+541+        repo.lock()542+543+        assertEquals("large", repo.settings.value.uiScale)544+    }518545 }

view file