mirror of
https://github.com/bitwarden/android.git
synced 2026-08-01 03:05:47 -05:00
PM-40885: bug: Support overriding the colorscheme (#7206)
This commit is contained in:
+3
-6
@@ -15,7 +15,6 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -28,6 +27,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bitwarden.ui.platform.base.util.ColorSchemeOverride
|
||||
import com.bitwarden.ui.platform.base.util.EventsEffect
|
||||
import com.bitwarden.ui.platform.base.util.StatusBarsAppearanceAffect
|
||||
import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
|
||||
@@ -37,12 +37,11 @@ import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
|
||||
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
|
||||
import com.bitwarden.ui.platform.composition.LocalCardTextAnalyzer
|
||||
import com.bitwarden.ui.platform.feature.cardscanner.util.CardTextAnalyzer
|
||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||
import com.bitwarden.ui.platform.model.WindowSize
|
||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
import com.bitwarden.ui.platform.theme.LocalBitwardenColorScheme
|
||||
import com.bitwarden.ui.platform.theme.color.darkBitwardenColorScheme
|
||||
import com.bitwarden.ui.platform.util.rememberWindowSize
|
||||
|
||||
/**
|
||||
@@ -71,9 +70,7 @@ fun CardScanScreen(
|
||||
}
|
||||
|
||||
// This screen should always look like it's in dark mode
|
||||
CompositionLocalProvider(
|
||||
LocalBitwardenColorScheme provides darkBitwardenColorScheme,
|
||||
) {
|
||||
ColorSchemeOverride(appTheme = AppTheme.DARK) {
|
||||
StatusBarsAppearanceAffect()
|
||||
BitwardenScaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
|
||||
+3
-4
@@ -15,13 +15,13 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import com.bitwarden.ui.platform.base.util.ColorSchemeOverride
|
||||
import com.bitwarden.ui.platform.base.util.EventsEffect
|
||||
import com.bitwarden.ui.platform.base.util.StatusBarsAppearanceAffect
|
||||
import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
|
||||
@@ -32,12 +32,11 @@ import com.bitwarden.ui.platform.components.text.BitwardenHyperTextLink
|
||||
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
|
||||
import com.bitwarden.ui.platform.composition.LocalQrCodeAnalyzer
|
||||
import com.bitwarden.ui.platform.feature.qrcodescan.util.QrCodeAnalyzer
|
||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||
import com.bitwarden.ui.platform.model.WindowSize
|
||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
import com.bitwarden.ui.platform.theme.LocalBitwardenColorScheme
|
||||
import com.bitwarden.ui.platform.theme.color.darkBitwardenColorScheme
|
||||
import com.bitwarden.ui.platform.util.rememberWindowSize
|
||||
|
||||
/**
|
||||
@@ -70,7 +69,7 @@ fun QrCodeScanScreen(
|
||||
}
|
||||
}
|
||||
// This screen should always look like it's in dark mode
|
||||
CompositionLocalProvider(LocalBitwardenColorScheme provides darkBitwardenColorScheme) {
|
||||
ColorSchemeOverride(appTheme = AppTheme.DARK) {
|
||||
StatusBarsAppearanceAffect()
|
||||
BitwardenScaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
|
||||
+3
-4
@@ -14,7 +14,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -25,6 +24,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bitwarden.ui.platform.base.util.ColorSchemeOverride
|
||||
import com.bitwarden.ui.platform.base.util.EventsEffect
|
||||
import com.bitwarden.ui.platform.base.util.StatusBarsAppearanceAffect
|
||||
import com.bitwarden.ui.platform.base.util.standardHorizontalMargin
|
||||
@@ -36,12 +36,11 @@ import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
|
||||
import com.bitwarden.ui.platform.components.text.BitwardenHyperTextLink
|
||||
import com.bitwarden.ui.platform.composition.LocalQrCodeAnalyzer
|
||||
import com.bitwarden.ui.platform.feature.qrcodescan.util.QrCodeAnalyzer
|
||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||
import com.bitwarden.ui.platform.model.WindowSize
|
||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
import com.bitwarden.ui.platform.theme.LocalBitwardenColorScheme
|
||||
import com.bitwarden.ui.platform.theme.color.darkBitwardenColorScheme
|
||||
import com.bitwarden.ui.platform.util.rememberWindowSize
|
||||
|
||||
/**
|
||||
@@ -76,7 +75,7 @@ fun QrCodeScanScreen(
|
||||
}
|
||||
|
||||
// This screen should always look like it's in dark mode
|
||||
CompositionLocalProvider(LocalBitwardenColorScheme provides darkBitwardenColorScheme) {
|
||||
ColorSchemeOverride(appTheme = AppTheme.DARK) {
|
||||
StatusBarsAppearanceAffect()
|
||||
QrCodeScanDialogs(
|
||||
dialogState = state.dialog,
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.bitwarden.ui.platform.base.util
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
import com.bitwarden.ui.platform.theme.LocalBitwardenColorScheme
|
||||
import com.bitwarden.ui.platform.theme.LocalBitwardenDynamicDarkColorScheme
|
||||
import com.bitwarden.ui.platform.theme.LocalBitwardenDynamicLightColorScheme
|
||||
import com.bitwarden.ui.platform.theme.color.BitwardenColorScheme
|
||||
import com.bitwarden.ui.platform.theme.color.darkBitwardenColorScheme
|
||||
import com.bitwarden.ui.platform.theme.color.lightBitwardenColorScheme
|
||||
|
||||
/**
|
||||
* Overrides the [BitwardenColorScheme] for the [content] based on the provided [AppTheme].
|
||||
*/
|
||||
@Composable
|
||||
fun ColorSchemeOverride(
|
||||
appTheme: AppTheme,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val colorSchemeOverride = when (appTheme) {
|
||||
AppTheme.DEFAULT -> BitwardenTheme.colorScheme
|
||||
AppTheme.DARK -> {
|
||||
if (BitwardenTheme.colorScheme.isDynamicTheme) {
|
||||
LocalBitwardenDynamicDarkColorScheme.current
|
||||
} else {
|
||||
darkBitwardenColorScheme
|
||||
}
|
||||
}
|
||||
|
||||
AppTheme.LIGHT -> {
|
||||
if (BitwardenTheme.colorScheme.isDynamicTheme) {
|
||||
LocalBitwardenDynamicLightColorScheme.current
|
||||
} else {
|
||||
lightBitwardenColorScheme
|
||||
}
|
||||
}
|
||||
}
|
||||
CompositionLocalProvider(
|
||||
value = LocalBitwardenColorScheme provides colorSchemeOverride,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bitwarden.ui.platform.theme
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -13,6 +14,7 @@ import androidx.compose.runtime.ProvidableCompositionLocal
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import com.bitwarden.core.util.isBuildVersionAtLeast
|
||||
import com.bitwarden.ui.platform.components.field.interceptor.IncognitoInput
|
||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||
import com.bitwarden.ui.platform.theme.color.BitwardenColorScheme
|
||||
@@ -61,39 +63,44 @@ object BitwardenTheme {
|
||||
*/
|
||||
@Composable
|
||||
fun BitwardenTheme(
|
||||
context: Context = LocalContext.current,
|
||||
theme: AppTheme = AppTheme.DEFAULT,
|
||||
dynamicColor: Boolean = false,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val darkTheme = theme.isDarkMode(isSystemDarkMode = isSystemInDarkTheme())
|
||||
// Get the current scheme
|
||||
val materialColorScheme = when {
|
||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||
val context = LocalContext.current
|
||||
if (darkTheme) {
|
||||
dynamicDarkColorScheme(context = context)
|
||||
} else {
|
||||
dynamicLightColorScheme(context = context)
|
||||
}
|
||||
}
|
||||
|
||||
darkTheme -> darkColorScheme()
|
||||
else -> lightColorScheme()
|
||||
val isDarkTheme = theme.isDarkMode(isSystemDarkMode = isSystemInDarkTheme())
|
||||
val isDynamicEnabled = dynamicColor && isBuildVersionAtLeast(version = Build.VERSION_CODES.S)
|
||||
// Get the material color schemes from the OS.
|
||||
val darkMaterialColorScheme = if (isDynamicEnabled) {
|
||||
dynamicDarkColorScheme(context = context)
|
||||
} else {
|
||||
darkColorScheme()
|
||||
}
|
||||
val lightMaterialColorScheme = if (isDynamicEnabled) {
|
||||
dynamicLightColorScheme(context = context)
|
||||
} else {
|
||||
lightColorScheme()
|
||||
}
|
||||
val materialColorScheme = if (isDarkTheme) darkMaterialColorScheme else lightMaterialColorScheme
|
||||
// Convert the material color schemes to Bitwarden color schemes.
|
||||
val lightDynamicColorScheme = dynamicBitwardenColorScheme(
|
||||
materialColorScheme = lightMaterialColorScheme,
|
||||
isDarkTheme = false,
|
||||
)
|
||||
val darkDynamicColorScheme = dynamicBitwardenColorScheme(
|
||||
materialColorScheme = darkMaterialColorScheme,
|
||||
isDarkTheme = true,
|
||||
)
|
||||
val bitwardenColorScheme = when {
|
||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||
dynamicBitwardenColorScheme(
|
||||
materialColorScheme = materialColorScheme,
|
||||
isDarkTheme = darkTheme,
|
||||
)
|
||||
}
|
||||
|
||||
darkTheme -> darkBitwardenColorScheme
|
||||
isDynamicEnabled -> if (isDarkTheme) darkDynamicColorScheme else lightDynamicColorScheme
|
||||
isDarkTheme -> darkBitwardenColorScheme
|
||||
else -> lightBitwardenColorScheme
|
||||
}
|
||||
|
||||
// Provide the selected color scheme as well as the dynamic ones for override support.
|
||||
CompositionLocalProvider(
|
||||
LocalBitwardenColorScheme provides bitwardenColorScheme,
|
||||
LocalBitwardenDynamicLightColorScheme provides lightDynamicColorScheme,
|
||||
LocalBitwardenDynamicDarkColorScheme provides darkDynamicColorScheme,
|
||||
LocalBitwardenShapes provides bitwardenShapes,
|
||||
LocalBitwardenTypography provides bitwardenTypography,
|
||||
) {
|
||||
@@ -112,6 +119,20 @@ fun BitwardenTheme(
|
||||
val LocalBitwardenColorScheme: ProvidableCompositionLocal<BitwardenColorScheme> =
|
||||
compositionLocalOf { lightBitwardenColorScheme }
|
||||
|
||||
/**
|
||||
* Provides access to the Bitwarden dynamic light-mode colors throughout the app.
|
||||
* This is only to be used for scenarios that require the UI to have its colors overridden.
|
||||
*/
|
||||
val LocalBitwardenDynamicLightColorScheme: ProvidableCompositionLocal<BitwardenColorScheme> =
|
||||
compositionLocalOf { lightBitwardenColorScheme }
|
||||
|
||||
/**
|
||||
* Provides access to the Bitwarden default dark-mode colors throughout the app.
|
||||
* This is only to be used for dynamic that require the UI to have its colors overridden.
|
||||
*/
|
||||
val LocalBitwardenDynamicDarkColorScheme: ProvidableCompositionLocal<BitwardenColorScheme> =
|
||||
compositionLocalOf { darkBitwardenColorScheme }
|
||||
|
||||
/**
|
||||
* Provides access to the Bitwarden shapes throughout the app.
|
||||
*/
|
||||
|
||||
@@ -210,7 +210,7 @@ val lightBitwardenColorScheme: BitwardenColorScheme = BitwardenColorScheme(
|
||||
* Creates a [BitwardenColorScheme] based on dynamic Material You colors.
|
||||
*/
|
||||
@Suppress("LongMethod")
|
||||
fun dynamicBitwardenColorScheme(
|
||||
internal fun dynamicBitwardenColorScheme(
|
||||
materialColorScheme: ColorScheme,
|
||||
isDarkTheme: Boolean,
|
||||
): BitwardenColorScheme {
|
||||
@@ -310,7 +310,7 @@ fun dynamicBitwardenColorScheme(
|
||||
* Derives a Material [ColorScheme] from the [BitwardenColorScheme] using the [defaultColorScheme]
|
||||
* as a baseline.
|
||||
*/
|
||||
fun BitwardenColorScheme.toMaterialColorScheme(
|
||||
internal fun BitwardenColorScheme.toMaterialColorScheme(
|
||||
defaultColorScheme: ColorScheme,
|
||||
): ColorScheme = defaultColorScheme.copy(
|
||||
primary = this.stroke.border,
|
||||
|
||||
Reference in New Issue
Block a user