OXYGENHUB

Light and dark in the hub's own colours, dynamic colour by default (refs #2) 206d05a042e7

The Material schemes take the hub's palette (templates/style.css) for when
dynamic colour is off; wallpaper colours otherwise. The window behind
Compose is the hub's page colour in both themes, so a dark phone never
flashes white. Status colours (open, closed) as a composition local. The
launcher icon's mipmap-anydpi-v26 folder is plain mipmap-anydpi, since the
minimum is 31.
Author
Andy McCall @andymccall <[email protected]>
via
agent agent:claude@andymccall <[email protected]> · keyless, under your grant for changes,refs,seal · key f4ec0f2e7863
When
· 2026-10-24 22:23 UTC
Signature
◈ sealed by agent:claude@andymccall
Hash
206d05a042e743fbe1193eb933d8ef8892b8bd83f9c8ad8643d1b22577424945
Depends on
57c0824300db e0e4a1c48a77
Depended on by
b610bc6eeab7 840c75813f86 3f3508bd5f16 0a2858c0dad3
In bookmarks
main
In tags
v0.1.0 v0.1.1 v0.1.2 v0.1.3 v0.1.4 v0.1.5 v0.1.6 v0.1.7 v0.1.8 v0.1.9
Edits
20 atoms, 6 tree operations, 8 files

Browse the tree at this change

renamed app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml → app/src/main/res/mipmap-anydpi/ic_launcher.xml +0 −0
…
6 unchanged lines
renamed app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml → app/src/main/res/mipmap-anydpi/ic_launcher_round.xml +0 −0
…
6 unchanged lines
added app/src/main/res/values-night/themes.xml +7 −0
1 +
<?xml version="1.0" encoding="utf-8"?>
2 +
<resources>
3 +
    <!-- Dark: the hub's dark page colour, so a dark phone never flashes white. -->
4 +
    <style name="Theme.OxygenHub" parent="android:Theme.Material.NoActionBar">
5 +
        <item name="android:windowBackground">@color/window_dark</item>
6 +
    </style>
7 +
</resources>
removed app/src/main/res/mipmap-anydpi-v26 +0 −0

No line changes.

modified app/src/main/java/io/oxygenhub/android/ui/theme/Color.kt +29 −6
…
1 unchanged lines
2 2
3 3
import androidx.compose.ui.graphics.Color
4 4
5 -
val Purple80 = Color(0xFFD0BCFF)
6 -
val PurpleGrey80 = Color(0xFFCCC2DC)
7 -
val Pink80 = Color(0xFFEFB8C8)
5 +
// The hub's own palette (oxygenhub templates/style.css), for phones without
6 +
// dynamic colour or when the user turns it off.
8 7
9 -
val Purple40 = Color(0xFF6650a4)
10 -
val PurpleGrey40 = Color(0xFF625b71)
11 -
val Pink40 = Color(0xFF7D5260)
8 +
// Dark
9 +
val DarkBackground = Color(0xFF070C18)
10 +
val DarkSurface = Color(0xFF0E1526)
11 +
val DarkSurfaceSoft = Color(0xFF141D33)
12 +
val DarkInk = Color(0xFFE6ECF7)
13 +
val DarkMute = Color(0xFF8592AD)
14 +
val DarkLine = Color(0xFF1F2B47)
15 +
val DarkAccent = Color(0xFF00E0F0)
16 +
val DarkAccent2 = Color(0xFF0072FF)
17 +
val DarkBand = Color(0xFF0B3F9E)
18 +
val DarkOk = Color(0xFF5FE3A1)
19 +
val DarkBad = Color(0xFFFF5E7A)
20 +
val DarkWarn = Color(0xFFB48CFF)
21 +
22 +
// Light
23 +
val LightBackground = Color(0xFFF4F7FC)
24 +
val LightSurface = Color(0xFFFFFFFF)
25 +
val LightSurfaceSoft = Color(0xFFE9EEF8)
26 +
val LightInk = Color(0xFF1B2333)
27 +
val LightMute = Color(0xFF5F6A81)
28 +
val LightLine = Color(0xFFD6DDED)
29 +
val LightAccent = Color(0xFF0064E0)
30 +
val LightAccent2 = Color(0xFF00B8D4)
31 +
val LightBand = Color(0xFF0B3F9E)
32 +
val LightOk = Color(0xFF1A7850)
33 +
val LightBad = Color(0xFFC62D47)
34 +
val LightWarn = Color(0xFF6B3FD1)
modified app/src/main/java/io/oxygenhub/android/ui/theme/Theme.kt +60 −28
1 1
package io.oxygenhub.android.ui.theme
2 2
3 -
import android.app.Activity
4 -
import android.os.Build
5 3
import androidx.compose.foundation.isSystemInDarkTheme
4 +
import androidx.compose.material3.ColorScheme
6 5
import androidx.compose.material3.MaterialTheme
7 6
import androidx.compose.material3.darkColorScheme
8 7
import androidx.compose.material3.dynamicDarkColorScheme
9 8
import androidx.compose.material3.dynamicLightColorScheme
10 9
import androidx.compose.material3.lightColorScheme
11 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
12 14
import androidx.compose.ui.platform.LocalContext
13 15
14 16
private val DarkColorScheme = darkColorScheme(
15 -
    primary = Purple80,
16 -
    secondary = PurpleGrey80,
17 -
    tertiary = Pink80
17 +
    primary = DarkAccent,
18 +
    onPrimary = DarkBackground,
19 +
    primaryContainer = DarkBand,
20 +
    onPrimaryContainer = Color.White,
21 +
    secondary = DarkAccent2,
22 +
    onSecondary = Color.White,
23 +
    tertiary = DarkWarn,
24 +
    background = DarkBackground,
25 +
    onBackground = DarkInk,
26 +
    surface = DarkBackground,
27 +
    onSurface = DarkInk,
28 +
    surfaceVariant = DarkSurfaceSoft,
29 +
    onSurfaceVariant = DarkMute,
30 +
    surfaceContainerLowest = DarkBackground,
31 +
    surfaceContainerLow = DarkSurface,
32 +
    surfaceContainer = DarkSurface,
33 +
    surfaceContainerHigh = DarkSurfaceSoft,
34 +
    surfaceContainerHighest = DarkSurfaceSoft,
35 +
    outline = DarkMute,
36 +
    outlineVariant = DarkLine,
37 +
    error = DarkBad,
18 38
)
19 39
20 40
private val LightColorScheme = lightColorScheme(
21 -
    primary = Purple40,
22 -
    secondary = PurpleGrey40,
23 -
    tertiary = Pink40
24 -
25 -
    /* Other default colors to override
26 -
    background = Color(0xFFFFFBFE),
27 -
    surface = Color(0xFFFFFBFE),
41 +
    primary = LightAccent,
28 42
    onPrimary = Color.White,
43 +
    primaryContainer = LightBand,
44 +
    onPrimaryContainer = Color.White,
45 +
    secondary = LightAccent2,
29 46
    onSecondary = Color.White,
30 -
    onTertiary = Color.White,
31 -
    onBackground = Color(0xFF1C1B1F),
32 -
    onSurface = Color(0xFF1C1B1F),
33 -
    */
47 +
    tertiary = LightWarn,
48 +
    background = LightBackground,
49 +
    onBackground = LightInk,
50 +
    surface = LightBackground,
51 +
    onSurface = LightInk,
52 +
    surfaceVariant = LightSurfaceSoft,
53 +
    onSurfaceVariant = LightMute,
54 +
    surfaceContainerLowest = LightSurface,
55 +
    surfaceContainerLow = LightSurface,
56 +
    surfaceContainer = LightSurface,
57 +
    surfaceContainerHigh = LightSurfaceSoft,
58 +
    surfaceContainerHighest = LightSurfaceSoft,
59 +
    outline = LightMute,
60 +
    outlineVariant = LightLine,
61 +
    error = LightBad,
34 62
)
63 +
64 +
/** Colours Material has no slot for: an open or closed state. */
65 +
@Immutable
66 +
data class StatusColors(val ok: Color, val bad: Color, val warn: Color)
67 +
68 +
val LocalStatusColors = staticCompositionLocalOf { StatusColors(LightOk, LightBad, LightWarn) }
35 69
36 70
@Composable
37 71
fun OxygenHubTheme(
38 72
    darkTheme: Boolean = isSystemInDarkTheme(),
39 -
    // Dynamic color is available on Android 12+
73 +
    // Wallpaper colours (Android 12, the app's minimum, has them); the
74 +
    // hub's own palette when turned off.
40 75
    dynamicColor: Boolean = true,
41 -
    content: @Composable () -> Unit
76 +
    content: @Composable () -> Unit,
42 77
) {
43 -
    val colorScheme = when {
44 -
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
78 +
    val colorScheme: ColorScheme = when {
79 +
        dynamicColor -> {
45 80
            val context = LocalContext.current
46 81
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
47 82
        }
48 -
49 83
        darkTheme -> DarkColorScheme
50 84
        else -> LightColorScheme
51 85
    }
52 -
53 -
    MaterialTheme(
54 -
        colorScheme = colorScheme,
55 -
        typography = Typography,
56 -
        content = content
57 -
    )
58 -
}
86 +
    val status = if (darkTheme) StatusColors(DarkOk, DarkBad, DarkWarn) else StatusColors(LightOk, LightBad, LightWarn)
87 +
    androidx.compose.runtime.CompositionLocalProvider(LocalStatusColors provides status) {
88 +
        MaterialTheme(colorScheme = colorScheme, typography = Typography, content = content)
89 +
    }
90 +
}
modified app/src/main/res/values/colors.xml +4 −8
1 1
<?xml version="1.0" encoding="utf-8"?>
2 2
<resources>
3 -
    <color name="purple_200">#FFBB86FC</color>
4 -
    <color name="purple_500">#FF6200EE</color>
5 -
    <color name="purple_700">#FF3700B3</color>
6 -
    <color name="teal_200">#FF03DAC5</color>
7 -
    <color name="teal_700">#FF018786</color>
8 -
    <color name="black">#FF000000</color>
9 -
    <color name="white">#FFFFFFFF</color>
10 -
</resources>
3 +
    <!-- The hub's page backgrounds (oxygenhub templates/style.css, the bg colour). -->
4 +
    <color name="window_light">#FFF4F7FC</color>
5 +
    <color name="window_dark">#FF070C18</color>
6 +
</resources>
modified app/src/main/res/values/themes.xml +5 −3
1 1
<?xml version="1.0" encoding="utf-8"?>
2 2
<resources>
3 -
4 -
    <style name="Theme.OxygenHub" parent="android:Theme.Material.Light.NoActionBar" />
5 -
</resources>
3 +
    <!-- The window behind Compose, until it draws: the hub's light page colour. -->
4 +
    <style name="Theme.OxygenHub" parent="android:Theme.Material.Light.NoActionBar">
5 +
        <item name="android:windowBackground">@color/window_light</item>
6 +
    </style>
7 +
</resources>