diff --git a/.gitmodules b/.gitmodules index 13ce56c..78aefd4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "floret-kit"] path = floret-kit url = https://codeberg.org/jlmakiola/floret-kit.git - branch = feat/clockula + branch = main diff --git a/CHANGELOG.md b/CHANGELOG.md index 9538fc5..1eddbba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,6 +87,8 @@ The first release of Clockula: alarms, timers, a stopwatch and a world clock. with Clockula. A voice-set alarm cleans up after itself once dismissed. - Settings: theme, dynamic colour, language, and the defaults every new alarm and timer inherits. +- A Black theme next to Light and Dark: dark with pure black backgrounds, + for AMOLED screens. - Choose how long a ringing alarm or a finished timer keeps going before it stops on its own: 1, 5, 10, 15, 20 or 25 minutes, or Never, separately for alarms and timers. Ten minutes stays the default, and Never still stops diff --git a/app/src/main/java/de/jeanlucmakiola/clockula/MainActivity.kt b/app/src/main/java/de/jeanlucmakiola/clockula/MainActivity.kt index 35b6ffa..d24f478 100644 --- a/app/src/main/java/de/jeanlucmakiola/clockula/MainActivity.kt +++ b/app/src/main/java/de/jeanlucmakiola/clockula/MainActivity.kt @@ -30,6 +30,7 @@ import de.jeanlucmakiola.floret.crash.CrashReporter import de.jeanlucmakiola.floret.crash.submitCrashReport import de.jeanlucmakiola.floret.prefs.Appearance import de.jeanlucmakiola.floret.prefs.isDark +import de.jeanlucmakiola.floret.prefs.isPureBlack import javax.inject.Inject /** @@ -105,6 +106,7 @@ class MainActivity : ComponentActivity() { ClockulaTheme( darkTheme = darkTheme, dynamicColor = appearance.dynamicColor, + pureBlack = appearance.themeMode.isPureBlack, ) { ClockulaShell( modifier = Modifier.fillMaxSize(), diff --git a/app/src/main/java/de/jeanlucmakiola/clockula/ui/screensaver/ScreenSaverSettingsActivity.kt b/app/src/main/java/de/jeanlucmakiola/clockula/ui/screensaver/ScreenSaverSettingsActivity.kt index 6d68caf..8080ad7 100644 --- a/app/src/main/java/de/jeanlucmakiola/clockula/ui/screensaver/ScreenSaverSettingsActivity.kt +++ b/app/src/main/java/de/jeanlucmakiola/clockula/ui/screensaver/ScreenSaverSettingsActivity.kt @@ -18,6 +18,7 @@ import de.jeanlucmakiola.clockula.ui.theme.ClockulaTheme import de.jeanlucmakiola.floret.components.CollapsingScaffold import de.jeanlucmakiola.floret.prefs.Appearance import de.jeanlucmakiola.floret.prefs.isDark +import de.jeanlucmakiola.floret.prefs.isPureBlack import javax.inject.Inject /** @@ -47,7 +48,11 @@ class ScreenSaverSettingsActivity : ComponentActivity() { navigationBarStyle = SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT) { darkTheme }, ) } - ClockulaTheme(darkTheme = darkTheme, dynamicColor = appearance.dynamicColor) { + ClockulaTheme( + darkTheme = darkTheme, + dynamicColor = appearance.dynamicColor, + pureBlack = appearance.themeMode.isPureBlack, + ) { CollapsingScaffold(title = stringResource(R.string.screen_saver_title), onBack = ::finish) { ScreenSaverSettingsSection(inApp = false) } diff --git a/app/src/main/java/de/jeanlucmakiola/clockula/ui/settings/AppearanceScreen.kt b/app/src/main/java/de/jeanlucmakiola/clockula/ui/settings/AppearanceScreen.kt index 211b093..441736b 100644 --- a/app/src/main/java/de/jeanlucmakiola/clockula/ui/settings/AppearanceScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/clockula/ui/settings/AppearanceScreen.kt @@ -140,6 +140,9 @@ internal fun AppearanceScreen( options = ThemeMode.entries.toList(), selected = state.appearance.themeMode, label = { themeModeLabel(it) }, + summary = { mode -> + if (mode == ThemeMode.BLACK) stringResource(R.string.settings_theme_black_summary) else null + }, onSelect = viewModel::onThemeModeSelected, onDismiss = { showTheme = false }, ) @@ -152,6 +155,7 @@ private fun themeModeLabel(mode: ThemeMode): String = stringResource( ThemeMode.SYSTEM -> R.string.settings_theme_system ThemeMode.LIGHT -> R.string.settings_theme_light ThemeMode.DARK -> R.string.settings_theme_dark + ThemeMode.BLACK -> R.string.settings_theme_black }, ) diff --git a/app/src/main/java/de/jeanlucmakiola/clockula/ui/theme/Theme.kt b/app/src/main/java/de/jeanlucmakiola/clockula/ui/theme/Theme.kt index a9dea2e..e4489cc 100644 --- a/app/src/main/java/de/jeanlucmakiola/clockula/ui/theme/Theme.kt +++ b/app/src/main/java/de/jeanlucmakiola/clockula/ui/theme/Theme.kt @@ -9,12 +9,14 @@ import de.jeanlucmakiola.floret.identity.FloretExpressiveTheme * colour on API 31+, system light/dark, the standard motion scheme) fed with * Clockula's own identity — its seed-derived fallback schemes * ([ClockulaLightFallback] / [ClockulaDarkFallback]) and [ClockulaTypography]. - * The mechanics live in floret-kit; the look stays here. + * The mechanics live in floret-kit; the look stays here. [pureBlack] is the + * AMOLED take on the dark theme (`ThemeMode.BLACK`). */ @Composable fun ClockulaTheme( darkTheme: Boolean = isSystemInDarkTheme(), dynamicColor: Boolean = true, + pureBlack: Boolean = false, content: @Composable () -> Unit, ) { FloretExpressiveTheme( @@ -22,6 +24,7 @@ fun ClockulaTheme( darkScheme = ClockulaDarkFallback, darkTheme = darkTheme, dynamicColor = dynamicColor, + pureBlack = pureBlack, typography = ClockulaTypography, content = content, ) diff --git a/app/src/main/java/de/jeanlucmakiola/clockula/ui/tile/TilePreferencesActivity.kt b/app/src/main/java/de/jeanlucmakiola/clockula/ui/tile/TilePreferencesActivity.kt index fa5bed1..dbe9ba5 100644 --- a/app/src/main/java/de/jeanlucmakiola/clockula/ui/tile/TilePreferencesActivity.kt +++ b/app/src/main/java/de/jeanlucmakiola/clockula/ui/tile/TilePreferencesActivity.kt @@ -27,6 +27,7 @@ import de.jeanlucmakiola.clockula.ui.widget.config.QuickTimerPicker import de.jeanlucmakiola.clockula.ui.widget.openAppIntent import de.jeanlucmakiola.floret.prefs.Appearance import de.jeanlucmakiola.floret.prefs.isDark +import de.jeanlucmakiola.floret.prefs.isPureBlack import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -78,7 +79,11 @@ class TilePreferencesActivity : ComponentActivity() { // before the stored duration arrives. val duration by settingsPrefs.quickTileDuration.collectAsState(initial = null) val darkTheme = appearance.themeMode.isDark(isSystemInDarkTheme()) - ClockulaTheme(darkTheme = darkTheme, dynamicColor = appearance.dynamicColor) { + ClockulaTheme( + darkTheme = darkTheme, + dynamicColor = appearance.dynamicColor, + pureBlack = appearance.themeMode.isPureBlack, + ) { Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.surface) {} val current = duration ?: return@ClockulaTheme QuickTimerPicker( diff --git a/app/src/main/java/de/jeanlucmakiola/clockula/ui/widget/config/WidgetConfigActivity.kt b/app/src/main/java/de/jeanlucmakiola/clockula/ui/widget/config/WidgetConfigActivity.kt index 7c689e5..ae94018 100644 --- a/app/src/main/java/de/jeanlucmakiola/clockula/ui/widget/config/WidgetConfigActivity.kt +++ b/app/src/main/java/de/jeanlucmakiola/clockula/ui/widget/config/WidgetConfigActivity.kt @@ -21,6 +21,7 @@ import de.jeanlucmakiola.clockula.data.prefs.SettingsPrefs import de.jeanlucmakiola.clockula.ui.theme.ClockulaTheme import de.jeanlucmakiola.floret.prefs.Appearance import de.jeanlucmakiola.floret.prefs.isDark +import de.jeanlucmakiola.floret.prefs.isPureBlack import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -94,7 +95,11 @@ abstract class WidgetConfigActivity : ComponentActivity() { private fun ConfigTheme(content: @Composable () -> Unit) { val appearance by settingsPrefs.appearance.collectAsState(initial = Appearance()) val darkTheme = appearance.themeMode.isDark(isSystemInDarkTheme()) - ClockulaTheme(darkTheme = darkTheme, dynamicColor = appearance.dynamicColor) { + ClockulaTheme( + darkTheme = darkTheme, + dynamicColor = appearance.dynamicColor, + pureBlack = appearance.themeMode.isPureBlack, + ) { Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.surface) {} content() } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b96f9c9..d3d8960 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -329,6 +329,8 @@ Follow system Light Dark + Black + Dark with pure black backgrounds, for AMOLED screens Dynamic colour Use colours from your wallpaper Needs Android 12 or newer diff --git a/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt b/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt index b2488de..872a1c4 100644 --- a/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt +++ b/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt @@ -77,6 +77,15 @@ class SettingsPrefsTest { assertThat(prefs.themeMode.first()).isEqualTo(ThemeMode.DARK) } + @Test + fun `the pure-black theme mode round-trips`(@TempDir tempDir: Path) = runTest { + val prefs = SettingsPrefs(PrefStore(newDataStore(tempDir))) + + prefs.setThemeMode(ThemeMode.BLACK) + + assertThat(prefs.themeMode.first()).isEqualTo(ThemeMode.BLACK) + } + @Test fun `backup settings are applied together using normal preference clamps`(@TempDir tempDir: Path) = runTest { val prefs = SettingsPrefs(PrefStore(newDataStore(tempDir))) diff --git a/floret-kit b/floret-kit index 02bd14a..8593181 160000 --- a/floret-kit +++ b/floret-kit @@ -1 +1 @@ -Subproject commit 02bd14abdb713f31cd12eba4c8729241626496fa +Subproject commit 8593181618097191af016ea96a9e998490b4db29