Audit 9b: Dynamic color (Material You) + 48dp min touch target helpers

Dynamic color opt-in on Android 12+ via expect/actual DynamicColor:
- commonMain: expect isDynamicColorSupported() + rememberDynamicColorScheme()
- androidMain: SDK>=31 gate, dynamicLight/DarkColorScheme(context)
- iOS/JVM/JS/WASM: no-op actuals
- ThemeManager gains useDynamicColor StateFlow, persisted via ThemeStorage
- App.kt wires both currentTheme + useDynamicColor into HoneyDueTheme
- ThemeSelectionScreen exposes the "Use system colors" toggle

Touch target helpers:
- Modifier.minTouchTarget(48.dp) + Modifier.clickableWithRipple
- Applied at audit-flagged sites in CompleteTaskScreen

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey T
2026-04-18 17:39:22 -05:00
parent 214908cd5c
commit ba1ec2a69b
15 changed files with 314 additions and 19 deletions

View File

@@ -22,8 +22,21 @@ actual class ThemeStorageManager {
defaults.synchronize()
}
actual fun saveUseDynamicColor(enabled: Boolean) {
defaults.setBool(enabled, forKey = KEY_USE_DYNAMIC_COLOR)
defaults.synchronize()
}
actual fun getUseDynamicColor(): Boolean {
// iOS has no Material You — always false. Still read/write so stored
// state survives a platform reinstall scenario and cross-platform parity
// APIs stay symmetric.
return defaults.boolForKey(KEY_USE_DYNAMIC_COLOR)
}
companion object {
private const val KEY_THEME_ID = "theme_id"
private const val KEY_USE_DYNAMIC_COLOR = "use_dynamic_color"
private val instance by lazy { ThemeStorageManager() }

View File

@@ -0,0 +1,10 @@
package com.tt.honeyDue.ui.theme
import androidx.compose.material3.ColorScheme
import androidx.compose.runtime.Composable
/** iOS has no equivalent to Material You wallpaper-driven colors. */
actual fun isDynamicColorSupported(): Boolean = false
@Composable
actual fun rememberDynamicColorScheme(darkTheme: Boolean): ColorScheme? = null