| 1 |
package io.oxygenhub.android.ui.theme |
| 2 |
|
| 3 |
import androidx.compose.foundation.isSystemInDarkTheme |
| 4 |
import androidx.compose.material3.ColorScheme |
| 5 |
import androidx.compose.material3.MaterialTheme |
| 6 |
import androidx.compose.material3.darkColorScheme |
| 7 |
import androidx.compose.material3.dynamicDarkColorScheme |
| 8 |
import androidx.compose.material3.dynamicLightColorScheme |
| 9 |
import androidx.compose.material3.lightColorScheme |
| 10 |
import androidx.compose.runtime.Composable |
| 11 |
import androidx.compose.runtime.Immutable |
| 12 |
import androidx.compose.runtime.staticCompositionLocalOf |
| 13 |
import androidx.compose.ui.graphics.Color |
| 14 |
import androidx.compose.ui.platform.LocalContext |
| 15 |
|
| 16 |
private val DarkColorScheme = darkColorScheme( |
| 17 |
primary = DarkAccent, |
| 18 |
onPrimary = DarkBackground, |
| 19 |
primaryContainer = DarkBand, |
| 20 |
onPrimaryContainer = Color.White, |
| 21 |
secondary = DarkAccent2, |
| 22 |
onSecondary = Color.White, |
| 23 |
secondaryContainer = DarkSelected, |
| 24 |
onSecondaryContainer = DarkInk, |
| 25 |
tertiary = DarkWarn, |
| 26 |
background = DarkBackground, |
| 27 |
onBackground = DarkInk, |
| 28 |
surface = DarkBackground, |
| 29 |
onSurface = DarkInk, |
| 30 |
surfaceVariant = DarkSurfaceSoft, |
| 31 |
onSurfaceVariant = DarkMute, |
| 32 |
surfaceContainerLowest = DarkBackground, |
| 33 |
surfaceContainerLow = DarkSurface, |
| 34 |
surfaceContainer = DarkSurface, |
| 35 |
surfaceContainerHigh = DarkSurfaceSoft, |
| 36 |
surfaceContainerHighest = DarkSurfaceSoft, |
| 37 |
outline = DarkMute, |
| 38 |
outlineVariant = DarkLine, |
| 39 |
error = DarkBad, |
| 40 |
) |
| 41 |
|
| 42 |
private val LightColorScheme = lightColorScheme( |
| 43 |
primary = LightAccent, |
| 44 |
onPrimary = Color.White, |
| 45 |
primaryContainer = LightBand, |
| 46 |
onPrimaryContainer = Color.White, |
| 47 |
secondary = LightAccent2, |
| 48 |
onSecondary = Color.White, |
| 49 |
secondaryContainer = LightSelected, |
| 50 |
onSecondaryContainer = LightInk, |
| 51 |
tertiary = LightWarn, |
| 52 |
background = LightBackground, |
| 53 |
onBackground = LightInk, |
| 54 |
surface = LightBackground, |
| 55 |
onSurface = LightInk, |
| 56 |
surfaceVariant = LightSurfaceSoft, |
| 57 |
onSurfaceVariant = LightMute, |
| 58 |
surfaceContainerLowest = LightSurface, |
| 59 |
surfaceContainerLow = LightSurface, |
| 60 |
surfaceContainer = LightSurface, |
| 61 |
surfaceContainerHigh = LightSurfaceSoft, |
| 62 |
surfaceContainerHighest = LightSurfaceSoft, |
| 63 |
outline = LightMute, |
| 64 |
outlineVariant = LightLine, |
| 65 |
error = LightBad, |
| 66 |
) |
| 67 |
|
| 68 |
/** Colours Material has no slot for: an open or closed state. */ |
| 69 |
@Immutable |
| 70 |
data class StatusColors(val ok: Color, val bad: Color, val warn: Color) |
| 71 |
|
| 72 |
val LocalStatusColors = staticCompositionLocalOf { StatusColors(LightOk, LightBad, LightWarn) } |
| 73 |
|
| 74 |
@Composable |
| 75 |
fun OxygenHubTheme( |
| 76 |
darkTheme: Boolean = isSystemInDarkTheme(), |
| 77 |
// Wallpaper colours (Android 12, the app's minimum, has them); the |
| 78 |
// hub's own palette when turned off. |
| 79 |
dynamicColor: Boolean = true, |
| 80 |
content: @Composable () -> Unit, |
| 81 |
) { |
| 82 |
val colorScheme: ColorScheme = when { |
| 83 |
dynamicColor -> { |
| 84 |
val context = LocalContext.current |
| 85 |
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) |
| 86 |
} |
| 87 |
darkTheme -> DarkColorScheme |
| 88 |
else -> LightColorScheme |
| 89 |
} |
| 90 |
val status = if (darkTheme) StatusColors(DarkOk, DarkBad, DarkWarn) else StatusColors(LightOk, LightBad, LightWarn) |
| 91 |
androidx.compose.runtime.CompositionLocalProvider(LocalStatusColors provides status) { |
| 92 |
MaterialTheme(colorScheme = colorScheme, typography = Typography, content = content) |
| 93 |
} |
| 94 |
} |