The QrCodeScanScreen should always be in dark mode (#5983)

This commit is contained in:
David Perez
2025-10-07 15:31:44 -05:00
committed by GitHub
parent 97c4cd705b
commit d306813d1f
3 changed files with 78 additions and 39 deletions

View File

@@ -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 = {

View File

@@ -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,
)
}
}
}
}

View File

@@ -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
}
}
}