Add a Light theme option in Settings (Appearance > Theme)#353
Open
patrickrb wants to merge 2 commits into
Open
Add a Light theme option in Settings (Appearance > Theme)#353patrickrb wants to merge 2 commits into
patrickrb wants to merge 2 commits into
Conversation
The app was hard-locked to dark. Introduce a selectable Light theme (dark stays the default) via a "Theme" list picker in a new Appearance section of Advanced settings, structured so more themes can be added later. Mechanism: back the existing color names in theme/Color.kt with a single snapshot-state palette (activePalette). Compose tracks State reads in both the composition and draw phases, so every existing color reference — in composables and in DrawScope lambdas — becomes reactive with no call-site changes. Switching themes swaps the palette and repaints the whole UI live (no activity recreate). Saturated semantic hues (Status/Band/Target/Psk) stay theme-independent constants. - theme/Color.kt: FT8AFPalette + Dark/Light palettes + activePalette state; switchable colors become reactive getters. - theme/FT8AFTheme.kt: build the Material ColorScheme from the active palette; drive system-bar icon appearance off palette luminance; FT8AFColors getters. - theme/ThemePreference.kt (new): ThemeOption enum, palette map, id parse/ round-trip, SharedPreferences persistence (synchronous, read before setContent to avoid a cold-start flash), and live applyTheme(). - ComposeMainActivity: apply the saved theme before setContent instead of forcing MODE_NIGHT_YES. - AdvancedSettings: Appearance section + Theme picker (mirrors Language). - strings_compose.xml: new appearance/theme strings. - Unit tests for the pure ThemePreference logic. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## dev #353 +/- ##
============================================
+ Coverage 11.70% 11.87% +0.16%
- Complexity 113 120 +7
============================================
Files 85 90 +5
Lines 11691 12673 +982
Branches 2110 2255 +145
============================================
+ Hits 1369 1505 +136
- Misses 10191 11037 +846
Partials 131 131
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds a user-selectable Light theme (Dark remains default) by introducing a theme/palette abstraction that keeps existing color call sites intact while enabling live theme switching and persistence across launches.
Changes:
- Introduces
ThemeOption+ SharedPreferences persistence and liveapplyTheme()startup/application path. - Refactors theme colors to be backed by a snapshot
activePaletteso existing color names become reactive getters. - Adds an Appearance section in Advanced Settings with a Theme picker, plus associated string resources and unit tests.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| ft8af/app/src/main/kotlin/radio/ks3ckc/ft8af/theme/Color.kt | Adds FT8AFPalette, dark/light palettes, and snapshot-backed activePalette with reactive color getters to avoid rewriting call sites. |
| ft8af/app/src/main/kotlin/radio/ks3ckc/ft8af/theme/FT8AFTheme.kt | Builds Material3 ColorScheme from the active palette and adjusts system bar icon appearance based on palette brightness. |
| ft8af/app/src/main/kotlin/radio/ks3ckc/ft8af/theme/ThemePreference.kt | Adds theme enum + id parsing, palette mapping, SharedPreferences persistence, and applyTheme() (palette swap + night mode). |
| ft8af/app/src/main/kotlin/radio/ks3ckc/ft8af/ComposeMainActivity.kt | Applies the saved theme before setContent instead of forcing night mode. |
| ft8af/app/src/main/kotlin/radio/ks3ckc/ft8af/ui/settings/AdvancedSettings.kt | Adds Appearance section and Theme picker dialog wired to applyTheme() + persistence. |
| ft8af/app/src/main/res/values/strings_compose.xml | Adds strings for Appearance section and theme picker labels/descriptions. |
| ft8af/app/src/test/kotlin/radio/ks3ckc/ft8af/theme/ThemePreferenceTest.kt | Adds pure unit tests for theme id parsing/round-trip, palette mapping, and display-name resolver. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Replace the hand-rolled RGB-weighted average with Compose's luminance() (WCAG relative luminance, with sRGB gamma decoding) when choosing the Material3 base scheme and system-bar icon appearance, so near-mid backgrounds classify correctly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.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.
What
Adds a selectable Light theme (dark stays the default) via a Theme list picker in a new Appearance section under Settings → Advanced. Built so more themes can be added later with a single enum entry.
Why
The app was hard-locked to dark — a single
darkColorSchemeplus a forcedMODE_NIGHT_YES, with ~700 color references pointing directly at hardcoded dark constants. There was no light palette and no way to switch.How
The key trick avoids rewriting ~700 call sites: back the existing color names in
theme/Color.ktwith a singlemutableStateOfpalette (activePalette). Compose tracksStatereads in both the composition and the draw phase, so every existing color read — in composables and inDrawScopelambdas — becomes reactive automatically. Switching themes swaps the palette and repaints the whole UI live, in place (no activity recreate, no flicker).Saturated semantic hues (
Status*,Band*,Target*,PskSpot) stay theme-independent constants — they read fine on either background and this avoids stale static captures (e.g. the band-color map).Changes
theme/Color.kt—FT8AFPalettedata class,DarkPalette/LightPalette,activePalettesnapshot state; switchable colors are now reactive getters (names unchanged).theme/FT8AFTheme.kt— build the MaterialColorSchemefrom the active palette; drive system-bar icon appearance off palette luminance;FT8AFColorsmembers become getters.theme/ThemePreference.kt(new) —ThemeOptionenum, palette map, id parse/round-trip, SharedPreferences persistence (read synchronously beforesetContentto avoid a cold-start flash), and liveapplyTheme().ComposeMainActivity— apply the saved theme beforesetContentinstead of forcingMODE_NIGHT_YES.AdvancedSettings— Appearance section + Theme picker (mirrors the Language picker).strings_compose.xml— new appearance/theme strings (locale files fall back to default until translated).Tests
New
ThemePreferenceTest(pure logic, no Robolectric): id parse/round-trip + unknown→default fallback,paletteFormapping, dark≠light palette spot checks,isLightflags, andcurrentThemeNameRes.gradlew testDebugUnitTestpasses;assembleDebugpackages cleanly.Not done here
On-device visual verification: installing a local debug build over the CI-signed app requires an uninstall that wipes the QSO log/config, so I left the device check for the maintainer. Proposed Light hex values are a sensible starting point and may want on-device tuning (notably the amber accent / cyan signal contrast on white).
🤖 Generated with Claude Code