PM-26303: Remoe the 'Exit' button from the VaultScreen overflow menu (#5956)

This commit is contained in:
David Perez 2025-09-29 11:35:25 -05:00 committed by GitHub
parent f0946e05d5
commit 2363b0d619
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 0 additions and 121 deletions

View File

@ -60,9 +60,7 @@ import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenPlurals
import com.bitwarden.ui.platform.resource.BitwardenString
import com.x8bit.bitwarden.ui.platform.composition.LocalAppReviewManager
import com.x8bit.bitwarden.ui.platform.composition.LocalExitManager
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.platform.manager.exit.ExitManager
import com.x8bit.bitwarden.ui.platform.manager.review.AppReviewManager
import com.x8bit.bitwarden.ui.vault.components.VaultItemSelectionDialog
import com.x8bit.bitwarden.ui.vault.components.model.CreateVaultItemType
@ -96,7 +94,6 @@ fun VaultScreen(
onNavigateToAddFolderScreen: (selectedFolderId: String?) -> Unit,
onNavigateToAboutScreen: () -> Unit,
onNavigateToAutofillScreen: () -> Unit,
exitManager: ExitManager = LocalExitManager.current,
intentManager: IntentManager = LocalIntentManager.current,
appReviewManager: AppReviewManager = LocalAppReviewManager.current,
) {
@ -162,8 +159,6 @@ fun VaultScreen(
}
is VaultEvent.NavigateToUrl -> intentManager.launchUri(event.url.toUri())
VaultEvent.NavigateOutOfApp -> exitManager.exitApplication()
VaultEvent.NavigateToImportLogins -> onNavigateToImportLogins()
is VaultEvent.ShowSnackbar -> snackbarHostState.showSnackbar(event.data)
VaultEvent.PromptForAppReview -> {
@ -213,7 +208,6 @@ private fun VaultScreenScaffold(
accountMenuVisible = shouldShowMenu
onDimBottomNavBarRequest(shouldShowMenu)
}
var shouldShowExitConfirmationDialog by rememberSaveable { mutableStateOf(false) }
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(
state = rememberTopAppBarState(),
canScroll = { !accountMenuVisible },
@ -221,23 +215,6 @@ private fun VaultScreenScaffold(
// Dynamic dialogs
VaultDialogs(dialogState = state.dialog, vaultHandlers = vaultHandlers)
// Static dialogs
if (shouldShowExitConfirmationDialog) {
BitwardenTwoButtonDialog(
title = stringResource(id = BitwardenString.exit),
message = stringResource(id = BitwardenString.exit_confirmation),
confirmButtonText = stringResource(id = BitwardenString.yes),
dismissButtonText = stringResource(id = BitwardenString.cancel),
onConfirmClick = {
shouldShowExitConfirmationDialog = false
vaultHandlers.exitConfirmationAction()
},
onDismissClick = { shouldShowExitConfirmationDialog = false },
onDismissRequest = { shouldShowExitConfirmationDialog = false },
)
}
BitwardenScaffold(
topBar = {
BitwardenMediumTopAppBar(
@ -270,10 +247,6 @@ private fun VaultScreenScaffold(
text = stringResource(id = BitwardenString.lock),
onClick = vaultHandlers.lockAction,
),
OverflowMenuItemData(
text = stringResource(id = BitwardenString.exit),
onClick = { shouldShowExitConfirmationDialog = true },
),
),
)
},

View File

@ -242,7 +242,6 @@ class VaultViewModel @Inject constructor(
is VaultAction.AddAccountClick -> handleAddAccountClick()
is VaultAction.SyncClick -> handleSyncClick()
is VaultAction.LockClick -> handleLockClick()
is VaultAction.ExitConfirmationClick -> handleExitConfirmationClick()
is VaultAction.VaultFilterTypeSelect -> handleVaultFilterTypeSelect(action)
is VaultAction.SecureNoteGroupClick -> handleSecureNoteClick()
is VaultAction.SshKeyGroupClick -> handleSshKeyClick()
@ -497,10 +496,6 @@ class VaultViewModel @Inject constructor(
vaultRepository.lockVaultForCurrentUser(isUserInitiated = true)
}
private fun handleExitConfirmationClick() {
sendEvent(VaultEvent.NavigateOutOfApp)
}
private fun handleVaultFilterTypeSelect(action: VaultAction.VaultFilterTypeSelect) {
// Update the current filter
vaultRepository.vaultFilterType = action.vaultFilterType
@ -1573,11 +1568,6 @@ sealed class VaultEvent {
*/
data object NavigateToVerificationCodeScreen : VaultEvent()
/**
* Navigate out of the app.
*/
data object NavigateOutOfApp : VaultEvent()
/**
* Navigate to the import logins screen.
*/
@ -1698,12 +1688,6 @@ sealed class VaultAction {
*/
data object LockClick : VaultAction()
/**
* User confirmed that they want to exit the app after clicking the Sync option in the overflow
* menu.
*/
data object ExitConfirmationClick : VaultAction()
/**
* User selected a [VaultFilterType] from the Vault Filter menu.
*/

View File

@ -22,7 +22,6 @@ data class VaultHandlers(
val addAccountClickAction: () -> Unit,
val syncAction: () -> Unit,
val lockAction: () -> Unit,
val exitConfirmationAction: () -> Unit,
val vaultItemClick: (VaultState.ViewState.VaultItem) -> Unit,
val folderClick: (VaultState.ViewState.FolderItem) -> Unit,
val collectionClick: (VaultState.ViewState.CollectionItem) -> Unit,
@ -79,9 +78,6 @@ data class VaultHandlers(
addAccountClickAction = { viewModel.trySendAction(VaultAction.AddAccountClick) },
syncAction = { viewModel.trySendAction(VaultAction.SyncClick) },
lockAction = { viewModel.trySendAction(VaultAction.LockClick) },
exitConfirmationAction = {
viewModel.trySendAction(VaultAction.ExitConfirmationClick)
},
vaultItemClick = { viewModel.trySendAction(VaultAction.VaultItemClick(it)) },
folderClick = { viewModel.trySendAction(VaultAction.FolderClick(it)) },
collectionClick = { viewModel.trySendAction(VaultAction.CollectionClick(it)) },

View File

@ -49,7 +49,6 @@ import com.bitwarden.ui.util.performYesDialogButtonClick
import com.bitwarden.vault.CipherType
import com.x8bit.bitwarden.data.util.advanceTimeByAndRunCurrent
import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
import com.x8bit.bitwarden.ui.platform.manager.exit.ExitManager
import com.x8bit.bitwarden.ui.platform.manager.review.AppReviewManager
import com.x8bit.bitwarden.ui.vault.components.model.CreateVaultItemType
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditArgs
@ -90,7 +89,6 @@ class VaultScreenTest : BitwardenComposeTest() {
private var onNavigateToSearchScreen = false
private var onNavigateToAddFolderCalled = false
private var onNavigateToAddFolderParentFolderName: String? = null
private val exitManager = mockk<ExitManager>(relaxed = true)
private val intentManager = mockk<IntentManager>(relaxed = true)
private val appReviewManager: AppReviewManager = mockk {
every { promptForReview() } just runs
@ -105,7 +103,6 @@ class VaultScreenTest : BitwardenComposeTest() {
@Before
fun setUp() {
setContent(
exitManager = exitManager,
intentManager = intentManager,
appReviewManager = appReviewManager,
) {
@ -416,7 +413,6 @@ class VaultScreenTest : BitwardenComposeTest() {
composeTestRule.onNode(isPopup()).assertDoesNotExist()
composeTestRule.onNodeWithText("Sync").assertDoesNotExist()
composeTestRule.onNodeWithText("Lock").assertDoesNotExist()
composeTestRule.onNodeWithText("Exit").assertDoesNotExist()
composeTestRule.onNodeWithContentDescription("More").performClick()
@ -429,10 +425,6 @@ class VaultScreenTest : BitwardenComposeTest() {
.onAllNodesWithText("Lock")
.filterToOne(hasAnyAncestor(isPopup()))
.assertIsDisplayed()
composeTestRule
.onAllNodesWithText("Exit")
.filterToOne(hasAnyAncestor(isPopup()))
.assertIsDisplayed()
}
@Test
@ -461,55 +453,6 @@ class VaultScreenTest : BitwardenComposeTest() {
verify { viewModel.trySendAction(VaultAction.LockClick) }
}
@Test
fun `exit click in the overflow menu should show a confirmation dialog`() {
// Expand the overflow menu
composeTestRule.onNodeWithContentDescription("More").performClick()
composeTestRule
.onAllNodesWithText("Exit")
.filterToOne(hasAnyAncestor(isPopup()))
.performClick()
composeTestRule
.onNode(isDialog())
.assertIsDisplayed()
composeTestRule
.onAllNodesWithText("Exit")
.filterToOne(hasAnyAncestor(isDialog()))
.assertIsDisplayed()
composeTestRule
.onAllNodesWithText("Are you sure you want to exit Bitwarden?")
.filterToOne(hasAnyAncestor(isDialog()))
.assertIsDisplayed()
composeTestRule
.onAllNodesWithText("Yes")
.filterToOne(hasAnyAncestor(isDialog()))
.assertIsDisplayed()
composeTestRule
.onAllNodesWithText("Cancel")
.filterToOne(hasAnyAncestor(isDialog()))
.assertIsDisplayed()
}
@Test
fun `yes click in exit confirmation dialog should send ExitConfirmationClick`() {
// Expand the overflow menu and show the exit confirmation dialog
composeTestRule.onNodeWithContentDescription("More").performClick()
composeTestRule
.onAllNodesWithText("Exit")
.filterToOne(hasAnyAncestor(isPopup()))
.performClick()
composeTestRule
.onAllNodesWithText("Yes")
.filterToOne(hasAnyAncestor(isDialog()))
.performClick()
composeTestRule.assertNoDialogExists()
verify { viewModel.trySendAction(VaultAction.ExitConfirmationClick) }
}
@Test
fun `floating action button should be shown or hidden according to the state`() {
val fabDescription = "Add Item"
@ -1056,12 +999,6 @@ class VaultScreenTest : BitwardenComposeTest() {
}
}
@Test
fun `NavigateOutOfApp event should call exitApplication on the ExitManager`() {
mutableEventFlow.tryEmit(VaultEvent.NavigateOutOfApp)
verify { exitManager.exitApplication() }
}
@Test
fun `totp section should be visible based on state`() {
mutableStateFlow.update { state ->

View File

@ -711,15 +711,6 @@ class VaultViewModelTest : BaseViewModelTest() {
}
}
@Test
fun `on ExitConfirmationClick should emit NavigateOutOfApp`() = runTest {
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(VaultAction.ExitConfirmationClick)
assertEquals(VaultEvent.NavigateOutOfApp, awaitItem())
}
}
@Suppress("MaxLineLength")
@Test
fun `on VaultFilterTypeSelect should update the selected filter type and re-filter any existing data`() {

View File

@ -366,8 +366,6 @@ Scanning will happen automatically.</string>
<string name="theme">Theme</string>
<string name="theme_description">Change the applications color theme</string>
<string name="copy_notes">Copy note</string>
<string name="exit">Exit</string>
<string name="exit_confirmation">Are you sure you want to exit Bitwarden?</string>
<string name="require_master_password_on_app_restart">Require master password on app restart?</string>
<string name="pin_require_master_password_restart">Do you want to require unlocking with your master password when the application is restarted?</string>
<string name="ask_to_add_item">Ask to add item</string>