diff --git a/README.md b/README.md index 353b4a103..5be22abd9 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ## Compatibility - **Minimum SDK**: 29 -- **Target SDK**: 34 +- **Target SDK**: 35 - **Device Types Supported**: Phone and Tablet - **Orientations Supported**: Portrait and Landscape 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 9d18975fa..3398db221 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 @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.rememberScrollState @@ -134,14 +133,13 @@ fun SetupAutoFillScreen( }, ) }, - ) { innerPadding -> + ) { SetupAutoFillContent( state = state, onAutofillServiceChanged = { handler.onAutofillServiceChanged(it) }, onContinueClick = handler.onContinueClick, onTurnOnLaterClick = handler.onTurnOnLaterClick, modifier = Modifier - .padding(innerPadding) .verticalScroll(rememberScrollState()) .fillMaxSize(), ) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupCompleteScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupCompleteScreen.kt index b45b83512..2d23678e7 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupCompleteScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/accountsetup/SetupCompleteScreen.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -62,11 +61,9 @@ fun SetupCompleteScreen( modifier = Modifier .fillMaxSize() .nestedScroll(scrollBehavior.nestedScrollConnection), - ) { innerPadding -> + ) { SetupCompleteContent( - modifier = Modifier - .padding(innerPadding) - .verticalScroll(rememberScrollState()), + modifier = Modifier.verticalScroll(rememberScrollState()), onContinue = setupCompleteAction, ) } 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 8348bb5e1..c3e748901 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 @@ -128,15 +128,13 @@ fun SetupUnlockScreen( }, ) }, - ) { innerPadding -> + ) { SetupUnlockScreenContent( state = state, showBiometricsPrompt = showBiometricsPrompt, handler = handler, biometricsManager = biometricsManager, - modifier = Modifier - .padding(paddingValues = innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/checkemail/CheckEmailScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/checkemail/CheckEmailScreen.kt index 8848b9ea2..6be4b6c75 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/checkemail/CheckEmailScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/checkemail/CheckEmailScreen.kt @@ -91,10 +91,9 @@ fun CheckEmailScreen( onNavigationIconClick = handler.onBackClick, ) }, - ) { innerPadding -> + ) { Column( modifier = Modifier - .padding(innerPadding) .imePadding() .fillMaxSize() .verticalScroll(rememberScrollState()), 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 102a162fa..1b6306f17 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 @@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -158,10 +157,9 @@ fun CompleteRegistrationScreen( }, ) }, - ) { innerPadding -> + ) { Column( modifier = Modifier - .padding(innerPadding) .imePadding() .fillMaxSize() .verticalScroll(rememberScrollState()), diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreen.kt index be2562f41..1b61b6b42 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreen.kt @@ -187,10 +187,9 @@ fun CreateAccountScreen( }, ) }, - ) { innerPadding -> + ) { Column( modifier = Modifier - .padding(innerPadding) .imePadding() .fillMaxSize() .verticalScroll(rememberScrollState()), diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnScreen.kt index 40042fc84..0007bcd42 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/enterprisesignon/EnterpriseSignOnScreen.kt @@ -126,15 +126,13 @@ fun EnterpriseSignOnScreen( }, ) }, - ) { innerPadding -> + ) { EnterpriseSignOnScreenContent( state = state, onOrgIdentifierInputChange = remember(viewModel) { { viewModel.trySendAction(EnterpriseSignOnAction.OrgIdentifierInputChange(it)) } }, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/environment/EnvironmentScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/environment/EnvironmentScreen.kt index 104324115..e627a6848 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/environment/EnvironmentScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/environment/EnvironmentScreen.kt @@ -98,10 +98,9 @@ fun EnvironmentScreen( }, ) }, - ) { innerPadding -> + ) { Column( - Modifier - .padding(innerPadding) + modifier = Modifier .fillMaxSize() .imePadding() .verticalScroll(rememberScrollState()), diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/expiredregistrationlink/ExpiredRegistrationLinkScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/expiredregistrationlink/ExpiredRegistrationLinkScreen.kt index f90d2a711..4ea319c75 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/expiredregistrationlink/ExpiredRegistrationLinkScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/expiredregistrationlink/ExpiredRegistrationLinkScreen.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api @@ -72,7 +71,7 @@ fun ExpiredRegistrationLinkScreen( ), ) }, - ) { innerPadding -> + ) { ExpiredRegistrationLinkContent( onNavigateToLogin = remember(viewModel) { { @@ -87,7 +86,6 @@ fun ExpiredRegistrationLinkScreen( } }, modifier = Modifier - .padding(innerPadding) .fillMaxSize() .verticalScroll(rememberScrollState()), ) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreen.kt index 62b34b203..7643107b5 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/landing/LandingScreen.kt @@ -148,7 +148,29 @@ fun LandingScreen( ) } }, - ) { innerPadding -> + overlay = { + BitwardenAccountSwitcher( + isVisible = isAccountMenuVisible, + accountSummaries = state.accountSummaries.toImmutableList(), + onSwitchAccountClick = remember(viewModel) { + { viewModel.trySendAction(LandingAction.SwitchAccountClick(it)) } + }, + onLockAccountClick = remember(viewModel) { + { viewModel.trySendAction(LandingAction.LockAccountClick(it)) } + }, + onLogoutAccountClick = remember(viewModel) { + { viewModel.trySendAction(LandingAction.LogoutAccountClick(it)) } + }, + onAddAccountClick = { + // Not available + }, + onDismissRequest = { isAccountMenuVisible = false }, + isAddAccountAvailable = false, + topAppBarScrollBehavior = scrollBehavior, + modifier = Modifier.fillMaxSize(), + ) + }, + ) { LandingScreenContent( state = state, isAppBarVisible = isAppBarVisible, @@ -167,32 +189,7 @@ fun LandingScreen( onCreateAccountClick = remember(viewModel) { { viewModel.trySendAction(LandingAction.CreateAccountClick) } }, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), - ) - - BitwardenAccountSwitcher( - isVisible = isAccountMenuVisible, - accountSummaries = state.accountSummaries.toImmutableList(), - onSwitchAccountClick = remember(viewModel) { - { viewModel.trySendAction(LandingAction.SwitchAccountClick(it)) } - }, - onLockAccountClick = remember(viewModel) { - { viewModel.trySendAction(LandingAction.LockAccountClick(it)) } - }, - onLogoutAccountClick = remember(viewModel) { - { viewModel.trySendAction(LandingAction.LogoutAccountClick(it)) } - }, - onAddAccountClick = { - // Not available - }, - onDismissRequest = { isAccountMenuVisible = false }, - isAddAccountAvailable = false, - topAppBarScrollBehavior = scrollBehavior, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt index 03faeeb49..f7c7dc443 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt @@ -145,7 +145,28 @@ fun LoginScreen( }, ) }, - ) { innerPadding -> + overlay = { + BitwardenAccountSwitcher( + isVisible = isAccountMenuVisible, + accountSummaries = state.accountSummaries.toImmutableList(), + onSwitchAccountClick = remember(viewModel) { + { viewModel.trySendAction(LoginAction.SwitchAccountClick(it)) } + }, + onLockAccountClick = remember(viewModel) { + { viewModel.trySendAction(LoginAction.LockAccountClick(it)) } + }, + onLogoutAccountClick = remember(viewModel) { + { viewModel.trySendAction(LoginAction.LogoutAccountClick(it)) } + }, + onAddAccountClick = remember(viewModel) { + { viewModel.trySendAction(LoginAction.AddAccountClick) } + }, + onDismissRequest = { isAccountMenuVisible = false }, + topAppBarScrollBehavior = scrollBehavior, + modifier = Modifier.fillMaxSize(), + ) + }, + ) { LoginScreenContent( state = state, onPasswordInputChanged = remember(viewModel) { @@ -169,31 +190,7 @@ fun LoginScreen( onNotYouButtonClick = remember(viewModel) { { viewModel.trySendAction(LoginAction.NotYouButtonClick) } }, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), - ) - - BitwardenAccountSwitcher( - isVisible = isAccountMenuVisible, - accountSummaries = state.accountSummaries.toImmutableList(), - onSwitchAccountClick = remember(viewModel) { - { viewModel.trySendAction(LoginAction.SwitchAccountClick(it)) } - }, - onLockAccountClick = remember(viewModel) { - { viewModel.trySendAction(LoginAction.LockAccountClick(it)) } - }, - onLogoutAccountClick = remember(viewModel) { - { viewModel.trySendAction(LoginAction.LogoutAccountClick(it)) } - }, - onAddAccountClick = remember(viewModel) { - { viewModel.trySendAction(LoginAction.AddAccountClick) } - }, - onDismissRequest = { isAccountMenuVisible = false }, - topAppBarScrollBehavior = scrollBehavior, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/loginwithdevice/LoginWithDeviceScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/loginwithdevice/LoginWithDeviceScreen.kt index 02f164179..87543ee10 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/loginwithdevice/LoginWithDeviceScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/loginwithdevice/LoginWithDeviceScreen.kt @@ -102,10 +102,7 @@ fun LoginWithDeviceScreen( }, ) }, - ) { paddingValues -> - val modifier = Modifier - .fillMaxSize() - .padding(paddingValues) + ) { when (val viewState = state.viewState) { is LoginWithDeviceState.ViewState.Content -> { LoginWithDeviceScreenContent( @@ -116,12 +113,12 @@ fun LoginWithDeviceScreen( onViewAllLogInOptionsClick = remember(viewModel) { { viewModel.trySendAction(LoginWithDeviceAction.ViewAllLogInOptionsClick) } }, - modifier = modifier, + modifier = Modifier.fillMaxSize(), ) } LoginWithDeviceState.ViewState.Loading -> BitwardenLoadingContent( - modifier = modifier, + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordgenerator/MasterPasswordGeneratorScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordgenerator/MasterPasswordGeneratorScreen.kt index 65e181247..45e2d8f7d 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordgenerator/MasterPasswordGeneratorScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordgenerator/MasterPasswordGeneratorScreen.kt @@ -98,12 +98,11 @@ fun MasterPasswordGeneratorScreen( snackbarHost = { BitwardenSnackbarHost(bitwardenHostState = snackbarHostState) }, - ) { innerPadding -> + ) { Column( modifier = Modifier .fillMaxSize() - .verticalScroll(rememberScrollState()) - .padding(innerPadding), + .verticalScroll(rememberScrollState()), ) { MasterPasswordGeneratorContent( generatedPassword = state.generatedPassword, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt index 45e718619..6b2befc44 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt @@ -80,12 +80,11 @@ fun MasterPasswordGuidanceScreen( }, ) }, - ) { innerPadding -> + ) { Column( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) - .padding(innerPadding) .standardHorizontalMargin(), ) { Column( diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordhint/MasterPasswordHintScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordhint/MasterPasswordHintScreen.kt index e53adee1a..1c72b7a01 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordhint/MasterPasswordHintScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordhint/MasterPasswordHintScreen.kt @@ -111,11 +111,9 @@ fun MasterPasswordHintScreen( }, ) }, - ) { innerPadding -> + ) { Column( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) { BitwardenTextField( modifier = Modifier diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/preventaccountlockout/PreventAccountLockoutScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/preventaccountlockout/PreventAccountLockoutScreen.kt index 5be5caadf..af4a3522f 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/preventaccountlockout/PreventAccountLockoutScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/preventaccountlockout/PreventAccountLockoutScreen.kt @@ -74,10 +74,9 @@ fun PreventAccountLockoutScreen( }, ) }, - ) { innerPadding -> + ) { Column( modifier = Modifier - .padding(innerPadding) .fillMaxWidth() .standardHorizontalMargin() .verticalScroll(rememberScrollState()), diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordScreen.kt index c9cee320f..62d656b79 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/removepassword/RemovePasswordScreen.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api @@ -65,7 +64,7 @@ fun RemovePasswordScreen( navigationIcon = null, ) }, - ) { innerPadding -> + ) { RemovePasswordScreenContent( state = state, onContinueClick = remember(viewModel) { @@ -74,9 +73,7 @@ fun RemovePasswordScreen( onInputChanged = remember(viewModel) { { viewModel.trySendAction(RemovePasswordAction.InputChanged(it)) } }, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/resetpassword/ResetPasswordScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/resetpassword/ResetPasswordScreen.kt index b500ea54b..c1caa5618 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/resetpassword/ResetPasswordScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/resetpassword/ResetPasswordScreen.kt @@ -121,7 +121,7 @@ fun ResetPasswordScreen( }, ) }, - ) { innerPadding -> + ) { ResetPasswordScreenContent( state = state, onCurrentPasswordInputChanged = remember(viewModel) { @@ -136,9 +136,7 @@ fun ResetPasswordScreen( onPasswordHintInputChanged = remember(viewModel) { { viewModel.trySendAction(ResetPasswordAction.PasswordHintInputChanged(it)) } }, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/setpassword/SetPasswordScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/setpassword/SetPasswordScreen.kt index bb48e1120..eecf0b875 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/setpassword/SetPasswordScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/setpassword/SetPasswordScreen.kt @@ -84,7 +84,7 @@ fun SetPasswordScreen( }, ) }, - ) { innerPadding -> + ) { SetPasswordScreenContent( state = state, onPasswordInputChanged = remember(viewModel) { @@ -97,7 +97,6 @@ fun SetPasswordScreen( { viewModel.trySendAction(SetPasswordAction.PasswordHintInputChanged(it)) } }, modifier = Modifier - .padding(innerPadding) .imePadding() .fillMaxSize(), ) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/startregistration/StartRegistrationScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/startregistration/StartRegistrationScreen.kt index 070cb86dd..4d1a1f45f 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/startregistration/StartRegistrationScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/startregistration/StartRegistrationScreen.kt @@ -177,10 +177,9 @@ fun StartRegistrationScreen( onNavigationIconClick = handler.onBackClick, ) }, - ) { innerPadding -> + ) { Column( modifier = Modifier - .padding(innerPadding) .imePadding() .fillMaxSize() .verticalScroll(rememberScrollState()), diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/trusteddevice/TrustedDeviceScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/trusteddevice/TrustedDeviceScreen.kt index dd8b6298b..45f71fb14 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/trusteddevice/TrustedDeviceScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/trusteddevice/TrustedDeviceScreen.kt @@ -114,10 +114,9 @@ private fun TrustedDeviceScaffold( ), ) }, - ) { innerPadding -> + ) { Column( modifier = Modifier - .padding(innerPadding) .fillMaxSize() .verticalScroll(rememberScrollState()), ) { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt index f8b086a64..457b38094 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt @@ -160,7 +160,7 @@ fun TwoFactorLoginScreen( }, ) }, - ) { innerPadding -> + ) { TwoFactorLoginScreenContent( state = state, onCodeInputChange = remember(viewModel) { @@ -175,9 +175,7 @@ fun TwoFactorLoginScreen( onResendEmailButtonClick = remember(viewModel) { { viewModel.trySendAction(TwoFactorLoginAction.ResendEmailClick) } }, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreen.kt index 555a0ce5f..d2fea85ba 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockScreen.kt @@ -2,7 +2,6 @@ package com.x8bit.bitwarden.ui.auth.feature.vaultunlock import android.widget.Toast import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -205,99 +204,7 @@ fun VaultUnlockScreen( }, ) }, - ) { innerPadding -> - Box { - Column( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize() - .verticalScroll(rememberScrollState()), - ) { - if (!state.hideInput) { - BitwardenPasswordField( - label = state.vaultUnlockType.unlockScreenInputLabel(), - value = state.input, - onValueChange = remember(viewModel) { - { viewModel.trySendAction(VaultUnlockAction.InputChanged(it)) } - }, - keyboardType = state.vaultUnlockType.unlockScreenKeyboardType, - showPasswordTestTag = state - .vaultUnlockType - .inputFieldVisibilityToggleTestTag, - modifier = Modifier - .testTag(state.vaultUnlockType.unlockScreenInputTestTag) - .padding(horizontal = 16.dp) - .fillMaxWidth(), - autoFocus = state.showKeyboard, - imeAction = ImeAction.Done, - keyboardActions = KeyboardActions( - onDone = remember(viewModel) { - { viewModel.trySendAction(VaultUnlockAction.UnlockClick) } - }, - ), - ) - Spacer(modifier = Modifier.height(24.dp)) - Text( - text = state.vaultUnlockType.unlockScreenMessage(), - style = BitwardenTheme.typography.bodyMedium, - color = BitwardenTheme.colorScheme.text.primary, - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), - ) - Spacer(modifier = Modifier.height(8.dp)) - } - Text( - text = stringResource( - id = R.string.logged_in_as_on, - state.email, - state.environmentUrl, - ), - style = BitwardenTheme.typography.bodyMedium, - color = BitwardenTheme.colorScheme.text.primary, - modifier = Modifier - .testTag("UserAndEnvironmentDataLabel") - .padding(horizontal = 16.dp) - .fillMaxWidth(), - ) - Spacer(modifier = Modifier.height(24.dp)) - if (state.showBiometricLogin && biometricsManager.isBiometricsSupported) { - BitwardenOutlinedButton( - label = stringResource(id = R.string.use_biometrics_to_unlock), - onClick = remember(viewModel) { - { viewModel.trySendAction(VaultUnlockAction.BiometricsUnlockClick) } - }, - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), - ) - Spacer(modifier = Modifier.height(12.dp)) - } else if (state.showBiometricInvalidatedMessage) { - Text( - text = stringResource(R.string.account_biometric_invalidated), - textAlign = TextAlign.Start, - style = BitwardenTheme.typography.bodyMedium, - color = BitwardenTheme.colorScheme.status.error, - modifier = Modifier.padding(horizontal = 16.dp), - ) - Spacer(modifier = Modifier.height(12.dp)) - } - if (!state.hideInput) { - BitwardenFilledButton( - label = stringResource(id = R.string.unlock), - onClick = remember(viewModel) { - { viewModel.trySendAction(VaultUnlockAction.UnlockClick) } - }, - isEnabled = state.input.isNotEmpty(), - modifier = Modifier - .testTag("UnlockVaultButton") - .padding(horizontal = 16.dp) - .fillMaxWidth(), - ) - } - Spacer(modifier = Modifier.navigationBarsPadding()) - } - + overlay = { BitwardenAccountSwitcher( isVisible = accountMenuVisible, accountSummaries = state.accountSummaries.toImmutableList(), @@ -315,10 +222,98 @@ fun VaultUnlockScreen( }, onDismissRequest = { accountMenuVisible = false }, topAppBarScrollBehavior = scrollBehavior, - modifier = Modifier - .fillMaxSize() - .padding(innerPadding), + modifier = Modifier.fillMaxSize(), ) + }, + ) { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()), + ) { + if (!state.hideInput) { + BitwardenPasswordField( + label = state.vaultUnlockType.unlockScreenInputLabel(), + value = state.input, + onValueChange = remember(viewModel) { + { viewModel.trySendAction(VaultUnlockAction.InputChanged(it)) } + }, + keyboardType = state.vaultUnlockType.unlockScreenKeyboardType, + showPasswordTestTag = state + .vaultUnlockType + .inputFieldVisibilityToggleTestTag, + modifier = Modifier + .testTag(state.vaultUnlockType.unlockScreenInputTestTag) + .padding(horizontal = 16.dp) + .fillMaxWidth(), + autoFocus = state.showKeyboard, + imeAction = ImeAction.Done, + keyboardActions = KeyboardActions( + onDone = remember(viewModel) { + { viewModel.trySendAction(VaultUnlockAction.UnlockClick) } + }, + ), + ) + Spacer(modifier = Modifier.height(24.dp)) + Text( + text = state.vaultUnlockType.unlockScreenMessage(), + style = BitwardenTheme.typography.bodyMedium, + color = BitwardenTheme.colorScheme.text.primary, + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + ) + Spacer(modifier = Modifier.height(8.dp)) + } + Text( + text = stringResource( + id = R.string.logged_in_as_on, + state.email, + state.environmentUrl, + ), + style = BitwardenTheme.typography.bodyMedium, + color = BitwardenTheme.colorScheme.text.primary, + modifier = Modifier + .testTag("UserAndEnvironmentDataLabel") + .padding(horizontal = 16.dp) + .fillMaxWidth(), + ) + Spacer(modifier = Modifier.height(24.dp)) + if (state.showBiometricLogin && biometricsManager.isBiometricsSupported) { + BitwardenOutlinedButton( + label = stringResource(id = R.string.use_biometrics_to_unlock), + onClick = remember(viewModel) { + { viewModel.trySendAction(VaultUnlockAction.BiometricsUnlockClick) } + }, + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + ) + Spacer(modifier = Modifier.height(12.dp)) + } else if (state.showBiometricInvalidatedMessage) { + Text( + text = stringResource(R.string.account_biometric_invalidated), + textAlign = TextAlign.Start, + style = BitwardenTheme.typography.bodyMedium, + color = BitwardenTheme.colorScheme.status.error, + modifier = Modifier.padding(horizontal = 16.dp), + ) + Spacer(modifier = Modifier.height(12.dp)) + } + if (!state.hideInput) { + BitwardenFilledButton( + label = stringResource(id = R.string.unlock), + onClick = remember(viewModel) { + { viewModel.trySendAction(VaultUnlockAction.UnlockClick) } + }, + isEnabled = state.input.isNotEmpty(), + modifier = Modifier + .testTag("UnlockVaultButton") + .padding(horizontal = 16.dp) + .fillMaxWidth(), + ) + } + Spacer(modifier = Modifier.navigationBarsPadding()) } } } 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 003fb7cf7..07079b53c 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 @@ -81,7 +81,7 @@ fun WelcomeScreen( modifier = Modifier.fillMaxSize(), containerColor = BitwardenTheme.colorScheme.background.secondary, contentColor = BitwardenTheme.colorScheme.text.secondary, - ) { innerPadding -> + ) { WelcomeScreenContent( state = state, pagerState = pagerState, @@ -97,9 +97,7 @@ fun WelcomeScreen( onLoginClick = remember(viewModel) { { viewModel.trySendAction(WelcomeAction.LoginClick) } }, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt index ce872bd13..8242552cc 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/account/BitwardenAccountSwitcher.kt @@ -14,11 +14,18 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.union import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.ExperimentalMaterial3Api @@ -107,9 +114,12 @@ fun BitwardenAccountSwitcher( onLogoutAccountClick: (AccountSummary) -> Unit, onAddAccountClick: () -> Unit, onDismissRequest: () -> Unit, - modifier: Modifier = Modifier, - isAddAccountAvailable: Boolean = true, topAppBarScrollBehavior: TopAppBarScrollBehavior, + modifier: Modifier = Modifier, + windowInsets: WindowInsets = WindowInsets.displayCutout + .union(WindowInsets.navigationBars) + .only(WindowInsetsSides.Horizontal), + isAddAccountAvailable: Boolean = true, ) { // Track the actual visibility (according to the internal transitions) so that we know when we // can safely show dialogs. @@ -190,6 +200,7 @@ fun BitwardenAccountSwitcher( isAddAccountAvailable = isAddAccountAvailable, topAppBarScrollBehavior = topAppBarScrollBehavior, currentAnimationState = { isVisibleActual = it }, + windowInsets = windowInsets, modifier = Modifier .fillMaxWidth(), ) @@ -208,9 +219,12 @@ private fun AnimatedAccountSwitcher( onSwitchAccountLongClick: (AccountSummary) -> Unit, onAddAccountClick: () -> Unit, isAddAccountAvailable: Boolean, - modifier: Modifier = Modifier, topAppBarScrollBehavior: TopAppBarScrollBehavior, currentAnimationState: (isVisible: Boolean) -> Unit, + modifier: Modifier = Modifier, + windowInsets: WindowInsets = WindowInsets.displayCutout + .union(WindowInsets.navigationBars) + .only(WindowInsetsSides.Horizontal), ) { val transition = updateTransition( targetState = isVisible, @@ -229,7 +243,8 @@ private fun AnimatedAccountSwitcher( // bottom padding. .padding(bottom = 24.dp) // Match the color of the switcher the different states of the app bar. - .scrolledContainerBackground(topAppBarScrollBehavior), + .scrolledContainerBackground(topAppBarScrollBehavior) + .windowInsetsPadding(windowInsets), ) { items(accountSummaries) { accountSummary -> AccountSummaryItem( diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenMediumTopAppBar.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenMediumTopAppBar.kt index dd6f4039f..c6190301a 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenMediumTopAppBar.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenMediumTopAppBar.kt @@ -1,6 +1,11 @@ package com.x8bit.bitwarden.ui.platform.components.appbar import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.displayCutout +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.union import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MediumTopAppBar import androidx.compose.material3.Text @@ -32,6 +37,7 @@ import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme * @param title The text to be displayed as the title of the app bar. * @param scrollBehavior Defines the scrolling behavior of the app bar. It controls how the app bar * behaves in conjunction with scrolling content. + * @param windowInsets The insets to be applied to this composable. * @param dividerStyle Determines how the bottom divider should be displayed. * @param actions A lambda containing the set of actions (usually icons or similar) to display * in the app bar's trailing side. This lambda extends [RowScope], allowing flexibility in @@ -43,10 +49,13 @@ fun BitwardenMediumTopAppBar( title: String, scrollBehavior: TopAppBarScrollBehavior, modifier: Modifier = Modifier, + windowInsets: WindowInsets = TopAppBarDefaults.windowInsets + .union(WindowInsets.displayCutout.only(WindowInsetsSides.Horizontal)), dividerStyle: TopAppBarDividerStyle = TopAppBarDividerStyle.ON_SCROLL, actions: @Composable RowScope.() -> Unit = {}, ) { TopAppBar( + windowInsets = windowInsets, colors = bitwardenTopAppBarColors(), scrollBehavior = scrollBehavior, expandedHeight = 56.dp, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenSearchTopAppBar.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenSearchTopAppBar.kt index 34ea1eab0..2300591e3 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenSearchTopAppBar.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenSearchTopAppBar.kt @@ -1,11 +1,17 @@ package com.x8bit.bitwarden.ui.platform.components.appbar +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.union import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -42,6 +48,8 @@ fun BitwardenSearchTopAppBar( scrollBehavior: TopAppBarScrollBehavior, navigationIcon: NavigationIcon?, modifier: Modifier = Modifier, + windowInsets: WindowInsets = TopAppBarDefaults.windowInsets + .union(WindowInsets.displayCutout.only(WindowInsetsSides.Horizontal)), autoFocus: Boolean = true, ) { val focusRequester = remember { FocusRequester() } @@ -49,6 +57,7 @@ fun BitwardenSearchTopAppBar( modifier = modifier .testTag(tag = "HeaderBarComponent") .bottomDivider(), + windowInsets = windowInsets, colors = bitwardenTopAppBarColors(), scrollBehavior = scrollBehavior, navigationIcon = { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenTopAppBar.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenTopAppBar.kt index 4291eee46..5fba3d52b 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenTopAppBar.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/appbar/BitwardenTopAppBar.kt @@ -1,6 +1,11 @@ package com.x8bit.bitwarden.ui.platform.components.appbar import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.displayCutout +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.union import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MediumTopAppBar import androidx.compose.material3.Text @@ -50,6 +55,8 @@ fun BitwardenTopAppBar( navigationIconContentDescription: String, onNavigationIconClick: () -> Unit, modifier: Modifier = Modifier, + windowInsets: WindowInsets = TopAppBarDefaults.windowInsets + .union(WindowInsets.displayCutout.only(WindowInsetsSides.Horizontal)), dividerStyle: TopAppBarDividerStyle = TopAppBarDividerStyle.ON_SCROLL, actions: @Composable RowScope.() -> Unit = { }, ) { @@ -62,6 +69,7 @@ fun BitwardenTopAppBar( onNavigationIconClick = onNavigationIconClick, ), modifier = modifier, + windowInsets = windowInsets, dividerStyle = dividerStyle, actions = actions, ) @@ -87,6 +95,8 @@ fun BitwardenTopAppBar( scrollBehavior: TopAppBarScrollBehavior, navigationIcon: NavigationIcon?, modifier: Modifier = Modifier, + windowInsets: WindowInsets = TopAppBarDefaults.windowInsets + .union(WindowInsets.displayCutout.only(WindowInsetsSides.Horizontal)), dividerStyle: TopAppBarDividerStyle = TopAppBarDividerStyle.ON_SCROLL, actions: @Composable RowScope.() -> Unit = {}, minimunHeight: Dp = 48.dp, @@ -129,6 +139,7 @@ fun BitwardenTopAppBar( if (titleTextHasOverflow) { MediumTopAppBar( + windowInsets = windowInsets, colors = bitwardenTopAppBarColors(), scrollBehavior = scrollBehavior, navigationIcon = navigationIconContent, @@ -149,6 +160,7 @@ fun BitwardenTopAppBar( ) } else { TopAppBar( + windowInsets = windowInsets, colors = bitwardenTopAppBarColors(), scrollBehavior = scrollBehavior, navigationIcon = navigationIconContent, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/bottomsheet/BitwardenModalBottomSheet.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/bottomsheet/BitwardenModalBottomSheet.kt index 85956def3..6a6bc2b18 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/bottomsheet/BitwardenModalBottomSheet.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/bottomsheet/BitwardenModalBottomSheet.kt @@ -1,6 +1,5 @@ package com.x8bit.bitwarden.ui.platform.components.bottomsheet -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.ExperimentalMaterial3Api @@ -45,10 +44,7 @@ fun BitwardenModalBottomSheet( modifier: Modifier = Modifier, showBottomSheet: Boolean = true, sheetState: SheetState = rememberModalBottomSheetState(), - sheetContent: @Composable ( - paddingValues: PaddingValues, - animatedOnDismiss: () -> Unit, - ) -> Unit, + sheetContent: @Composable (animatedOnDismiss: () -> Unit) -> Unit, ) { if (!showBottomSheet) return ModalBottomSheet( @@ -79,8 +75,8 @@ fun BitwardenModalBottomSheet( modifier = Modifier .nestedScroll(scrollBehavior.nestedScrollConnection) .fillMaxSize(), - ) { paddingValues -> - sheetContent(paddingValues, animatedOnDismiss) + ) { + sheetContent(animatedOnDismiss) } } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/fab/BitwardenFloatingActionButton.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/fab/BitwardenFloatingActionButton.kt index a4afa6c90..d83f319e1 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/fab/BitwardenFloatingActionButton.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/fab/BitwardenFloatingActionButton.kt @@ -1,5 +1,10 @@ package com.x8bit.bitwarden.ui.platform.components.fab +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.displayCutout +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.union +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.runtime.Composable @@ -14,6 +19,7 @@ import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme * @param painter The icon for the button. * @param contentDescription The content description for the button. * @param modifier The [Modifier] to be applied to the button. + * @param windowInsets The insets to be applied to this composable. */ @Composable fun BitwardenFloatingActionButton( @@ -21,13 +27,14 @@ fun BitwardenFloatingActionButton( painter: Painter, contentDescription: String, modifier: Modifier = Modifier, + windowInsets: WindowInsets = WindowInsets.displayCutout.union(WindowInsets.navigationBars), ) { FloatingActionButton( containerColor = BitwardenTheme.colorScheme.filledButton.background, contentColor = BitwardenTheme.colorScheme.filledButton.foreground, onClick = onClick, shape = BitwardenTheme.shapes.fab, - modifier = modifier, + modifier = modifier.windowInsetsPadding(insets = windowInsets), ) { Icon( painter = painter, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/scaffold/BitwardenScaffold.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/scaffold/BitwardenScaffold.kt index 3804d6653..0f72eb766 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/scaffold/BitwardenScaffold.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/scaffold/BitwardenScaffold.kt @@ -1,12 +1,14 @@ package com.x8bit.bitwarden.ui.platform.components.scaffold import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.exclude -import androidx.compose.foundation.layout.navigationBars -import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.displayCutout +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.union +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FabPosition import androidx.compose.material3.Scaffold @@ -22,17 +24,25 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTagsAsResourceId +import androidx.compose.ui.unit.dp import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme /** * Direct passthrough to [Scaffold] but contains a few specific override values. Everything is * still overridable if necessary. + * + * The [utilityBar] is a nonstandard [Composable] that is placed below the [topBar] and does not + * scroll. + * The [overlay] is a nonstandard [Composable] that is placed over top the `utilityBar` and + * `content`. */ @OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) @Composable fun BitwardenScaffold( modifier: Modifier = Modifier, topBar: @Composable () -> Unit = { }, + utilityBar: @Composable () -> Unit = { }, + overlay: @Composable () -> Unit = { }, bottomBar: @Composable () -> Unit = { }, snackbarHost: @Composable () -> Unit = { }, floatingActionButton: @Composable () -> Unit = { }, @@ -42,8 +52,9 @@ fun BitwardenScaffold( contentColor: Color = BitwardenTheme.colorScheme.text.primary, contentWindowInsets: WindowInsets = ScaffoldDefaults .contentWindowInsets - .exclude(WindowInsets.navigationBars), - content: @Composable (PaddingValues) -> Unit, + .union(WindowInsets.displayCutout) + .only(WindowInsetsSides.Horizontal), + content: @Composable () -> Unit, ) { Scaffold( modifier = Modifier @@ -52,36 +63,38 @@ fun BitwardenScaffold( topBar = topBar, bottomBar = bottomBar, snackbarHost = snackbarHost, - floatingActionButton = { - Box(modifier = Modifier.navigationBarsPadding()) { - floatingActionButton() - } - }, + floatingActionButton = floatingActionButton, floatingActionButtonPosition = floatingActionButtonPosition, containerColor = containerColor, contentColor = contentColor, - contentWindowInsets = contentWindowInsets, + contentWindowInsets = WindowInsets(0.dp), content = { paddingValues -> - val internalPullToRefreshState = rememberPullToRefreshState() - Box( - modifier = Modifier.pullToRefresh( - state = internalPullToRefreshState, - isRefreshing = pullToRefreshState.isRefreshing, - onRefresh = pullToRefreshState.onRefresh, - enabled = pullToRefreshState.isEnabled, - ), - ) { - content(paddingValues) - - PullToRefreshDefaults.Indicator( + Column(modifier = Modifier.padding(paddingValues = paddingValues)) { + utilityBar() + val internalPullToRefreshState = rememberPullToRefreshState() + Box( modifier = Modifier - .padding(paddingValues) - .align(Alignment.TopCenter), - isRefreshing = pullToRefreshState.isRefreshing, - state = internalPullToRefreshState, - containerColor = BitwardenTheme.colorScheme.background.secondary, - color = BitwardenTheme.colorScheme.icon.secondary, - ) + .windowInsetsPadding(insets = contentWindowInsets) + .pullToRefresh( + state = internalPullToRefreshState, + isRefreshing = pullToRefreshState.isRefreshing, + onRefresh = pullToRefreshState.onRefresh, + enabled = pullToRefreshState.isEnabled, + ), + ) { + content() + + PullToRefreshDefaults.Indicator( + modifier = Modifier.align(Alignment.TopCenter), + isRefreshing = pullToRefreshState.isRefreshing, + state = internalPullToRefreshState, + containerColor = BitwardenTheme.colorScheme.background.secondary, + color = BitwardenTheme.colorScheme.icon.secondary, + ) + } + } + Box(modifier = Modifier.padding(paddingValues = paddingValues)) { + overlay() } }, ) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/segment/BitwardenSegmentedButton.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/segment/BitwardenSegmentedButton.kt index 3dad060ba..59874ac36 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/segment/BitwardenSegmentedButton.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/segment/BitwardenSegmentedButton.kt @@ -3,8 +3,15 @@ package com.x8bit.bitwarden.ui.platform.components.segment import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.union +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.SegmentedButton import androidx.compose.material3.SingleChoiceSegmentedButtonRow import androidx.compose.material3.Text @@ -23,17 +30,22 @@ import kotlinx.collections.immutable.ImmutableList * * @param options List of options to display. * @param modifier Modifier. + * @param windowInsets The insets to be applied to this composable. */ @Composable fun BitwardenSegmentedButton( options: ImmutableList, modifier: Modifier = Modifier, + windowInsets: WindowInsets = WindowInsets.displayCutout + .union(WindowInsets.navigationBars) + .only(WindowInsetsSides.Horizontal), ) { if (options.isEmpty()) return Box( modifier = modifier .background(color = BitwardenTheme.colorScheme.background.secondary) - .padding(top = 4.dp, bottom = 8.dp, start = 16.dp, end = 16.dp), + .padding(top = 4.dp, bottom = 8.dp, start = 16.dp, end = 16.dp) + .windowInsetsPadding(insets = windowInsets), ) { SingleChoiceSegmentedButtonRow( modifier = Modifier diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/snackbar/BitwardenSnackbarHost.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/snackbar/BitwardenSnackbarHost.kt index ada958dd6..5b5e5fc75 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/snackbar/BitwardenSnackbarHost.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/snackbar/BitwardenSnackbarHost.kt @@ -1,5 +1,10 @@ package com.x8bit.bitwarden.ui.platform.components.snackbar +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.displayCutout +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.union +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.SnackbarHost import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -9,15 +14,17 @@ import androidx.compose.ui.Modifier * * @param bitwardenHostState The state of this snackbar. * @param modifier The [Modifier] to be applied to the [SnackbarHost]. + * @param windowInsets The insets to be applied to this composable. */ @Composable fun BitwardenSnackbarHost( bitwardenHostState: BitwardenSnackbarHostState, modifier: Modifier = Modifier, + windowInsets: WindowInsets = WindowInsets.displayCutout.union(WindowInsets.navigationBars), ) { SnackbarHost( hostState = bitwardenHostState.snackbarHostState, - modifier = modifier, + modifier = modifier.windowInsetsPadding(insets = windowInsets), ) { snackbarData -> val message = snackbarData.visuals.message val currentCustomSnackbarData = bitwardenHostState.currentSnackbarData diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuScreen.kt index be613928e..29e7d8d93 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/debugmenu/DebugMenuScreen.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api @@ -74,11 +73,9 @@ fun DebugMenuScreen( ), ) }, - ) { innerPadding -> + ) { Column( - modifier = Modifier - .verticalScroll(rememberScrollState()) - .padding(innerPadding), + modifier = Modifier.verticalScroll(rememberScrollState()), ) { Spacer(modifier = Modifier.height(16.dp)) FeatureFlagContent( diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/search/SearchScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/search/SearchScreen.kt index 42bffa0d7..37194d61a 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/search/SearchScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/search/SearchScreen.kt @@ -1,7 +1,6 @@ package com.x8bit.bitwarden.ui.platform.feature.search import android.widget.Toast -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.imePadding @@ -91,14 +90,7 @@ fun SearchScreen( ), ) }, - modifier = Modifier - .nestedScroll(scrollBehavior.nestedScrollConnection), - ) { innerPadding -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(innerPadding), - ) { + utilityBar = { val vaultFilterData = state.vaultFilterData if (state.viewState.hasVaultFilter && vaultFilterData != null) { VaultFilter( @@ -116,32 +108,39 @@ fun SearchScreen( .fillMaxWidth(), ) } + }, + modifier = Modifier + .nestedScroll(scrollBehavior.nestedScrollConnection), + ) { + when (val viewState = state.viewState) { + is SearchState.ViewState.Content -> SearchContent( + viewState = viewState, + searchHandlers = searchHandlers, + searchType = state.searchType, + modifier = Modifier + .fillMaxSize() + .imePadding(), + ) - val innerModifier = Modifier - .fillMaxSize() - .imePadding() - when (val viewState = state.viewState) { - is SearchState.ViewState.Content -> SearchContent( - viewState = viewState, - searchHandlers = searchHandlers, - searchType = state.searchType, - modifier = innerModifier, - ) + is SearchState.ViewState.Empty -> SearchEmptyContent( + viewState = viewState, + modifier = Modifier + .fillMaxSize() + .imePadding(), + ) - is SearchState.ViewState.Empty -> SearchEmptyContent( - viewState = viewState, - modifier = innerModifier, - ) + is SearchState.ViewState.Error -> BitwardenErrorContent( + message = viewState.message(), + modifier = Modifier + .fillMaxSize() + .imePadding(), + ) - is SearchState.ViewState.Error -> BitwardenErrorContent( - message = viewState.message(), - modifier = innerModifier, - ) - - SearchState.ViewState.Loading -> BitwardenLoadingContent( - modifier = innerModifier, - ) - } + SearchState.ViewState.Loading -> BitwardenLoadingContent( + modifier = Modifier + .fillMaxSize() + .imePadding(), + ) } } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsScreen.kt index e3238ff55..b21c51e38 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/SettingsScreen.kt @@ -80,10 +80,9 @@ fun SettingsScreen( ) }, modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), - ) { innerPadding -> + ) { Column( modifier = Modifier - .padding(innerPadding) .fillMaxSize() .verticalScroll(state = rememberScrollState()), ) { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt index 45448d57d..3de12b656 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt @@ -111,12 +111,10 @@ fun AboutScreen( }, ) }, - ) { innerPadding -> + ) { ContentColumn( state = state, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), onHelpCenterClick = remember(viewModel) { { viewModel.trySendAction(AboutAction.HelpCenterClick) } }, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreen.kt index 2eb2733c6..56f89d749 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreen.kt @@ -174,10 +174,9 @@ fun AccountSecurityScreen( }, ) }, - ) { innerPadding -> + ) { Column( modifier = Modifier - .padding(innerPadding) .fillMaxSize() .verticalScroll(rememberScrollState()), ) { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountScreen.kt index 3fec7d5eb..d2be0f9d0 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountScreen.kt @@ -118,12 +118,11 @@ fun DeleteAccountScreen( }, ) }, - ) { innerPadding -> + ) { Column( modifier = Modifier .imePadding() .fillMaxSize() - .padding(innerPadding) .verticalScroll(rememberScrollState()), ) { Spacer(modifier = Modifier.height(8.dp)) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccountconfirmation/DeleteAccountConfirmationScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccountconfirmation/DeleteAccountConfirmationScreen.kt index 3f6c8f82f..d6d28598e 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccountconfirmation/DeleteAccountConfirmationScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccountconfirmation/DeleteAccountConfirmationScreen.kt @@ -218,13 +218,12 @@ private fun DeleteAccountConfirmationScaffold( onNavigationIconClick = onCloseClick, ) }, - ) { innerPadding -> + ) { DeleteAccountConfirmationContent( state = state, onDeleteAccountClick = onDeleteAccountClick, onResendCodeClick = onResendCodeClick, onVerificationCodeTextChange = onVerificationCodeTextChange, - modifier = Modifier.padding(innerPadding), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalScreen.kt index 4eecfc59a..5e4d1a6ba 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalScreen.kt @@ -104,7 +104,7 @@ fun LoginApprovalScreen( }, ) }, - ) { innerPadding -> + ) { when (val viewState = state.viewState) { is LoginApprovalState.ViewState.Content -> { LoginApprovalContent( @@ -115,26 +115,20 @@ fun LoginApprovalScreen( onDeclineLoginClick = remember(viewModel) { { viewModel.trySendAction(LoginApprovalAction.DeclineRequestClick) } }, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } is LoginApprovalState.ViewState.Error -> { BitwardenErrorContent( message = stringResource(id = R.string.generic_error_message), - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } is LoginApprovalState.ViewState.Loading -> { BitwardenLoadingContent( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/pendingrequests/PendingRequestsScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/pendingrequests/PendingRequestsScreen.kt index 9bea08324..28b7d7e10 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/pendingrequests/PendingRequestsScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/pendingrequests/PendingRequestsScreen.kt @@ -125,9 +125,8 @@ fun PendingRequestsScreen( }, sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), modifier = Modifier.statusBarsPadding(), - ) { paddingValues, animatedOnDismiss -> + ) { animatedOnDismiss -> PendingRequestsBottomSheetContent( - modifier = Modifier.padding(paddingValues), permissionsManager = permissionsManager, onDismiss = animatedOnDismiss, ) @@ -150,13 +149,11 @@ fun PendingRequestsScreen( ) }, pullToRefreshState = pullToRefreshState, - ) { innerPadding -> + ) { when (val viewState = state.viewState) { is PendingRequestsState.ViewState.Content -> { PendingRequestsContent( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), state = viewState, onDeclineAllRequestsConfirm = remember(viewModel) { { @@ -176,22 +173,16 @@ fun PendingRequestsScreen( } is PendingRequestsState.ViewState.Empty -> PendingRequestsEmpty( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) PendingRequestsState.ViewState.Error -> BitwardenErrorContent( message = stringResource(R.string.generic_error_message), - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) PendingRequestsState.ViewState.Loading -> BitwardenLoadingContent( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt index 224786fc1..6ca4ed614 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt @@ -73,10 +73,9 @@ fun AppearanceScreen( }, ) }, - ) { innerPadding -> + ) { Column( - Modifier - .padding(innerPadding) + modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()), ) { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt index 1f657333c..be7c5938c 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/AutoFillScreen.kt @@ -126,10 +126,9 @@ fun AutoFillScreen( }, ) }, - ) { innerPadding -> + ) { Column( - Modifier - .padding(innerPadding) + modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()), ) { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreen.kt index 5be5df8fc..2b7e76718 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/autofill/blockautofill/BlockAutoFillScreen.kt @@ -141,11 +141,9 @@ fun BlockAutoFillScreen( ) } }, - ) { innerPadding -> + ) { LazyColumn( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) { when (val viewState = state.viewState) { is BlockAutoFillState.ViewState.Content -> { @@ -191,9 +189,7 @@ fun BlockAutoFillScreen( addItemClickAction = remember(viewModel) { { viewModel.trySendAction(BlockAutoFillAction.AddUriClick) } }, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/exportvault/ExportVaultScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/exportvault/ExportVaultScreen.kt index e7f2df461..39936431b 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/exportvault/ExportVaultScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/exportvault/ExportVaultScreen.kt @@ -160,7 +160,7 @@ fun ExportVaultScreen( }, ) }, - ) { innerPadding -> + ) { ExportVaultScreenContent( state = state, onConfirmFilePasswordInputChanged = remember(viewModel) { @@ -179,9 +179,7 @@ fun ExportVaultScreen( { viewModel.trySendAction(ExportVaultAction.SendCodeClick) } }, onExportVaultClick = { shouldShowConfirmationDialog = true }, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/FoldersScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/FoldersScreen.kt index d8ea2423e..867df5b3f 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/FoldersScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/FoldersScreen.kt @@ -98,7 +98,7 @@ fun FoldersScreen( .navigationBarsPadding(), ) }, - ) { innerPadding -> + ) { when (val viewState = state.value.viewState) { is FoldersState.ViewState.Content -> { FoldersContent( @@ -106,26 +106,20 @@ fun FoldersScreen( onItemClick = remember(viewModel) { { viewModel.trySendAction(FoldersAction.FolderClick(it)) } }, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } is FoldersState.ViewState.Error -> { BitwardenErrorContent( message = viewState.message(), - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } is FoldersState.ViewState.Loading -> { BitwardenLoadingContent( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/addedit/FolderAddEditScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/addedit/FolderAddEditScreen.kt index e8428ec03..fd50478df 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/addedit/FolderAddEditScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/folders/addedit/FolderAddEditScreen.kt @@ -124,13 +124,11 @@ fun FolderAddEditScreen( }, ) }, - ) { innerPadding -> + ) { when (val viewState = state.viewState) { is FolderAddEditState.ViewState.Content -> { Column( - Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) { BitwardenTextField( label = stringResource(id = R.string.name), @@ -148,17 +146,13 @@ fun FolderAddEditScreen( is FolderAddEditState.ViewState.Error -> { BitwardenErrorContent( message = viewState.message(), - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } is FolderAddEditState.ViewState.Loading -> { BitwardenLoadingContent( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt index 20df6aad9..7c6fd068b 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt @@ -93,10 +93,9 @@ fun OtherScreen( }, ) }, - ) { innerPadding -> + ) { Column( - Modifier - .padding(innerPadding) + modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()), ) { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreen.kt index a8e91c748..7a5b4a524 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/vault/VaultSettingsScreen.kt @@ -100,10 +100,9 @@ fun VaultSettingsScreen( bitwardenHostState = snackbarHostState, ) }, - ) { innerPadding -> + ) { Column( - Modifier - .padding(innerPadding) + modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()), ) { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreen.kt index b0c011c5e..5acc57ecd 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlockednavbar/VaultUnlockedNavBarScreen.kt @@ -2,16 +2,14 @@ package com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.consumeWindowInsets -import androidx.compose.foundation.layout.exclude import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.ime import androidx.compose.foundation.layout.navigationBars -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.only import androidx.compose.material3.BottomAppBar -import androidx.compose.material3.ScaffoldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf @@ -21,6 +19,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.testTag +import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavBackStackEntry @@ -35,7 +34,6 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navOptions import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect -import com.x8bit.bitwarden.ui.platform.base.util.max import com.x8bit.bitwarden.ui.platform.base.util.toDp import com.x8bit.bitwarden.ui.platform.components.navigation.BitwardenNavigationBarItem import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold @@ -177,10 +175,9 @@ private fun VaultUnlockedNavBarScaffold( var shouldDimNavBar by remember { mutableStateOf(false) } // This scaffold will host screens that contain top bars while not hosting one itself. - // We need to ignore the status bar insets here and let the content screens handle - // it themselves. + // We need to ignore the all insets here and let the content screens handle it themselves. BitwardenScaffold( - contentWindowInsets = ScaffoldDefaults.contentWindowInsets.exclude(WindowInsets.statusBars), + contentWindowInsets = WindowInsets(0.dp), bottomBar = { Box { var appBarHeightPx by remember { mutableIntStateOf(0) } @@ -208,17 +205,16 @@ private fun VaultUnlockedNavBarScaffold( ) } }, - ) { innerPadding -> + ) { // Because this Scaffold has a bottom navigation bar, the NavHost will: - // - consume the navigation bar insets. + // - consume the vertical navigation bar insets. // - consume the IME insets. NavHost( navController = navController, startDestination = VAULT_GRAPH_ROUTE, modifier = Modifier - .consumeWindowInsets(WindowInsets.navigationBars) - .consumeWindowInsets(WindowInsets.ime) - .padding(innerPadding.max(WindowInsets.ime)), + .consumeWindowInsets(WindowInsets.navigationBars.only(WindowInsetsSides.Vertical)) + .consumeWindowInsets(WindowInsets.ime), enterTransition = RootTransitionProviders.Enter.fadeIn, exitTransition = RootTransitionProviders.Exit.fadeOut, popEnterTransition = RootTransitionProviders.Enter.fadeIn, 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 84c1ea694..6b67f6f81 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 @@ -189,12 +189,7 @@ fun GeneratorScreen( } } }, - snackbarHost = { - BitwardenSnackbarHost(bitwardenHostState = snackbarHostState) - }, - modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), - ) { innerPadding -> - Column(modifier = Modifier.padding(innerPadding)) { + utilityBar = { MainStateOptionsItem( selectedType = state.selectedType, passcodePolicyOverride = state.passcodePolicyOverride, @@ -203,20 +198,25 @@ fun GeneratorScreen( modifier = Modifier .scrolledContainerBottomDivider(topAppBarScrollBehavior = scrollBehavior), ) - ScrollContent( - state = state, - onRegenerateClick = onRegenerateClick, - onCopyClick = onCopyClick, - onUsernameSubStateOptionClicked = onUsernameOptionClicked, - passwordHandlers = passwordHandlers, - passphraseHandlers = passphraseHandlers, - usernameTypeHandlers = usernameTypeHandlers, - forwardedEmailAliasHandlers = forwardedEmailAliasHandlers, - plusAddressedEmailHandlers = plusAddressedEmailHandlers, - catchAllEmailHandlers = catchAllEmailHandlers, - randomWordHandlers = randomWordHandlers, - ) - } + }, + snackbarHost = { + BitwardenSnackbarHost(bitwardenHostState = snackbarHostState) + }, + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), + ) { + ScrollContent( + state = state, + onRegenerateClick = onRegenerateClick, + onCopyClick = onCopyClick, + onUsernameSubStateOptionClicked = onUsernameOptionClicked, + passwordHandlers = passwordHandlers, + passphraseHandlers = passphraseHandlers, + usernameTypeHandlers = usernameTypeHandlers, + forwardedEmailAliasHandlers = forwardedEmailAliasHandlers, + plusAddressedEmailHandlers = plusAddressedEmailHandlers, + catchAllEmailHandlers = catchAllEmailHandlers, + randomWordHandlers = randomWordHandlers, + ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/passwordhistory/PasswordHistoryScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/passwordhistory/PasswordHistoryScreen.kt index 9bb0b84fe..149639760 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/passwordhistory/PasswordHistoryScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/passwordhistory/PasswordHistoryScreen.kt @@ -97,30 +97,24 @@ fun PasswordHistoryScreen( }, ) }, - content = { innerPadding -> + content = { when (val viewState = state.viewState) { is PasswordHistoryState.ViewState.Loading -> { PasswordHistoryLoading( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } is PasswordHistoryState.ViewState.Error -> { PasswordHistoryError( state = viewState, - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } is PasswordHistoryState.ViewState.Empty -> { PasswordHistoryEmpty( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } @@ -129,8 +123,7 @@ fun PasswordHistoryScreen( state = viewState, modifier = Modifier .fillMaxSize() - .imePadding() - .padding(innerPadding), + .imePadding(), onPasswordCopyClick = { password -> viewModel.trySendAction( PasswordHistoryAction.PasswordCopyClick(password), diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt index 2502e46ad..df6027502 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt @@ -6,7 +6,6 @@ import androidx.compose.animation.scaleIn import androidx.compose.animation.scaleOut import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState @@ -161,11 +160,10 @@ fun SendScreen( } }, pullToRefreshState = pullToRefreshState, - ) { padding -> + ) { val modifier = Modifier .imePadding() .fillMaxSize() - .padding(padding) when (val viewState = state.viewState) { is SendState.ViewState.Content -> SendContent( policyDisablesSend = state.policyDisablesSend, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendContent.kt b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendContent.kt index 5835e29bb..add9a98ad 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendContent.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendContent.kt @@ -21,7 +21,6 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -35,22 +34,18 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp import com.x8bit.bitwarden.R -import com.x8bit.bitwarden.ui.platform.base.util.scrolledContainerBottomDivider import com.x8bit.bitwarden.ui.platform.components.button.BitwardenOutlinedButton import com.x8bit.bitwarden.ui.platform.components.button.BitwardenTextButton import com.x8bit.bitwarden.ui.platform.components.card.BitwardenInfoCalloutCard import com.x8bit.bitwarden.ui.platform.components.field.BitwardenPasswordField import com.x8bit.bitwarden.ui.platform.components.field.BitwardenTextField import com.x8bit.bitwarden.ui.platform.components.header.BitwardenListHeaderText -import com.x8bit.bitwarden.ui.platform.components.segment.BitwardenSegmentedButton -import com.x8bit.bitwarden.ui.platform.components.segment.SegmentedButtonState import com.x8bit.bitwarden.ui.platform.components.stepper.BitwardenStepper import com.x8bit.bitwarden.ui.platform.components.toggle.BitwardenSwitch import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter import com.x8bit.bitwarden.ui.platform.manager.permissions.PermissionsManager import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme import com.x8bit.bitwarden.ui.tools.feature.send.addsend.handlers.AddSendHandlers -import kotlinx.collections.immutable.persistentListOf /** * Content view for the [AddSendScreen]. @@ -60,7 +55,6 @@ import kotlinx.collections.immutable.persistentListOf @Composable fun AddSendContent( state: AddSendState.ViewState.Content, - scrollBehavior: TopAppBarScrollBehavior, policyDisablesSend: Boolean, policySendOptionsInEffect: Boolean, isAddMode: Boolean, @@ -72,201 +66,177 @@ fun AddSendContent( val chooseFileCameraPermissionLauncher = permissionsManager.getLauncher { isGranted -> addSendHandlers.onChooseFileClick(isGranted) } - Column(modifier = modifier) { - if (isAddMode && !isShared) { - BitwardenSegmentedButton( + Column( + modifier = modifier.verticalScroll(rememberScrollState()), + ) { + if (policyDisablesSend) { + Spacer(modifier = Modifier.height(8.dp)) + BitwardenInfoCalloutCard( + text = stringResource(id = R.string.send_disabled_warning), modifier = Modifier - .scrolledContainerBottomDivider(topAppBarScrollBehavior = scrollBehavior) - .fillMaxWidth(), - options = persistentListOf( - SegmentedButtonState( - text = stringResource(id = R.string.file), - onClick = addSendHandlers.onFileTypeSelect, - isChecked = state.isFileType, - testTag = "SendFileButton", - ), - SegmentedButtonState( - text = stringResource(id = R.string.text), - onClick = addSendHandlers.onTextTypeSelect, - isChecked = state.isTextType, - testTag = "SendTextButton", - ), - ), + .padding(horizontal = 16.dp) + .fillMaxWidth() + .testTag("SendPolicyInEffectLabel"), ) + Spacer(modifier = Modifier.height(16.dp)) } - Column( - modifier = Modifier.verticalScroll(rememberScrollState()), - ) { - if (policyDisablesSend) { - Spacer(modifier = Modifier.height(8.dp)) - BitwardenInfoCalloutCard( - text = stringResource(id = R.string.send_disabled_warning), - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .testTag("SendPolicyInEffectLabel"), - ) - Spacer(modifier = Modifier.height(16.dp)) - } - - if (policySendOptionsInEffect) { - BitwardenInfoCalloutCard( - text = stringResource(id = R.string.send_options_policy_in_effect), - modifier = Modifier - .testTag(tag = "SendPolicyInEffectLabel") - .padding(horizontal = 16.dp) - .fillMaxWidth(), - ) - - Spacer(modifier = Modifier.height(16.dp)) - } - - BitwardenTextField( + if (policySendOptionsInEffect) { + BitwardenInfoCalloutCard( + text = stringResource(id = R.string.send_options_policy_in_effect), modifier = Modifier - .testTag(tag = "SendNameEntry") - .fillMaxWidth() - .padding(horizontal = 16.dp), - label = stringResource(id = R.string.name), - hint = stringResource(id = R.string.name_info), - readOnly = policyDisablesSend, - value = state.common.name, - onValueChange = addSendHandlers.onNamChange, + .testTag(tag = "SendPolicyInEffectLabel") + .padding(horizontal = 16.dp) + .fillMaxWidth(), ) - Spacer(modifier = Modifier.height(8.dp)) - when (val type = state.selectedType) { - is AddSendState.ViewState.Content.SendType.File -> { - BitwardenListHeaderText( - label = stringResource(id = R.string.file), + Spacer(modifier = Modifier.height(16.dp)) + } + + BitwardenTextField( + modifier = Modifier + .testTag(tag = "SendNameEntry") + .fillMaxWidth() + .padding(horizontal = 16.dp), + label = stringResource(id = R.string.name), + hint = stringResource(id = R.string.name_info), + readOnly = policyDisablesSend, + value = state.common.name, + onValueChange = addSendHandlers.onNamChange, + ) + + Spacer(modifier = Modifier.height(8.dp)) + when (val type = state.selectedType) { + is AddSendState.ViewState.Content.SendType.File -> { + BitwardenListHeaderText( + label = stringResource(id = R.string.file), + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + ) + Spacer(modifier = Modifier.height(16.dp)) + if (isShared) { + Text( + text = type.name.orEmpty(), + color = BitwardenTheme.colorScheme.text.primary, + style = BitwardenTheme.typography.bodyMedium, modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp), ) + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = stringResource(id = R.string.max_file_size), + color = BitwardenTheme.colorScheme.text.secondary, + style = BitwardenTheme.typography.bodySmall, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + ) + } else if (isAddMode) { + Text( + modifier = Modifier + .testTag(tag = "SendCurrentFileNameLabel") + .align(Alignment.CenterHorizontally), + text = type.name ?: stringResource(id = R.string.no_file_chosen), + color = BitwardenTheme.colorScheme.text.secondary, + style = BitwardenTheme.typography.bodySmall, + ) + Spacer(modifier = Modifier.height(8.dp)) + BitwardenOutlinedButton( + label = stringResource(id = R.string.choose_file), + onClick = { + @Suppress("MaxLineLength") + if (permissionsManager.checkPermission(Manifest.permission.CAMERA)) { + addSendHandlers.onChooseFileClick(true) + } else { + chooseFileCameraPermissionLauncher.launch( + Manifest.permission.CAMERA, + ) + } + }, + modifier = Modifier + .testTag(tag = "SendChooseFileButton") + .fillMaxWidth() + .padding(horizontal = 16.dp), + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = stringResource(id = R.string.max_file_size), + color = BitwardenTheme.colorScheme.text.secondary, + style = BitwardenTheme.typography.bodySmall, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 32.dp), + ) Spacer(modifier = Modifier.height(16.dp)) - if (isShared) { + Text( + text = stringResource(id = R.string.type_file_info), + color = BitwardenTheme.colorScheme.text.secondary, + style = BitwardenTheme.typography.bodySmall, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + ) + } else { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + ) { Text( text = type.name.orEmpty(), color = BitwardenTheme.colorScheme.text.primary, + style = BitwardenTheme.typography.bodyLarge, + modifier = Modifier.weight(1f), + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = type.displaySize.orEmpty(), + color = BitwardenTheme.colorScheme.text.primary, style = BitwardenTheme.typography.bodyMedium, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), ) - Spacer(modifier = Modifier.height(8.dp)) - Text( - text = stringResource(id = R.string.max_file_size), - color = BitwardenTheme.colorScheme.text.secondary, - style = BitwardenTheme.typography.bodySmall, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - ) - } else if (isAddMode) { - Text( - modifier = Modifier - .testTag(tag = "SendCurrentFileNameLabel") - .align(Alignment.CenterHorizontally), - text = type.name ?: stringResource(id = R.string.no_file_chosen), - color = BitwardenTheme.colorScheme.text.secondary, - style = BitwardenTheme.typography.bodySmall, - ) - Spacer(modifier = Modifier.height(8.dp)) - BitwardenOutlinedButton( - label = stringResource(id = R.string.choose_file), - onClick = { - @Suppress("MaxLineLength") - if (permissionsManager.checkPermission(Manifest.permission.CAMERA)) { - addSendHandlers.onChooseFileClick(true) - } else { - chooseFileCameraPermissionLauncher.launch( - Manifest.permission.CAMERA, - ) - } - }, - modifier = Modifier - .testTag(tag = "SendChooseFileButton") - .fillMaxWidth() - .padding(horizontal = 16.dp), - ) - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = stringResource(id = R.string.max_file_size), - color = BitwardenTheme.colorScheme.text.secondary, - style = BitwardenTheme.typography.bodySmall, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 32.dp), - ) - Spacer(modifier = Modifier.height(16.dp)) - Text( - text = stringResource(id = R.string.type_file_info), - color = BitwardenTheme.colorScheme.text.secondary, - style = BitwardenTheme.typography.bodySmall, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - ) - } else { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - ) { - Text( - text = type.name.orEmpty(), - color = BitwardenTheme.colorScheme.text.primary, - style = BitwardenTheme.typography.bodyLarge, - modifier = Modifier.weight(1f), - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = type.displaySize.orEmpty(), - color = BitwardenTheme.colorScheme.text.primary, - style = BitwardenTheme.typography.bodyMedium, - ) - } } } - - is AddSendState.ViewState.Content.SendType.Text -> { - BitwardenTextField( - modifier = Modifier - .testTag(tag = "SendTextContentEntry") - .fillMaxWidth() - .padding(horizontal = 16.dp), - label = stringResource(id = R.string.text), - hint = stringResource(id = R.string.type_text_info), - readOnly = policyDisablesSend, - value = type.input, - singleLine = false, - onValueChange = addSendHandlers.onTextChange, - ) - Spacer(modifier = Modifier.height(16.dp)) - BitwardenSwitch( - modifier = Modifier - .testTag(tag = "SendHideTextByDefaultToggle") - .fillMaxWidth() - .padding(horizontal = 16.dp), - label = stringResource(id = R.string.hide_text_by_default), - isChecked = type.isHideByDefaultChecked, - onCheckedChange = addSendHandlers.onIsHideByDefaultToggle, - readOnly = policyDisablesSend, - ) - } } - Spacer(modifier = Modifier.height(16.dp)) - AddSendOptions( - state = state, - sendRestrictionPolicy = policyDisablesSend, - isAddMode = isAddMode, - addSendHandlers = addSendHandlers, - ) - - Spacer(modifier = Modifier.height(24.dp)) - Spacer(modifier = Modifier.navigationBarsPadding()) + is AddSendState.ViewState.Content.SendType.Text -> { + BitwardenTextField( + modifier = Modifier + .testTag(tag = "SendTextContentEntry") + .fillMaxWidth() + .padding(horizontal = 16.dp), + label = stringResource(id = R.string.text), + hint = stringResource(id = R.string.type_text_info), + readOnly = policyDisablesSend, + value = type.input, + singleLine = false, + onValueChange = addSendHandlers.onTextChange, + ) + Spacer(modifier = Modifier.height(16.dp)) + BitwardenSwitch( + modifier = Modifier + .testTag(tag = "SendHideTextByDefaultToggle") + .fillMaxWidth() + .padding(horizontal = 16.dp), + label = stringResource(id = R.string.hide_text_by_default), + isChecked = type.isHideByDefaultChecked, + onCheckedChange = addSendHandlers.onIsHideByDefaultToggle, + readOnly = policyDisablesSend, + ) + } } + + Spacer(modifier = Modifier.height(16.dp)) + AddSendOptions( + state = state, + sendRestrictionPolicy = policyDisablesSend, + isAddMode = isAddMode, + addSendHandlers = addSendHandlers, + ) + + Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.navigationBarsPadding()) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreen.kt index 1aa631e55..393c6907a 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreen.kt @@ -3,8 +3,8 @@ package com.x8bit.bitwarden.ui.tools.feature.send.addsend import android.widget.Toast import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState @@ -23,6 +23,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect +import com.x8bit.bitwarden.ui.platform.base.util.scrolledContainerBottomDivider import com.x8bit.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar import com.x8bit.bitwarden.ui.platform.components.appbar.NavigationIcon import com.x8bit.bitwarden.ui.platform.components.appbar.action.BitwardenOverflowActionItem @@ -37,6 +38,8 @@ import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialo import com.x8bit.bitwarden.ui.platform.components.dialog.LoadingDialogState import com.x8bit.bitwarden.ui.platform.components.model.TopAppBarDividerStyle import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold +import com.x8bit.bitwarden.ui.platform.components.segment.BitwardenSegmentedButton +import com.x8bit.bitwarden.ui.platform.components.segment.SegmentedButtonState import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter import com.x8bit.bitwarden.ui.platform.composition.LocalExitManager import com.x8bit.bitwarden.ui.platform.composition.LocalIntentManager @@ -46,11 +49,12 @@ import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.platform.manager.permissions.PermissionsManager import com.x8bit.bitwarden.ui.platform.util.persistentListOfNotNull import com.x8bit.bitwarden.ui.tools.feature.send.addsend.handlers.AddSendHandlers +import kotlinx.collections.immutable.persistentListOf /** * Displays new send UX. */ -@Suppress("LongMethod") +@Suppress("LongMethod", "CyclomaticComplexMethod") @OptIn(ExperimentalMaterial3Api::class) @Composable fun AddSendScreen( @@ -187,16 +191,41 @@ fun AddSendScreen( }, ) }, - ) { innerPadding -> + utilityBar = { + val viewState = state.viewState + if (state.isAddMode && + !state.isShared && + viewState is AddSendState.ViewState.Content + ) { + BitwardenSegmentedButton( + modifier = Modifier + .scrolledContainerBottomDivider(topAppBarScrollBehavior = scrollBehavior) + .fillMaxWidth(), + options = persistentListOf( + SegmentedButtonState( + text = stringResource(id = R.string.file), + onClick = addSendHandlers.onFileTypeSelect, + isChecked = viewState.isFileType, + testTag = "SendFileButton", + ), + SegmentedButtonState( + text = stringResource(id = R.string.text), + onClick = addSendHandlers.onTextTypeSelect, + isChecked = viewState.isTextType, + testTag = "SendTextButton", + ), + ), + ) + } + }, + ) { val modifier = Modifier .imePadding() .fillMaxSize() - .padding(paddingValues = innerPadding) when (val viewState = state.viewState) { is AddSendState.ViewState.Content -> AddSendContent( state = viewState, - scrollBehavior = scrollBehavior, policyDisablesSend = state.policyDisablesSend, policySendOptionsInEffect = state.shouldDisplayPolicyWarning, isAddMode = state.isAddMode, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreen.kt index 0e302f146..f33e0b751 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/addedit/VaultAddEditScreen.kt @@ -3,7 +3,6 @@ package com.x8bit.bitwarden.ui.vault.feature.addedit import android.widget.Toast import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState @@ -312,7 +311,7 @@ fun VaultAddEditScreen( .takeUnless { state.isAddItemMode || !state.isCipherInCollection || - !state.canAssociateToCollections + !state.canAssociateToCollections }, OverflowMenuItemData( text = stringResource(id = R.string.delete), @@ -324,7 +323,7 @@ fun VaultAddEditScreen( }, ) }, - ) { innerPadding -> + ) { when (val viewState = state.viewState) { is VaultAddEditState.ViewState.Content -> { VaultAddEditContent( @@ -342,7 +341,6 @@ fun VaultAddEditScreen( sshKeyItemTypeHandlers = sshKeyItemTypeHandlers, modifier = Modifier .imePadding() - .padding(innerPadding) .fillMaxSize(), ) } @@ -350,17 +348,13 @@ fun VaultAddEditScreen( is VaultAddEditState.ViewState.Error -> { BitwardenErrorContent( message = viewState.message(), - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } VaultAddEditState.ViewState.Loading -> { BitwardenLoadingContent( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/attachments/AttachmentsScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/attachments/AttachmentsScreen.kt index c530c23b6..bd5577c51 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/attachments/AttachmentsScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/attachments/AttachmentsScreen.kt @@ -2,7 +2,6 @@ package com.x8bit.bitwarden.ui.vault.feature.attachments import android.widget.Toast import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState @@ -98,24 +97,21 @@ fun AttachmentsScreen( }, ) }, - ) { innerPadding -> - val modifier = Modifier - .fillMaxSize() - .padding(innerPadding) + ) { when (val viewState = state.viewState) { is AttachmentsState.ViewState.Content -> AttachmentsContent( viewState = viewState, attachmentsHandlers = attachmentsHandlers, - modifier = modifier, + modifier = Modifier.fillMaxSize(), ) is AttachmentsState.ViewState.Error -> BitwardenErrorContent( message = viewState.message(), - modifier = modifier, + modifier = Modifier.fillMaxSize(), ) AttachmentsState.ViewState.Loading -> BitwardenLoadingContent( - modifier = modifier, + modifier = Modifier.fillMaxSize(), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/importlogins/ImportLoginsScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/importlogins/ImportLoginsScreen.kt index 2f8ed1e3b..ed69a0603 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/importlogins/ImportLoginsScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/importlogins/ImportLoginsScreen.kt @@ -104,10 +104,9 @@ fun ImportLoginsScreen( onDismiss = handler.onSuccessfulSyncAcknowledged, sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), modifier = Modifier.statusBarsPadding(), - ) { paddingValues, animatedOnDismiss -> + ) { animatedOnDismiss -> ImportLoginsSuccessBottomSheetContent( onCompleteImportLogins = animatedOnDismiss, - modifier = Modifier.padding(paddingValues), ) } @@ -132,13 +131,11 @@ fun ImportLoginsScreen( scrollBehavior = scrollBehavior, ) }, - ) { innerPadding -> + ) { Crossfade( targetState = state.viewState, label = "CrossfadeBetweenViewStates", - modifier = Modifier - .fillMaxSize() - .padding(paddingValues = innerPadding), + modifier = Modifier.fillMaxSize(), ) { viewState -> when (viewState) { ImportLoginsState.ViewState.InitialContent -> { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt index dc46ed4d6..5f8ca044e 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt @@ -254,13 +254,12 @@ fun VaultItemScreen( ) } }, - ) { innerPadding -> + ) { VaultItemContent( viewState = state.viewState, modifier = Modifier .imePadding() - .fillMaxSize() - .padding(innerPadding), + .fillMaxSize(), vaultCommonItemTypeHandlers = remember(viewModel) { VaultCommonItemTypeHandlers.create(viewModel = viewModel) }, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreen.kt index 7b86d7680..122a93b21 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingScreen.kt @@ -3,7 +3,6 @@ package com.x8bit.bitwarden.ui.vault.feature.itemlisting import android.widget.Toast import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState @@ -456,12 +455,24 @@ private fun VaultItemListingScaffold( ) } }, + overlay = { + BitwardenAccountSwitcher( + isVisible = isAccountMenuVisible, + accountSummaries = state.accountSummaries.toImmutableList(), + onSwitchAccountClick = vaultItemListingHandlers.switchAccountClick, + onLockAccountClick = vaultItemListingHandlers.lockAccountClick, + onLogoutAccountClick = vaultItemListingHandlers.logoutAccountClick, + onAddAccountClick = { + // Not available + }, + onDismissRequest = { isAccountMenuVisible = false }, + isAddAccountAvailable = false, + topAppBarScrollBehavior = scrollBehavior, + modifier = Modifier.fillMaxSize(), + ) + }, pullToRefreshState = pullToRefreshState, - ) { paddingValues -> - val modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - + ) { when (state.viewState) { is VaultItemListingState.ViewState.Content -> { VaultItemListingContent( @@ -475,7 +486,7 @@ private fun VaultItemListingScaffold( masterPasswordRepromptSubmit = vaultItemListingHandlers.masterPasswordRepromptSubmit, onOverflowItemClick = vaultItemListingHandlers.overflowItemClick, - modifier = modifier, + modifier = Modifier.fillMaxSize(), ) } @@ -485,7 +496,7 @@ private fun VaultItemListingScaffold( policyDisablesSend = state.policyDisablesSend && state.itemListingType is VaultItemListingState.ItemListingType.Send, addItemClickAction = vaultItemListingHandlers.addVaultItemClick, - modifier = modifier, + modifier = Modifier.fillMaxSize(), ) } @@ -493,28 +504,13 @@ private fun VaultItemListingScaffold( BitwardenErrorContent( message = state.viewState.message(), onTryAgainClick = vaultItemListingHandlers.refreshClick, - modifier = modifier, + modifier = Modifier.fillMaxSize(), ) } is VaultItemListingState.ViewState.Loading -> { - BitwardenLoadingContent(modifier = modifier) + BitwardenLoadingContent(modifier = Modifier.fillMaxSize()) } } - - BitwardenAccountSwitcher( - isVisible = isAccountMenuVisible, - accountSummaries = state.accountSummaries.toImmutableList(), - onSwitchAccountClick = vaultItemListingHandlers.switchAccountClick, - onLockAccountClick = vaultItemListingHandlers.lockAccountClick, - onLogoutAccountClick = vaultItemListingHandlers.logoutAccountClick, - onAddAccountClick = { - // Not available - }, - onDismissRequest = { isAccountMenuVisible = false }, - isAddAccountAvailable = false, - topAppBarScrollBehavior = scrollBehavior, - modifier = modifier, - ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreen.kt index 9fff98335..4ac5a552d 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreen.kt @@ -121,9 +121,8 @@ fun ManualCodeEntryScreen( scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()), ) }, - ) { paddingValues -> - Column(modifier = Modifier.padding(paddingValues)) { - + ) { + Column { Text( text = stringResource(id = R.string.enter_key_manually), style = BitwardenTheme.typography.titleMedium, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationScreen.kt index f64da9f80..f8e4c84f9 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/movetoorganization/VaultMoveToOrganizationScreen.kt @@ -3,7 +3,6 @@ package com.x8bit.bitwarden.ui.vault.feature.movetoorganization import android.widget.Toast import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState @@ -126,12 +125,10 @@ private fun VaultMoveToOrganizationScaffold( }, ) }, - ) { innerPadding -> + ) { val modifier = Modifier .imePadding() .fillMaxSize() - .padding(innerPadding) - when (state.viewState) { is VaultMoveToOrganizationState.ViewState.Content -> { VaultMoveToOrganizationContent( 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 2e14935b9..204f19d8f 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 @@ -125,24 +125,21 @@ fun QrCodeScanScreen( ), ) }, - ) { innerPadding -> + ) { CameraPreview( cameraErrorReceive = remember(viewModel) { { viewModel.trySendAction(QrCodeScanAction.CameraSetupErrorReceive) } }, qrCodeAnalyzer = qrCodeAnalyzer, - modifier = Modifier.padding(innerPadding), ) if (LocalConfiguration.current.isPortrait) { PortraitQRCodeContent( onEnterCodeManuallyClick = onEnterCodeManuallyClick, - modifier = Modifier.padding(innerPadding), ) } else { LandscapeQRCodeContent( onEnterCodeManuallyClick = onEnterCodeManuallyClick, - modifier = Modifier.padding(innerPadding), ) } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultFilter.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultFilter.kt index 6753fcaae..4ff90c09b 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultFilter.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultFilter.kt @@ -2,8 +2,15 @@ package com.x8bit.bitwarden.ui.vault.feature.vault import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.displayCutout +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.union import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarScrollBehavior @@ -37,6 +44,7 @@ import kotlinx.collections.immutable.ImmutableList * @param topAppBarScrollBehavior Used to derive the background color of the content and keep it in * sync with the associated app bar. * @param modifier A [Modifier] for the composable. + * @param windowInsets The insets to be applied to this composable. */ @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -46,6 +54,9 @@ fun VaultFilter( onVaultFilterTypeSelect: (VaultFilterType) -> Unit, topAppBarScrollBehavior: TopAppBarScrollBehavior, modifier: Modifier = Modifier, + windowInsets: WindowInsets = WindowInsets.displayCutout + .union(WindowInsets.navigationBars) + .only(WindowInsetsSides.Horizontal), ) { var shouldShowSelectionDialog by remember { mutableStateOf(false) } @@ -73,7 +84,8 @@ fun VaultFilter( .scrolledContainerBottomDivider(topAppBarScrollBehavior = topAppBarScrollBehavior) .padding(vertical = 8.dp) .testTag("ActiveFilterRow") - .then(modifier), + .then(modifier) + .windowInsetsPadding(insets = windowInsets), verticalAlignment = Alignment.CenterVertically, ) { Text( diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt index 04f3c078a..fcdc65591 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt @@ -4,7 +4,6 @@ import android.widget.Toast import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.scaleIn import androidx.compose.animation.scaleOut -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -240,6 +239,24 @@ private fun VaultScreenScaffold( }, ) }, + utilityBar = { + state.vaultFilterDataWithFilter?.let { + VaultFilter( + selectedVaultFilterType = it.selectedVaultFilterType, + vaultFilterTypes = it.vaultFilterTypes.toImmutableList(), + onVaultFilterTypeSelect = vaultHandlers.vaultFilterTypeSelect, + topAppBarScrollBehavior = scrollBehavior, + modifier = Modifier + .padding( + start = 16.dp, + // There is some built-in padding to the menu button that makes up + // the visual difference here. + end = 12.dp, + ) + .fillMaxWidth(), + ) + } + }, snackbarHost = { BitwardenSnackbarHost( bitwardenHostState = snackbarHostState, @@ -259,81 +276,7 @@ private fun VaultScreenScaffold( ) } }, - pullToRefreshState = pullToRefreshState, - modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), - ) { paddingValues -> - Box { - val innerModifier = Modifier - .fillMaxSize() - val outerModifier = Modifier - .fillMaxSize() - .padding(paddingValues) - Column(modifier = outerModifier) { - state.vaultFilterDataWithFilter?.let { - VaultFilter( - selectedVaultFilterType = it.selectedVaultFilterType, - vaultFilterTypes = it.vaultFilterTypes.toImmutableList(), - onVaultFilterTypeSelect = vaultHandlers.vaultFilterTypeSelect, - topAppBarScrollBehavior = scrollBehavior, - modifier = Modifier - .padding( - start = 16.dp, - // There is some built-in padding to the menu button that makes up - // the visual difference here. - end = 12.dp, - ) - .fillMaxWidth(), - ) - } - - when (val viewState = state.viewState) { - is VaultState.ViewState.Content -> VaultContent( - state = viewState, - showSshKeys = state.showSshKeys, - vaultHandlers = vaultHandlers, - onOverflowOptionClick = { masterPasswordRepromptAction = it }, - modifier = innerModifier, - ) - - is VaultState.ViewState.Loading -> BitwardenLoadingContent( - modifier = innerModifier, - ) - - is VaultState.ViewState.NoItems -> { - AnimatedVisibility( - visible = state.showImportActionCard, - exit = actionCardExitAnimation(), - label = "VaultNoItemsActionCard", - ) { - BitwardenActionCard( - cardTitle = stringResource(R.string.import_saved_logins), - cardSubtitle = stringResource( - R.string.use_a_computer_to_import_logins, - ), - actionText = stringResource(R.string.get_started), - onActionClick = vaultHandlers.importActionCardClick, - onDismissClick = vaultHandlers.dismissImportActionCard, - modifier = Modifier - .fillMaxWidth() - .standardHorizontalMargin() - .padding(top = 12.dp), - ) - } - VaultNoItems( - modifier = innerModifier, - policyDisablesSend = false, - addItemClickAction = vaultHandlers.addItemClickAction, - ) - } - - is VaultState.ViewState.Error -> BitwardenErrorContent( - message = viewState.message(), - onTryAgainClick = vaultHandlers.tryAgainClick, - modifier = innerModifier, - ) - } - } - + overlay = { BitwardenAccountSwitcher( isVisible = accountMenuVisible, accountSummaries = state.accountSummaries.toImmutableList(), @@ -343,8 +286,61 @@ private fun VaultScreenScaffold( onAddAccountClick = vaultHandlers.addAccountClickAction, onDismissRequest = { updateAccountMenuVisibility(false) }, topAppBarScrollBehavior = scrollBehavior, - modifier = outerModifier, + modifier = Modifier.fillMaxSize(), ) + }, + pullToRefreshState = pullToRefreshState, + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), + ) { + Column( + modifier = Modifier.fillMaxSize(), + ) { + when (val viewState = state.viewState) { + is VaultState.ViewState.Content -> VaultContent( + state = viewState, + showSshKeys = state.showSshKeys, + vaultHandlers = vaultHandlers, + onOverflowOptionClick = { masterPasswordRepromptAction = it }, + modifier = Modifier.fillMaxSize(), + ) + + is VaultState.ViewState.Loading -> BitwardenLoadingContent( + modifier = Modifier.fillMaxSize(), + ) + + is VaultState.ViewState.NoItems -> { + AnimatedVisibility( + visible = state.showImportActionCard, + exit = actionCardExitAnimation(), + label = "VaultNoItemsActionCard", + ) { + BitwardenActionCard( + cardTitle = stringResource(R.string.import_saved_logins), + cardSubtitle = stringResource( + R.string.use_a_computer_to_import_logins, + ), + actionText = stringResource(R.string.get_started), + onActionClick = vaultHandlers.importActionCardClick, + onDismissClick = vaultHandlers.dismissImportActionCard, + modifier = Modifier + .fillMaxWidth() + .standardHorizontalMargin() + .padding(top = 12.dp), + ) + } + VaultNoItems( + policyDisablesSend = false, + addItemClickAction = vaultHandlers.addItemClickAction, + modifier = Modifier.fillMaxSize(), + ) + } + + is VaultState.ViewState.Error -> BitwardenErrorContent( + message = viewState.message(), + onTryAgainClick = vaultHandlers.tryAgainClick, + modifier = Modifier.fillMaxSize(), + ) + } } } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/verificationcode/VerificationCodeScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/verificationcode/VerificationCodeScreen.kt index ee28a1d56..13d461bfb 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/verificationcode/VerificationCodeScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/verificationcode/VerificationCodeScreen.kt @@ -106,18 +106,14 @@ fun VerificationCodeScreen( ) }, pullToRefreshState = pullToRefreshState, - ) { paddingValues -> - val modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - + ) { when (val viewState = state.viewState) { is VerificationCodeState.ViewState.Content -> { VerificationCodeContent( items = viewState.verificationCodeDisplayItems.toImmutableList(), onCopyClick = verificationCodeHandler.copyClick, itemClick = verificationCodeHandler.itemClick, - modifier = modifier, + modifier = Modifier.fillMaxSize(), ) } @@ -125,12 +121,12 @@ fun VerificationCodeScreen( BitwardenErrorContent( message = viewState.message.invoke(), onTryAgainClick = verificationCodeHandler.refreshClick, - modifier = modifier, + modifier = Modifier.fillMaxSize(), ) } is VerificationCodeState.ViewState.Loading -> { - BitwardenLoadingContent(modifier = modifier) + BitwardenLoadingContent(modifier = Modifier.fillMaxSize()) } } } diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt index 0238980a5..407029d6c 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt @@ -409,7 +409,8 @@ class AddSendScreenTest : BaseComposeTest() { @Test fun `Text segmented button click should send TextTypeClick`() { composeTestRule - .onAllNodesWithText("Text")[0] + .onAllNodesWithText("Text") + .filterToOne(!isEditableText) // A bug prevents performClick from working here so we // have to perform the semantic action instead. .performSemanticsAction(SemanticsActions.OnClick) @@ -469,9 +470,13 @@ class AddSendScreenTest : BaseComposeTest() { @Test fun `text input change should send TextChange`() { composeTestRule - .onAllNodesWithText("Text")[1] + .onAllNodesWithText("Text") + .filterToOne(isEditableText) + .performScrollTo() .performTextInput("input") - viewModel.trySendAction(AddSendAction.TextChange("input")) + verify(exactly = 1) { + viewModel.trySendAction(AddSendAction.TextChange("input")) + } } @Test diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 732730d38..2037edf06 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,8 +2,8 @@ [versions] # SDK Versions -compileSdk = "34" -targetSdk = "34" +compileSdk = "35" +targetSdk = "35" minSdk = "29" # Dependency Versions @@ -13,17 +13,17 @@ androidXBiometrics = "1.2.0-alpha05" androidxBrowser = "1.8.0" androidxCamera = "1.4.0" androidxComposeBom = "2024.10.01" -androidxCore = "1.13.1" +androidxCore = "1.15.0" androidxCredentials = "1.3.0" androidxHiltNavigationCompose = "1.2.0" -androidxLifecycle = "2.8.6" +androidxLifecycle = "2.8.7" androidxNavigation = "2.8.0" androidxRoom = "2.6.1" androidXSecurityCrypto = "1.1.0-alpha06" androidxSplash = "1.1.0-rc01" androidXAppCompat = "1.7.0" androdixAutofill = "1.1.0" -androidxWork = "2.9.1" +androidxWork = "2.10.0" bitwardenSdk = "1.0.0-20241030.101847-8" crashlytics = "3.0.2" detekt = "1.23.7"