From d7fd67aeae628cb280b0e1c36607a56e88535c0a Mon Sep 17 00:00:00 2001 From: Artem Chepurnoy Date: Sun, 18 Feb 2024 11:38:48 +0200 Subject: [PATCH] feat: Use the High surface color for the navigation bar if possible #167 --- .../keyguard/android/BaseActivity.kt | 5 +- .../keyguard/feature/twopane/TwoPaneLayout.kt | 5 ++ .../keyguard/feature/twopane/TwoPaneScreen.kt | 5 ++ .../keyguard/ui/surface/BackgroundManager.kt | 74 +++++++++++++++++++ .../keyguard/ui/toolbar/util/ToolbarColors.kt | 9 +-- .../kotlin/com/artemchep/keyguard/Main.kt | 5 +- 6 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 common/src/commonMain/kotlin/com/artemchep/keyguard/ui/surface/BackgroundManager.kt diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/BaseActivity.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/BaseActivity.kt index e11d1a15..429370ca 100644 --- a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/BaseActivity.kt +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/BaseActivity.kt @@ -9,7 +9,7 @@ import android.webkit.MimeTypeMap import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import androidx.browser.customtabs.CustomTabsIntent -import androidx.compose.material3.MaterialTheme +import androidx.compose.animation.animateColorAsState import androidx.compose.material3.Surface import androidx.compose.material3.contentColorFor import androidx.compose.runtime.Composable @@ -46,6 +46,7 @@ import com.artemchep.keyguard.feature.navigation.N import com.artemchep.keyguard.feature.navigation.NavigationController import com.artemchep.keyguard.feature.navigation.NavigationIntent import com.artemchep.keyguard.feature.navigation.NavigationRouterBackHandler +import com.artemchep.keyguard.ui.surface.LocalBackgroundManager import com.artemchep.keyguard.ui.surface.LocalSurfaceColor import com.artemchep.keyguard.ui.theme.KeyguardTheme import com.google.firebase.crashlytics.ktx.crashlytics @@ -100,7 +101,7 @@ abstract class BaseActivity : AppCompatActivity(), DIAware { WindowCompat.setDecorFitsSystemWindows(window, false) setContent { KeyguardTheme { - val containerColor = MaterialTheme.colorScheme.surfaceContainerHighest + val containerColor = LocalBackgroundManager.current.colorHighest val contentColor = contentColorFor(containerColor) Surface( modifier = Modifier.semantics { diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/twopane/TwoPaneLayout.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/twopane/TwoPaneLayout.kt index bea956db..20246e52 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/twopane/TwoPaneLayout.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/twopane/TwoPaneLayout.kt @@ -60,6 +60,7 @@ import com.artemchep.keyguard.ui.scaffoldContentWindowInsets import com.artemchep.keyguard.ui.screenMaxWidth import com.artemchep.keyguard.ui.surface.LocalSurfaceColor import com.artemchep.keyguard.ui.surface.LocalSurfaceElevation +import com.artemchep.keyguard.ui.surface.ReportSurfaceColor import com.artemchep.keyguard.ui.surface.color import com.artemchep.keyguard.ui.surface.splitHigh import com.artemchep.keyguard.ui.surface.splitLow @@ -143,6 +144,8 @@ fun TwoPaneScaffoldScope.TwoPaneLayout( LocalSurfaceColor provides surfaceElevationColor(elevation.to), LocalHasDetailPane provides true, ) { + ReportSurfaceColor() + val horizontalInsets = scaffoldContentWindowInsets .only(WindowInsetsSides.Horizontal) PaneLayout( @@ -165,6 +168,8 @@ fun TwoPaneScaffoldScope.TwoPaneLayout( LocalSurfaceColor provides surfaceElevationColor(elevation.to), LocalHasDetailPane provides false, ) { + ReportSurfaceColor() + PaneLayout( modifier = Modifier .background(surfaceElevation.color), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/twopane/TwoPaneScreen.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/twopane/TwoPaneScreen.kt index 743dec38..277ba8e0 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/twopane/TwoPaneScreen.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/twopane/TwoPaneScreen.kt @@ -27,6 +27,7 @@ import com.artemchep.keyguard.platform.leStatusBars import com.artemchep.keyguard.platform.leSystemBars import com.artemchep.keyguard.ui.surface.LocalSurfaceElevation import com.artemchep.keyguard.ui.surface.ProvideSurfaceColor +import com.artemchep.keyguard.ui.surface.ReportSurfaceColor import com.artemchep.keyguard.ui.surface.splitLow import com.artemchep.keyguard.ui.surface.surfaceElevationColor import com.artemchep.keyguard.ui.theme.Dimens @@ -61,6 +62,8 @@ fun TwoPaneScreen( surfaceElevationColor(elevation) } ProvideSurfaceColor(color) { + ReportSurfaceColor() + val detailIsVisible = this@TwoPaneScaffold.tabletUi val insetsModifier = if (detailIsVisible) { val insetsTop = WindowInsets.leSystemBars @@ -115,6 +118,8 @@ fun TwoPaneScreen( } val detailSurfaceColor = surfaceElevationColor(surfaceElevation.to) ProvideSurfaceColor(detailSurfaceColor) { + ReportSurfaceColor() + content( scope, contentModifier, diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/surface/BackgroundManager.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/surface/BackgroundManager.kt new file mode 100644 index 00000000..59c85bca --- /dev/null +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/surface/BackgroundManager.kt @@ -0,0 +1,74 @@ +package com.artemchep.keyguard.ui.surface + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.mutableStateMapOf +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.graphics.Color +import java.util.UUID + +class BackgroundManager { + private val surfaceColorsState = mutableStateMapOf() + + val colorHighest: Color + @Composable + get() { + val surfaceContainerHigh = MaterialTheme.colorScheme.surfaceContainerHigh + val surfaceContainerHighest = MaterialTheme.colorScheme.surfaceContainerHighest + + var maxPriority = 0 + surfaceColorsState.values.forEach { color -> + val priority = when (color) { + surfaceContainerHigh -> 1 + surfaceContainerHighest -> 2 + else -> 0 + } + if (maxPriority < priority) { + maxPriority = priority + } + } + + return when (maxPriority) { + 0 -> surfaceContainerHigh + 1 -> surfaceContainerHighest + else -> surfaceContainerHighest + } + } + + fun register( + color: Color, + ): () -> Unit { + val key = UUID.randomUUID().toString() + surfaceColorsState[key] = color + + return { + surfaceColorsState.remove(key) + } + } +} + +private val globalBackgroundManager = BackgroundManager() + +val LocalBackgroundManager = staticCompositionLocalOf { + globalBackgroundManager +} + +/** + * Reports the background color to the background manager. This might affect the + * highest elevation elements such as elevated toolbar or the navigation bar/rail. + */ +@Composable +fun ReportSurfaceColor() { + val surfaceColor = LocalSurfaceColor.current + val backgroundManager = LocalBackgroundManager.current + DisposableEffect( + surfaceColor, + backgroundManager, + ) { + val unregister = backgroundManager.register(surfaceColor) + onDispose { + unregister() + } + } +} diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/toolbar/util/ToolbarColors.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/toolbar/util/ToolbarColors.kt index 7d404a1f..e247c0dc 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/toolbar/util/ToolbarColors.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/ui/toolbar/util/ToolbarColors.kt @@ -1,12 +1,9 @@ package com.artemchep.keyguard.ui.toolbar.util -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.graphics.isUnspecified -import androidx.compose.ui.unit.dp -import com.artemchep.keyguard.feature.home.vault.component.surfaceColorAtElevationSemi +import com.artemchep.keyguard.ui.surface.LocalBackgroundManager import com.artemchep.keyguard.ui.surface.LocalSurfaceColor object ToolbarColors { @@ -24,8 +21,6 @@ object ToolbarColors { return containerColor } - val tint = MaterialTheme.colorScheme - .surfaceColorAtElevationSemi(elevation = 2.0.dp) - return tint.compositeOver(MaterialTheme.colorScheme.surfaceContainerLow) + return LocalBackgroundManager.current.colorHighest } } diff --git a/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt b/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt index 35a6c5bc..761da9b2 100644 --- a/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt +++ b/desktopApp/src/jvmMain/kotlin/com/artemchep/keyguard/Main.kt @@ -1,6 +1,6 @@ package com.artemchep.keyguard -import androidx.compose.material3.MaterialTheme +import androidx.compose.animation.animateColorAsState import androidx.compose.material3.Surface import androidx.compose.material3.contentColorFor import androidx.compose.runtime.Composable @@ -46,6 +46,7 @@ import com.artemchep.keyguard.feature.navigation.NavigationRouterBackHandler import com.artemchep.keyguard.platform.lifecycle.LeLifecycleState import com.artemchep.keyguard.res.Res import com.artemchep.keyguard.ui.LocalComposeWindow +import com.artemchep.keyguard.ui.surface.LocalBackgroundManager import com.artemchep.keyguard.ui.surface.LocalSurfaceColor import com.artemchep.keyguard.ui.theme.KeyguardTheme import dev.icerock.moko.resources.compose.painterResource @@ -262,7 +263,7 @@ private fun ApplicationScope.KeyguardWindow( title = "Keyguard", ) { KeyguardTheme { - val containerColor = MaterialTheme.colorScheme.surfaceContainerHighest + val containerColor = LocalBackgroundManager.current.colorHighest val contentColor = contentColorFor(containerColor) Surface( modifier = Modifier.semantics {