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