diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt index 2507da8d67..27590313bd 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt @@ -51,6 +51,7 @@ import androidx.core.content.ContextCompat import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.LocalLifecycleOwner import com.bitwarden.ui.platform.base.util.EventsEffect +import com.bitwarden.ui.platform.base.util.StatusBarsAppearanceAffect import com.bitwarden.ui.platform.base.util.annotatedStringResource import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold @@ -101,6 +102,7 @@ fun QrCodeScanScreen( } // This screen should always look like it's in dark mode CompositionLocalProvider(LocalBitwardenColorScheme provides darkBitwardenColorScheme) { + StatusBarsAppearanceAffect(isLightStatusBars = false) BitwardenScaffold( modifier = Modifier.fillMaxSize(), topBar = { diff --git a/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/qrcodescan/QrCodeScanScreen.kt b/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/qrcodescan/QrCodeScanScreen.kt index c87f417c3d..f7c846e08e 100644 --- a/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/qrcodescan/QrCodeScanScreen.kt +++ b/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/qrcodescan/QrCodeScanScreen.kt @@ -23,8 +23,8 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api 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.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -52,6 +52,7 @@ import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.bitwarden.authenticator.ui.platform.util.isPortrait import com.bitwarden.ui.platform.base.util.EventsEffect +import com.bitwarden.ui.platform.base.util.StatusBarsAppearanceAffect import com.bitwarden.ui.platform.base.util.annotatedStringResource import com.bitwarden.ui.platform.base.util.spanStyleOf import com.bitwarden.ui.platform.base.util.standardHorizontalMargin @@ -63,6 +64,8 @@ import com.bitwarden.ui.platform.feature.qrcodescan.util.QrCodeAnalyzerImpl 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 java.util.concurrent.Executors import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine @@ -98,48 +101,52 @@ fun QrCodeScanScreen( } } - QrCodeScanDialogs( - dialogState = state.dialog, - onSaveHereClick = remember(viewModel) { - { viewModel.trySendAction(QrCodeScanAction.SaveLocallyClick(it)) } - }, - onTakeMeToBitwardenClick = remember(viewModel) { - { viewModel.trySendAction(QrCodeScanAction.SaveToBitwardenClick(it)) } - }, - onDismissRequest = remember(viewModel) { - { viewModel.trySendAction(QrCodeScanAction.SaveToBitwardenErrorDismiss) } - }, - ) - - BitwardenScaffold( - modifier = Modifier.fillMaxSize(), - topBar = { - BitwardenTopAppBar( - title = stringResource(id = BitwardenString.scan_qr_code), - navigationIcon = painterResource(id = BitwardenDrawable.ic_close), - navigationIconContentDescription = stringResource(id = BitwardenString.close), - onNavigationIconClick = remember(viewModel) { - { viewModel.trySendAction(QrCodeScanAction.CloseClick) } - }, - scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()), - ) - }, - ) { - CameraPreview( - cameraErrorReceive = remember(viewModel) { - { viewModel.trySendAction(QrCodeScanAction.CameraSetupErrorReceive) } + // This screen should always look like it's in dark mode + CompositionLocalProvider(LocalBitwardenColorScheme provides darkBitwardenColorScheme) { + StatusBarsAppearanceAffect(isLightStatusBars = false) + QrCodeScanDialogs( + dialogState = state.dialog, + onSaveHereClick = remember(viewModel) { + { viewModel.trySendAction(QrCodeScanAction.SaveLocallyClick(it)) } + }, + onTakeMeToBitwardenClick = remember(viewModel) { + { viewModel.trySendAction(QrCodeScanAction.SaveToBitwardenClick(it)) } + }, + onDismissRequest = remember(viewModel) { + { viewModel.trySendAction(QrCodeScanAction.SaveToBitwardenErrorDismiss) } }, - qrCodeAnalyzer = qrCodeAnalyzer, ) - if (LocalConfiguration.current.isPortrait) { - PortraitQRCodeContent( - onEnterCodeManuallyClick = onEnterCodeManuallyClick, - ) - } else { - LandscapeQRCodeContent( - onEnterCodeManuallyClick = onEnterCodeManuallyClick, + BitwardenScaffold( + modifier = Modifier.fillMaxSize(), + topBar = { + BitwardenTopAppBar( + title = stringResource(id = BitwardenString.scan_qr_code), + navigationIcon = painterResource(id = BitwardenDrawable.ic_close), + navigationIconContentDescription = stringResource(id = BitwardenString.close), + onNavigationIconClick = remember(viewModel) { + { viewModel.trySendAction(QrCodeScanAction.CloseClick) } + }, + scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(), + ) + }, + ) { + CameraPreview( + cameraErrorReceive = remember(viewModel) { + { viewModel.trySendAction(QrCodeScanAction.CameraSetupErrorReceive) } + }, + qrCodeAnalyzer = qrCodeAnalyzer, ) + + if (LocalConfiguration.current.isPortrait) { + PortraitQRCodeContent( + onEnterCodeManuallyClick = onEnterCodeManuallyClick, + ) + } else { + LandscapeQRCodeContent( + onEnterCodeManuallyClick = onEnterCodeManuallyClick, + ) + } } } } diff --git a/ui/src/main/kotlin/com/bitwarden/ui/platform/base/util/StatusBarsAppearanceAffect.kt b/ui/src/main/kotlin/com/bitwarden/ui/platform/base/util/StatusBarsAppearanceAffect.kt new file mode 100644 index 0000000000..b8aae9e0e0 --- /dev/null +++ b/ui/src/main/kotlin/com/bitwarden/ui/platform/base/util/StatusBarsAppearanceAffect.kt @@ -0,0 +1,30 @@ +package com.bitwarden.ui.platform.base.util + +import android.app.Activity +import android.view.View +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat + +/** + * Sets the appearance of the StatusBars to the [isLightStatusBars] value and clears the value once + * disposed. + */ +@Composable +fun StatusBarsAppearanceAffect( + isLightStatusBars: Boolean, + view: View = LocalView.current, +) { + if (view.isInEditMode) return + val activity = view.context as Activity + DisposableEffect(Unit) { + val insetsController = WindowCompat.getInsetsController(activity.window, view) + val originalStatusBarValue = insetsController.isAppearanceLightStatusBars + insetsController.isAppearanceLightStatusBars = isLightStatusBars + + onDispose { + insetsController.isAppearanceLightStatusBars = originalStatusBarValue + } + } +}