You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Settings: theme preference synced to the account (theme) #36
Part of #31 — Settings & preferences parity — most of PATCH /api/user/update is unreachable from Android
Dark mode already works locally via ThemeSettingsStore/ThemeMode in :core:datastore,
but the choice is device-local. The account carries a theme field on PATCH /api/user/update,
so a user who sets dark on the web still lands in light on a fresh Android install.
Two-way sync: push local changes to theme, and adopt the account value on first sign-in.
Keep the local store as the source of truth while offline, reconciling on next sync.
Tests: local → PATCH; account value applied at sign-in; offline change survives and syncs.
Filed from the parity review of feature/parity-wip @ 14d7795 against interlinedlist.com (OpenAPI /api/openapi.json, 233 paths) and the public help centre.
Implemented in the PR above (branch issue/36-settings-theme). Closing here — review and any follow-up happens on the PR.
Server-side finding worth acting on independently: theme is not validated at all.PATCH /api/user/update accepted and stored "not-a-theme", "sepia", "SYSTEM" and "", each answering 200 {"message":"User updated successfully"}. Compare viewingPreference, which returns a proper allow-list in its 400. Any client can put the account into a theme no client can render. The app is therefore the conservative side — it sends only light/dark/system and refuses to adopt an unrenderable stored value rather than silently overwriting it. The test account was left as found (light).
The vocabulary came from /help/settings instead: "Theme: Light, dark, or system (follows your device preference)" — so the account does have a follow-the-system option, and ThemeMode.SYSTEM maps straight to "system" with no coercion.
The reconciliation rule the issue asked me to define and test: an unsynced local choice wins; otherwise the account wins. Neither side has a modification timestamp, so "newest wins" was unavailable — but a persisted unsynced flag is happened-after evidence, since a change that never reached the account means the account still holds whatever preceded it.
Activity
PATCH /api/user/updateis unreachable from Android #31Adron commentedon Sep 16, 2026
Implemented in the PR above (branch
issue/36-settings-theme). Closing here — review and any follow-up happens on the PR.Server-side finding worth acting on independently:
themeis not validated at all.PATCH /api/user/updateaccepted and stored"not-a-theme","sepia","SYSTEM"and"", each answering200 {"message":"User updated successfully"}. CompareviewingPreference, which returns a proper allow-list in its 400. Any client can put the account into a theme no client can render. The app is therefore the conservative side — it sends onlylight/dark/systemand refuses to adopt an unrenderable stored value rather than silently overwriting it. The test account was left as found (light).The vocabulary came from
/help/settingsinstead: "Theme: Light, dark, or system (follows your device preference)" — so the account does have a follow-the-system option, andThemeMode.SYSTEMmaps straight to"system"with no coercion.The reconciliation rule the issue asked me to define and test: an unsynced local choice wins; otherwise the account wins. Neither side has a modification timestamp, so "newest wins" was unavailable — but a persisted unsynced flag is happened-after evidence, since a change that never reached the account means the account still holds whatever preceded it.
merge: #36 theme account sync (PR)