Replace landscape and portrait logic with sceen width logic (#4915)

This commit is contained in:
David Perez 2025-03-26 11:09:41 -05:00 committed by GitHub
parent b4b4f753ca
commit 6081b7e932
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 186 additions and 119 deletions

View File

@ -226,6 +226,7 @@ dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.animation)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material3.adaptive)
implementation(libs.androidx.compose.runtime)
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.graphics)

View File

@ -1,6 +1,5 @@
package com.x8bit.bitwarden.ui.auth.feature.accountsetup
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@ -23,7 +22,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
@ -48,8 +46,9 @@ import com.x8bit.bitwarden.ui.platform.components.toggle.BitwardenSwitch
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.x8bit.bitwarden.ui.platform.composition.LocalIntentManager
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.platform.model.WindowSize
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
import com.x8bit.bitwarden.ui.platform.util.isPortrait
import com.x8bit.bitwarden.ui.platform.util.rememberWindowSize
/**
* Top level composable for the Auto-fill setup screen.
@ -198,21 +197,24 @@ private fun SetupAutoFillContent(
@Composable
private fun SetupAutoFillContentHeader(
modifier: Modifier = Modifier,
configuration: Configuration = LocalConfiguration.current,
) {
if (configuration.isPortrait) {
Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally,
) {
OrderedHeaderContent()
when (rememberWindowSize()) {
WindowSize.Compact -> {
Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally,
) {
OrderedHeaderContent()
}
}
} else {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
) {
OrderedHeaderContent()
WindowSize.Medium -> {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
) {
OrderedHeaderContent()
}
}
}
}

View File

@ -1,6 +1,5 @@
package com.x8bit.bitwarden.ui.auth.feature.accountsetup
import android.content.res.Configuration
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
@ -28,7 +27,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
@ -54,8 +52,9 @@ import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.x8bit.bitwarden.ui.platform.composition.LocalBiometricsManager
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricSupportStatus
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManager
import com.x8bit.bitwarden.ui.platform.model.WindowSize
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
import com.x8bit.bitwarden.ui.platform.util.isPortrait
import com.x8bit.bitwarden.ui.platform.util.rememberWindowSize
/**
* Top level composable for the setup unlock screen.
@ -146,15 +145,13 @@ private fun SetupUnlockScreenContent(
handler: SetupUnlockHandler,
modifier: Modifier = Modifier,
biometricsManager: BiometricsManager,
config: Configuration = LocalConfiguration.current,
) {
Column(
modifier = modifier.verticalScroll(state = rememberScrollState()),
) {
if (config.isPortrait) {
SetupUnlockHeaderPortrait()
} else {
SetupUnlockHeaderLandscape()
when (rememberWindowSize()) {
WindowSize.Compact -> SetupUnlockHeaderCompact()
WindowSize.Medium -> SetupUnlockHeaderMedium()
}
Spacer(modifier = Modifier.height(height = 24.dp))
@ -243,7 +240,7 @@ private fun SetUpLaterButton(
}
@Composable
private fun ColumnScope.SetupUnlockHeaderPortrait() {
private fun ColumnScope.SetupUnlockHeaderCompact() {
Spacer(modifier = Modifier.height(height = 32.dp))
Image(
painter = rememberVectorPainter(id = R.drawable.account_setup),
@ -281,7 +278,7 @@ private fun ColumnScope.SetupUnlockHeaderPortrait() {
}
@Composable
private fun SetupUnlockHeaderLandscape(
private fun SetupUnlockHeaderMedium(
modifier: Modifier = Modifier,
) {
Row(

View File

@ -1,6 +1,5 @@
package com.x8bit.bitwarden.ui.auth.feature.completeregistration
import android.content.res.Configuration
import android.widget.Toast
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.Image
@ -27,7 +26,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
@ -57,8 +55,9 @@ import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.x8bit.bitwarden.ui.platform.components.text.BitwardenClickableText
import com.x8bit.bitwarden.ui.platform.components.toggle.BitwardenSwitch
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.x8bit.bitwarden.ui.platform.model.WindowSize
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
import com.x8bit.bitwarden.ui.platform.util.isPortrait
import com.x8bit.bitwarden.ui.platform.util.rememberWindowSize
/**
* Top level composable for the complete registration screen.
@ -341,21 +340,24 @@ private fun CompleteRegistrationContent(
@Composable
private fun CompleteRegistrationContentHeader(
modifier: Modifier = Modifier,
configuration: Configuration = LocalConfiguration.current,
) {
if (configuration.isPortrait) {
Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally,
) {
OrderedHeaderContent()
when (rememberWindowSize()) {
WindowSize.Compact -> {
Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally,
) {
OrderedHeaderContent()
}
}
} else {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
) {
OrderedHeaderContent()
WindowSize.Medium -> {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
) {
OrderedHeaderContent()
}
}
}
}

View File

@ -30,7 +30,6 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.clearAndSetSemantics
@ -48,13 +47,14 @@ import com.x8bit.bitwarden.ui.platform.components.button.BitwardenFilledButton
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenOutlinedButton
import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.x8bit.bitwarden.ui.platform.model.WindowSize
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
import com.x8bit.bitwarden.ui.platform.util.isPortrait
import com.x8bit.bitwarden.ui.platform.util.rememberWindowSize
/**
* The custom horizontal margin that is specific to this screen.
*/
private val LANDSCAPE_HORIZONTAL_MARGIN: Dp = 128.dp
private val HORIZONTAL_MARGIN_MEDIUM: Dp = 128.dp
/**
* Top level composable for the welcome screen.
@ -106,6 +106,7 @@ fun WelcomeScreen(
}
}
@Suppress("LongMethod")
@Composable
private fun WelcomeScreenContent(
state: WelcomeState,
@ -119,7 +120,6 @@ private fun WelcomeScreenContent(
LaunchedEffect(pagerState.currentPage) {
onPagerSwipe(pagerState.currentPage)
}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier.verticalScroll(rememberScrollState()),
@ -132,17 +132,21 @@ private fun WelcomeScreenContent(
val pagerSemanticsModifier = Modifier.semantics(mergeDescendants = true) {
contentDescription = pageNumberContentDescription
}
if (LocalConfiguration.current.isPortrait) {
WelcomeCardPortrait(
state = state.pages[index],
modifier = pagerSemanticsModifier.standardHorizontalMargin(),
)
} else {
WelcomeCardLandscape(
state = state.pages[index],
modifier = pagerSemanticsModifier
.standardHorizontalMargin(landscape = LANDSCAPE_HORIZONTAL_MARGIN),
)
when (rememberWindowSize()) {
WindowSize.Compact -> {
WelcomeCardCompact(
state = state.pages[index],
modifier = pagerSemanticsModifier.standardHorizontalMargin(),
)
}
WindowSize.Medium -> {
WelcomeCardMedium(
state = state.pages[index],
modifier = pagerSemanticsModifier
.standardHorizontalMargin(medium = HORIZONTAL_MARGIN_MEDIUM),
)
}
}
}
@ -161,7 +165,7 @@ private fun WelcomeScreenContent(
label = stringResource(id = R.string.create_account),
onClick = onCreateAccountClick,
modifier = Modifier
.standardHorizontalMargin(landscape = LANDSCAPE_HORIZONTAL_MARGIN)
.standardHorizontalMargin(medium = HORIZONTAL_MARGIN_MEDIUM)
.fillMaxWidth()
.testTag("ChooseAccountCreationButton"),
)
@ -170,7 +174,7 @@ private fun WelcomeScreenContent(
label = stringResource(id = R.string.log_in_verb),
onClick = onLoginClick,
modifier = Modifier
.standardHorizontalMargin(landscape = LANDSCAPE_HORIZONTAL_MARGIN)
.standardHorizontalMargin(medium = HORIZONTAL_MARGIN_MEDIUM)
.fillMaxWidth()
.testTag("ChooseLoginButton"),
)
@ -181,7 +185,7 @@ private fun WelcomeScreenContent(
}
@Composable
private fun WelcomeCardLandscape(
private fun WelcomeCardMedium(
state: WelcomeState.WelcomeCard,
modifier: Modifier = Modifier,
) {
@ -218,7 +222,7 @@ private fun WelcomeCardLandscape(
}
@Composable
private fun WelcomeCardPortrait(
private fun WelcomeCardCompact(
state: WelcomeState.WelcomeCard,
modifier: Modifier = Modifier,
) {

View File

@ -10,6 +10,8 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
@ -33,11 +35,8 @@ import androidx.compose.ui.input.key.type
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasureResult
import androidx.compose.ui.layout.MeasureScope
import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
import androidx.compose.ui.node.LayoutModifierNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.node.currentValueOf
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.testTag
@ -49,8 +48,9 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.offset
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
import com.x8bit.bitwarden.ui.platform.components.model.CardStyle
import com.x8bit.bitwarden.ui.platform.model.WindowSize
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
import com.x8bit.bitwarden.ui.platform.util.isPortrait
import com.x8bit.bitwarden.ui.platform.util.getWindowSize
/**
* Adds a performance-optimized background color specified by the given [topAppBarScrollBehavior]
@ -215,39 +215,65 @@ fun Modifier.tabNavigation(): Modifier {
*/
@OmitFromCoverage
@Stable
@Composable
fun Modifier.standardHorizontalMargin(
portrait: Dp = 16.dp,
landscape: Dp = 48.dp,
compact: Dp = 16.dp,
medium: Dp = 48.dp,
): Modifier =
this then StandardHorizontalMarginElement(portrait = portrait, landscape = landscape)
standardHorizontalMargin(
compact = compact,
medium = medium,
windowAdaptiveInfo = currentWindowAdaptiveInfo(),
)
/**
* This is a [Modifier] extension for ensuring that the content uses the standard horizontal margin.
*/
@OmitFromCoverage
@Stable
fun Modifier.standardHorizontalMargin(
compact: Dp = 16.dp,
medium: Dp = 48.dp,
windowAdaptiveInfo: WindowAdaptiveInfo,
): Modifier =
this then StandardHorizontalMarginElement(
compact = compact,
medium = medium,
windowAdaptiveInfo = windowAdaptiveInfo,
)
private data class StandardHorizontalMarginElement(
private val portrait: Dp,
private val landscape: Dp,
private val compact: Dp,
private val medium: Dp,
private val windowAdaptiveInfo: WindowAdaptiveInfo,
) : ModifierNodeElement<StandardHorizontalMarginElement.StandardHorizontalMarginConsumerNode>() {
override fun create(): StandardHorizontalMarginConsumerNode =
StandardHorizontalMarginConsumerNode(
portrait = portrait,
landscape = landscape,
compact = compact,
medium = medium,
windowAdaptiveInfo = windowAdaptiveInfo,
)
override fun update(node: StandardHorizontalMarginConsumerNode) {
node.portrait = portrait
node.landscape = landscape
node.compact = compact
node.medium = medium
}
class StandardHorizontalMarginConsumerNode(
var portrait: Dp,
var landscape: Dp,
var compact: Dp,
var medium: Dp,
private val windowAdaptiveInfo: WindowAdaptiveInfo,
) : Modifier.Node(),
LayoutModifierNode,
CompositionLocalConsumerModifierNode {
LayoutModifierNode {
override fun MeasureScope.measure(
measurable: Measurable,
constraints: Constraints,
): MeasureResult {
val currentConfig = currentValueOf(LocalConfiguration)
val paddingPx = (if (currentConfig.isPortrait) portrait else landscape).roundToPx()
val paddingPx = when (windowAdaptiveInfo.getWindowSize()) {
WindowSize.Compact -> compact.roundToPx()
WindowSize.Medium -> medium.roundToPx()
}
// Account for the padding on each side.
val horizontalPx = paddingPx * 2
// Measure the placeable within the horizontal space accounting for the padding Px.

View File

@ -0,0 +1,9 @@
package com.x8bit.bitwarden.ui.platform.model
/**
* Enum representing the window size classes currently supported by the app.
*/
enum class WindowSize {
Compact,
Medium,
}

View File

@ -1,15 +0,0 @@
@file:OmitFromCoverage
package com.x8bit.bitwarden.ui.platform.util
import android.content.res.Configuration
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
/**
* A helper method to indicate if the current UI configuration is portrait or not.
*/
val Configuration.isPortrait: Boolean
get() = when (this.orientation) {
Configuration.ORIENTATION_LANDSCAPE -> false
else -> true
}

View File

@ -0,0 +1,33 @@
package com.x8bit.bitwarden.ui.platform.util
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.window.core.layout.WindowWidthSizeClass
import com.x8bit.bitwarden.ui.platform.model.WindowSize
/**
* Remembers the [WindowSize] class for the window corresponding to the current window metrics.
*/
@Composable
fun rememberWindowSize(
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
): WindowSize {
return remember(key1 = windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass) {
windowAdaptiveInfo.getWindowSize()
}
}
/**
* Retrieves the [WindowSize] class for the window corresponding to the current window metrics.
*/
fun WindowAdaptiveInfo.getWindowSize(): WindowSize {
// Currently the app only operates with the Compact and Medium sizes in
// mind, but we can add support for others in the future here.
return when (this.windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> WindowSize.Compact
WindowWidthSizeClass.MEDIUM -> WindowSize.Medium
else -> WindowSize.Medium
}
}

View File

@ -17,6 +17,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
@ -382,6 +383,7 @@ private fun CoachMarkScope<ExploreGeneratorCoachMark>.ScrollContent(
onCoachMarkComplete: () -> Unit,
modifier: Modifier = Modifier,
) {
val windowAdaptiveInfo = currentWindowAdaptiveInfo()
LazyColumn(
state = lazyListState,
modifier = modifier
@ -461,7 +463,7 @@ private fun CoachMarkScope<ExploreGeneratorCoachMark>.ScrollContent(
onActionClick = onCoachMarkComplete,
)
},
modifier = Modifier.standardHorizontalMargin(),
modifier = Modifier.standardHorizontalMargin(windowAdaptiveInfo = windowAdaptiveInfo),
) {
BitwardenFilledButton(
label = stringResource(id = R.string.copy),
@ -507,7 +509,8 @@ private fun CoachMarkScope<ExploreGeneratorCoachMark>.ScrollContent(
onActionClick = onShowNextCoachMark,
)
},
modifier = Modifier.standardHorizontalMargin(),
modifier = Modifier
.standardHorizontalMargin(windowAdaptiveInfo = windowAdaptiveInfo),
) {
PasswordTypeContent(
passwordTypeState = selectedType,

View File

@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
@ -70,6 +71,7 @@ fun CoachMarkScope<AddEditItemCoachMark>.VaultAddEditContent(
)
var isAdditionalOptionsExpanded = rememberSaveable { mutableStateOf(value = false) }
val windowAdaptiveInfo = currentWindowAdaptiveInfo()
LazyColumn(modifier = modifier, state = lazyListState) {
item {
Spacer(modifier = Modifier.height(height = 12.dp))
@ -196,6 +198,7 @@ fun CoachMarkScope<AddEditItemCoachMark>.VaultAddEditContent(
vaultAddEditLoginItems(
loginState = state.type,
loginItemTypeHandlers = loginItemTypeHandlers,
windowAdaptiveInfo = windowAdaptiveInfo,
onTotpSetupClick = {
if (permissionsManager.checkPermission(Manifest.permission.CAMERA)) {
loginItemTypeHandlers.onSetupTotpClick(true)

View File

@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -46,6 +47,7 @@ fun LazyListScope.vaultAddEditLoginItems(
coachMarkScope: CoachMarkScope<AddEditItemCoachMark>,
loginState: VaultAddEditState.ViewState.Content.ItemType.Login,
loginItemTypeHandlers: VaultAddEditLoginTypeHandlers,
windowAdaptiveInfo: WindowAdaptiveInfo,
onTotpSetupClick: () -> Unit,
onNextCoachMark: () -> Unit,
onPreviousCoachMark: () -> Unit,
@ -124,7 +126,7 @@ fun LazyListScope.vaultAddEditLoginItems(
},
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin(),
.standardHorizontalMargin(windowAdaptiveInfo = windowAdaptiveInfo),
) {
TotpRow(
totpKey = loginState.totp,
@ -182,7 +184,7 @@ fun LazyListScope.vaultAddEditLoginItems(
},
items = loginState.uriList,
modifier = Modifier
.standardHorizontalMargin(),
.standardHorizontalMargin(windowAdaptiveInfo = windowAdaptiveInfo),
) { uriItem, cardStyle ->
VaultAddEditUriItem(
uriItem = uriItem,
@ -230,8 +232,7 @@ private fun UsernameRow(
BitwardenTwoButtonDialog(
title = stringResource(id = R.string.username),
message = stringResource(
id =
R.string.are_you_sure_you_want_to_overwrite_the_current_username,
id = R.string.are_you_sure_you_want_to_overwrite_the_current_username,
),
confirmButtonText = stringResource(id = R.string.yes),
dismissButtonText = stringResource(id = R.string.no),
@ -323,10 +324,7 @@ private fun CoachMarkScope<AddEditItemCoachMark>.PasswordRow(
if (shouldShowDialog) {
BitwardenTwoButtonDialog(
title = stringResource(id = R.string.password),
message = stringResource(
id =
R.string.password_override_alert,
),
message = stringResource(id = R.string.password_override_alert),
confirmButtonText = stringResource(id = R.string.yes),
dismissButtonText = stringResource(id = R.string.no),
onConfirmClick = {

View File

@ -39,7 +39,6 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.CustomAccessibilityAction
@ -58,10 +57,11 @@ import com.x8bit.bitwarden.ui.platform.base.util.toAnnotatedString
import com.x8bit.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.x8bit.bitwarden.ui.platform.model.WindowSize
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
import com.x8bit.bitwarden.ui.platform.theme.LocalBitwardenColorScheme
import com.x8bit.bitwarden.ui.platform.theme.color.darkBitwardenColorScheme
import com.x8bit.bitwarden.ui.platform.util.isPortrait
import com.x8bit.bitwarden.ui.platform.util.rememberWindowSize
import com.x8bit.bitwarden.ui.vault.feature.qrcodescan.util.QrCodeAnalyzer
import com.x8bit.bitwarden.ui.vault.feature.qrcodescan.util.QrCodeAnalyzerImpl
import java.util.concurrent.Executors
@ -76,9 +76,9 @@ import kotlin.coroutines.suspendCoroutine
@Composable
fun QrCodeScanScreen(
onNavigateBack: () -> Unit,
onNavigateToManualCodeEntryScreen: () -> Unit,
viewModel: QrCodeScanViewModel = hiltViewModel(),
qrCodeAnalyzer: QrCodeAnalyzer = QrCodeAnalyzerImpl(),
onNavigateToManualCodeEntryScreen: () -> Unit,
) {
qrCodeAnalyzer.onQrCodeScanned = remember(viewModel) {
{ viewModel.trySendAction(QrCodeScanAction.QrCodeScanReceive(it)) }
@ -131,22 +131,25 @@ fun QrCodeScanScreen(
},
qrCodeAnalyzer = qrCodeAnalyzer,
)
when (rememberWindowSize()) {
WindowSize.Compact -> {
QrCodeContentCompact(
onEnterKeyManuallyClick = onEnterKeyManuallyClick,
)
}
if (LocalConfiguration.current.isPortrait) {
PortraitQRCodeContent(
onEnterKeyManuallyClick = onEnterKeyManuallyClick,
)
} else {
LandscapeQRCodeContent(
onEnterKeyManuallyClick = onEnterKeyManuallyClick,
)
WindowSize.Medium -> {
QrCodeContentMedium(
onEnterKeyManuallyClick = onEnterKeyManuallyClick,
)
}
}
}
}
}
@Composable
private fun PortraitQRCodeContent(
private fun QrCodeContentCompact(
onEnterKeyManuallyClick: () -> Unit,
modifier: Modifier = Modifier,
) {
@ -186,7 +189,7 @@ private fun PortraitQRCodeContent(
}
@Composable
private fun LandscapeQRCodeContent(
private fun QrCodeContentMedium(
onEnterKeyManuallyClick: () -> Unit,
modifier: Modifier = Modifier,
) {
@ -294,7 +297,7 @@ private fun CameraPreview(
} else {
cameraErrorReceive()
}
} catch (e: Exception) {
} catch (_: Exception) {
cameraErrorReceive()
}
}

View File

@ -75,6 +75,7 @@ androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "
androidx-compose-animation = { module = "androidx.compose.animation:animation" }
androidx-compose-bom = { module = "androidx.compose:compose-bom", version.ref = "androidxComposeBom" }
androidx-compose-material3 = { module = "androidx.compose.material3:material3" }
androidx-compose-material3-adaptive = { module = "androidx.compose.material3.adaptive:adaptive" }
androidx-compose-runtime = { module = "androidx.compose.runtime:runtime" }
androidx-compose-ui = { module = "androidx.compose.ui:ui" }
androidx-compose-ui-graphics = { module = "androidx.compose.ui:ui-graphics" }