Repository navigation
Conversation
Generated by 🚫 Danger Kotlin against ee58b79 |
Collaborator
r0adkll
added this pull request to stack #1207
October 6, 2026 14:23
LibraryViewSettings moves into the user graph, on the signed-in account's settings: UserPrefixedSettings keeps them in the app's existing preferences under "user:<id>:" keys, so they share its storage and backup without mixing with another account's. Signed out, there's no account, so the app-wide values are used. Each account starts from the library view settings the app kept for everyone, copied the first time its settings are opened; accounts added later start from the same values. Logging out clears the account's keys. The root UI takes the settings from the user graph it already receives.
The account's ObservableSettings is bound with @Forscope(UserScope::class) instead of a custom @UserSettings qualifier, and the app's is now bound and injected with @Forscope(AppScope::class), so every injection site says which store it reads.
r0adkll
force-pushed
the
refactor/user-library-view-settings
branch
from
October 6, 2026 14:27
26c1527 to
ee58b79
Compare
r0adkll
added a commit
that referenced
this pull request
Oct 6, 2026
<!-- pr-stack:start --> ## Stack - [This PR] #1189 - #1204 <!-- pr-stack:end --> First step of #607. `CampfireSettings` mixed device identity, privacy choices, app state, window layout, the socket toggle and library view preferences in one interface. This splits it by concern so each group can later move to the right storage layer (global vs per-user, then DataStore). ## What changed - `CampfireSettings` is split into: - `PrivacySettings`: consent, crash/analytics reporting, keep signed in after reinstall - `DeviceSettings`: device id, analytics id, current user - `AppStateSettings`: last seen version, app update prompts, widget pinning - `LayoutSettings`: navigation rail, supporting pane width - `ConnectionSettings`: socket toggle - `LibraryViewSettings`: sort/display state, marquee, time in book, download confirmation - `themeId`, `themeMode` and `observeTheme()` move onto the existing `ThemeSettings`. - `TestCampfireSettings` is split the same way into `Test*Settings`. - Call sites inject only the interfaces they use. `AnalyticsInitializer` and `PlayerWidgetComponent` held a `CampfireSettings` they never read; those are removed. ## What didn't change The members were moved over unchanged: the `var` + `observeX()` API, `AppSettings` delegates, storage keys and defaults are all the same. There's no user-facing change, so no changelog entry. ## Verification - `./scripts/ktlint --check` passes. - `:app:desktop:compileKotlin` and `:app:android:compileAlphaDebugKotlin` compile, and the touched modules compile for the iOS simulator. - `./gradlew jvmTest test`: everything passes except the four ffmpeg tests in `infra/audioplayer/engine-tests`, which fail locally because the native library doesn't load (`UnsatisfiedLinkError: no jniavutil`). This PR doesn't touch anything those tests use. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.
Stack
Closes #607. Each account now keeps its own library sorting and layout. Everything else stays app-wide, including the theme, and all settings stay on the existing preference-backed store.
What changed
UserPrefixedSettingsis anObservableSettingsthat keeps one account's values in the app's existing preferences, underuser:<userId>:keys.keys,sizeandclear()only see that account's settings.java.util.prefsrejects keys longer than 80 characters. A test checks every prefixed key against that limit.LibraryViewSettingsImplmoves into the user graph, on the account's settings (@ForScope(UserScope::class) ObservableSettings). Its observers run in the user graph's coroutine scope, so they end with it.DefaultUserSettingsStorehands each user graph its account's settings.UserSettingsStoreAPI.@ForScope(AppScope::class) ObservableSettingseverywhere it's provided and injected, so each injection site says which store it reads.Verification
./scripts/ktlint --checkpasses. Desktop, Android (alpha debug) and iOS (:app:ios) compile, and the Metro graph checks pass../gradlew jvmTest testpasses. The two native-FFmpeg audio engine modules were excluded locally, because the bundled FFmpeg native library doesn't load on this machine. New tests:UserPrefixedSettingsTest: per-account keys, isolation from other accounts and the app, scopedkeys/size/clear(), listeners;DefaultUserSettingsStoreTest: seeding once, keeping an account's changes, accounts apart, signed out, clearing;UserPrefixedKeyLengthTest: desktop's key length limit.Follow-ups
🤖 Generated with Claude Code