diff --git a/app/src/main/java/com/ganjoor/android/MainActivity.kt b/app/src/main/java/com/ganjoor/android/MainActivity.kt index e0ef431..7cca660 100644 --- a/app/src/main/java/com/ganjoor/android/MainActivity.kt +++ b/app/src/main/java/com/ganjoor/android/MainActivity.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.LayoutDirection +import androidx.core.graphics.drawable.toDrawable import com.ganjoor.android.data.Bookmarks import com.ganjoor.android.data.Ganjoor import com.ganjoor.android.data.LocalBookmarks @@ -17,6 +18,7 @@ import com.ganjoor.android.ui.GanjoorApp import com.ganjoor.android.ui.LocalSettings import com.ganjoor.android.ui.Settings import com.ganjoor.android.ui.theme.GanjoorTheme +import com.ganjoor.android.ui.theme.windowBackground import java.util.Locale class MainActivity : ComponentActivity() { @@ -35,9 +37,19 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Ganjoor.init(applicationContext) + + // Before the first frame: otherwise the window keeps the platform's white through + // startup and every screen transition, whatever theme is chosen. + val settings = Settings(applicationContext) + val systemInDark = resources.configuration.uiMode and + Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES + window.setBackgroundDrawable( + windowBackground(settings.value.theme, systemInDark).toDrawable() + ) + enableEdgeToEdge() setContent { - val settings = remember { Settings(applicationContext) } + val settings = remember { settings } val bookmarks = remember { Bookmarks(applicationContext) } // The client reads this flag on every request, so keep it in step with the setting. Ganjoor.offline = settings.value.offline diff --git a/app/src/main/java/com/ganjoor/android/ui/Load.kt b/app/src/main/java/com/ganjoor/android/ui/Load.kt index c4296d4..ca1e701 100644 --- a/app/src/main/java/com/ganjoor/android/ui/Load.kt +++ b/app/src/main/java/com/ganjoor/android/ui/Load.kt @@ -1,5 +1,6 @@ package com.ganjoor.android.ui +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -36,12 +37,23 @@ fun Load(key: Any?, block: suspend () -> T, content: @Composable (T) -> Unit result.let { outcome -> when { - outcome == null -> Box(Modifier.fillMaxSize(), Alignment.Center) { + // Painted explicitly: on the category and poem screens Load sits outside the + // Scaffold, so while loading nothing else fills the window and the bare window + // background would show through. + outcome == null -> Box( + modifier = Modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background), + contentAlignment = Alignment.Center, + ) { CircularProgressIndicator() } outcome.isFailure -> Column( - modifier = Modifier.fillMaxSize().padding(24.dp), + modifier = Modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background) + .padding(24.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, ) { diff --git a/app/src/main/java/com/ganjoor/android/ui/theme/Theme.kt b/app/src/main/java/com/ganjoor/android/ui/theme/Theme.kt index eea1d0c..49bb34a 100644 --- a/app/src/main/java/com/ganjoor/android/ui/theme/Theme.kt +++ b/app/src/main/java/com/ganjoor/android/ui/theme/Theme.kt @@ -8,7 +8,9 @@ import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalView +import androidx.core.graphics.drawable.toDrawable import androidx.core.view.WindowCompat import com.ganjoor.android.ui.Language import com.ganjoor.android.ui.ThemeMode @@ -146,6 +148,20 @@ private val SepiaDarkScheme = darkColorScheme( outline = Color(0xFF968A72), ) +/** + * The window's own background colour for a theme. The activity paints this before Compose runs, + * so the gap between the window appearing and the first frame matches the theme instead of + * flashing the platform's white. A static XML theme can't express sepia or OLED, hence this. + */ +fun windowBackground(mode: ThemeMode, systemInDark: Boolean): Int = when (mode) { + ThemeMode.Light -> LightScheme + ThemeMode.Dark -> DarkScheme + ThemeMode.Sepia -> SepiaScheme + ThemeMode.SepiaDark -> SepiaDarkScheme + ThemeMode.Black -> BlackScheme + ThemeMode.System -> if (systemInDark) DarkScheme else LightScheme +}.background.toArgb() + @Composable fun GanjoorTheme(mode: ThemeMode, language: Language, content: @Composable () -> Unit) { val dark = when (mode) { @@ -164,6 +180,9 @@ fun GanjoorTheme(mode: ThemeMode, language: Language, content: @Composable () -> if (!view.isInEditMode) { SideEffect { val window = (view.context as Activity).window + // Keep the window in step when the theme changes, so switching themes doesn't leave + // a stale colour behind transitions. + window.setBackgroundDrawable(scheme.background.toArgb().toDrawable()) WindowCompat.getInsetsController(window, view).apply { isAppearanceLightStatusBars = !dark isAppearanceLightNavigationBars = !dark diff --git a/app/src/main/res/values-night-v31/themes.xml b/app/src/main/res/values-night-v31/themes.xml new file mode 100644 index 0000000..b0717b3 --- /dev/null +++ b/app/src/main/res/values-night-v31/themes.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml new file mode 100644 index 0000000..8db70f9 --- /dev/null +++ b/app/src/main/res/values-night/colors.xml @@ -0,0 +1,5 @@ + + + + #191C1C + diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..31f7796 --- /dev/null +++ b/app/src/main/res/values-night/themes.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/app/src/main/res/values-v31/themes.xml b/app/src/main/res/values-v31/themes.xml new file mode 100644 index 0000000..129f192 --- /dev/null +++ b/app/src/main/res/values-v31/themes.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index f8c6127..75568d7 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,10 +1,5 @@ - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 - #FF000000 - #FFFFFFFF - \ No newline at end of file + + #FAFDFC + diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 04c4343..f93eb02 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,5 +1,12 @@ - +