From 6081b7e93282b23e4e133d3cffccc0a2eca2110d Mon Sep 17 00:00:00 2001 From: David Perez Date: Wed, 26 Mar 2025 11:09:41 -0500 Subject: [PATCH] Replace landscape and portrait logic with sceen width logic (#4915) --- app/build.gradle.kts | 1 + .../accountsetup/SetupAutofillScreen.kt | 34 +++++----- .../feature/accountsetup/SetupUnlockScreen.kt | 17 ++--- .../CompleteRegistrationScreen.kt | 34 +++++----- .../ui/auth/feature/welcome/WelcomeScreen.kt | 42 ++++++------ .../platform/base/util/ModifierExtensions.kt | 64 +++++++++++++------ .../bitwarden/ui/platform/model/WindowSize.kt | 9 +++ .../platform/util/ConfigurationExtensions.kt | 15 ----- .../util/WindowAdaptiveInfoExtensions.kt | 33 ++++++++++ .../feature/generator/GeneratorScreen.kt | 7 +- .../addedit/VaultAddEditItemContent.kt | 3 + .../feature/addedit/VaultAddEditLoginItems.kt | 14 ++-- .../feature/qrcodescan/QrCodeScanScreen.kt | 31 +++++---- gradle/libs.versions.toml | 1 + 14 files changed, 186 insertions(+), 119 deletions(-) create mode 100644 app/src/main/java/com/x8bit/bitwarden/ui/platform/model/WindowSize.kt delete mode 100644 app/src/main/java/com/x8bit/bitwarden/ui/platform/util/ConfigurationExtensions.kt create mode 100644 app/src/main/java/com/x8bit/bitwarden/ui/platform/util/WindowAdaptiveInfoExtensions.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6dd6f9b76a..0d72470eeb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -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) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupAutofillScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupAutofillScreen.kt index 67e19e2f70..a0b106dcc5 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupAutofillScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupAutofillScreen.kt @@ -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() + } } } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupUnlockScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupUnlockScreen.kt index 4a111dfb22..665e159f0f 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupUnlockScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupUnlockScreen.kt @@ -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( diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt index b51362aded..37b88e6d60 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt @@ -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() + } } } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/welcome/WelcomeScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/welcome/WelcomeScreen.kt index a9638e34d5..2250a532af 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/welcome/WelcomeScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/welcome/WelcomeScreen.kt @@ -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, ) { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/ModifierExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/ModifierExtensions.kt index 92098c0b95..ccee4cab32 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/ModifierExtensions.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/ModifierExtensions.kt @@ -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() { 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. diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/model/WindowSize.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/model/WindowSize.kt new file mode 100644 index 0000000000..bc8859c165 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/model/WindowSize.kt @@ -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, +} diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/util/ConfigurationExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/util/ConfigurationExtensions.kt deleted file mode 100644 index d355526717..0000000000 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/util/ConfigurationExtensions.kt +++ /dev/null @@ -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 - } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/util/WindowAdaptiveInfoExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/util/WindowAdaptiveInfoExtensions.kt new file mode 100644 index 0000000000..98660739e2 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/util/WindowAdaptiveInfoExtensions.kt @@ -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 + } +} diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreen.kt index 84b22577f6..6627525b31 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorScreen.kt @@ -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.ScrollContent( onCoachMarkComplete: () -> Unit, modifier: Modifier = Modifier, ) { + val windowAdaptiveInfo = currentWindowAdaptiveInfo() LazyColumn( state = lazyListState, modifier = modifier @@ -461,7 +463,7 @@ private fun CoachMarkScope.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.ScrollContent( onActionClick = onShowNextCoachMark, ) }, - modifier = Modifier.standardHorizontalMargin(), + modifier = Modifier + .standardHorizontalMargin(windowAdaptiveInfo = windowAdaptiveInfo), ) { PasswordTypeContent( passwordTypeState = selectedType, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditItemContent.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditItemContent.kt index 257dc527e4..a6bae43935 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditItemContent.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditItemContent.kt @@ -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.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.VaultAddEditContent( vaultAddEditLoginItems( loginState = state.type, loginItemTypeHandlers = loginItemTypeHandlers, + windowAdaptiveInfo = windowAdaptiveInfo, onTotpSetupClick = { if (permissionsManager.checkPermission(Manifest.permission.CAMERA)) { loginItemTypeHandlers.onSetupTotpClick(true) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditLoginItems.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditLoginItems.kt index 3e1cc3d25c..33ac533fde 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditLoginItems.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditLoginItems.kt @@ -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, 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.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 = { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt index 12c3ec126c..101e8bf6b1 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/qrcodescan/QrCodeScanScreen.kt @@ -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() } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d16131d88f..c3ab8b2ea0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -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" }