PM-21591: Add navigation routing for the ViewSendScreen (#5185)

This commit is contained in:
David Perez 2025-05-13 12:28:10 -05:00 committed by GitHub
parent 97b8c51ab3
commit 6d68c3ae24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 192 additions and 32 deletions

View File

@ -7,6 +7,7 @@ import androidx.navigation.NavOptions
import androidx.navigation.toRoute
import com.bitwarden.ui.platform.base.util.composableWithSlideTransitions
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditArgs
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemArgs
import kotlinx.serialization.Serializable
@ -85,6 +86,7 @@ fun SavedStateHandle.toSearchArgs(): SearchArgs {
fun NavGraphBuilder.searchDestination(
onNavigateBack: () -> Unit,
onNavigateToEditSend: (sendId: String) -> Unit,
onNavigateToViewSend: (route: ViewSendRoute) -> Unit,
onNavigateToEditCipher: (args: VaultAddEditArgs) -> Unit,
onNavigateToViewCipher: (args: VaultItemArgs) -> Unit,
) {
@ -92,6 +94,7 @@ fun NavGraphBuilder.searchDestination(
SearchScreen(
onNavigateBack = onNavigateBack,
onNavigateToEditSend = onNavigateToEditSend,
onNavigateToViewSend = onNavigateToViewSend,
onNavigateToEditCipher = onNavigateToEditCipher,
onNavigateToViewCipher = onNavigateToViewCipher,
)

View File

@ -35,6 +35,7 @@ import com.x8bit.bitwarden.ui.platform.composition.LocalAppResumeStateManager
import com.x8bit.bitwarden.ui.platform.composition.LocalIntentManager
import com.x8bit.bitwarden.ui.platform.feature.search.handlers.SearchHandlers
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditArgs
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemArgs
import com.x8bit.bitwarden.ui.vault.feature.vault.VaultFilter
@ -44,12 +45,13 @@ import kotlinx.collections.immutable.toImmutableList
/**
* The search UI for vault items or send items.
*/
@Suppress("LongMethod")
@Suppress("LongMethod", "CyclomaticComplexMethod")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SearchScreen(
onNavigateBack: () -> Unit,
onNavigateToEditSend: (sendId: String) -> Unit,
onNavigateToViewSend: (route: ViewSendRoute) -> Unit,
onNavigateToEditCipher: (args: VaultAddEditArgs) -> Unit,
onNavigateToViewCipher: (args: VaultItemArgs) -> Unit,
intentManager: IntentManager = LocalIntentManager.current,
@ -72,6 +74,12 @@ fun SearchScreen(
when (event) {
SearchEvent.NavigateBack -> onNavigateBack()
is SearchEvent.NavigateToEditSend -> onNavigateToEditSend(event.sendId)
is SearchEvent.NavigateToViewSend -> {
onNavigateToViewSend(
ViewSendRoute(sendId = event.sendId, sendType = event.sendType),
)
}
is SearchEvent.NavigateToEditCipher -> {
onNavigateToEditCipher(
VaultAddEditArgs(

View File

@ -44,6 +44,7 @@ import com.x8bit.bitwarden.ui.platform.feature.search.util.filterAndOrganize
import com.x8bit.bitwarden.ui.platform.feature.search.util.toSearchTypeData
import com.x8bit.bitwarden.ui.platform.feature.search.util.toViewState
import com.x8bit.bitwarden.ui.platform.feature.search.util.updateWithAdditionalDataIfNecessary
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.model.ListingItemOverflowAction
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterData
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
@ -1190,6 +1191,14 @@ sealed class SearchEvent {
val sendId: String,
) : SearchEvent()
/**
* Navigates to view a send.
*/
data class NavigateToViewSend(
val sendId: String,
val sendType: SendItemType,
) : SearchEvent()
/**
* Navigates to view a cipher.
*/

View File

@ -39,6 +39,8 @@ import com.x8bit.bitwarden.ui.tools.feature.generator.passwordhistory.passwordHi
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.addSendDestination
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.model.AddSendType
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.navigateToAddSend
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.navigateToViewSend
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.viewSendDestination
import com.x8bit.bitwarden.ui.vault.feature.addedit.navigateToVaultAddEdit
import com.x8bit.bitwarden.ui.vault.feature.addedit.vaultAddEditDestination
import com.x8bit.bitwarden.ui.vault.feature.attachments.attachmentDestination
@ -102,6 +104,7 @@ fun NavGraphBuilder.vaultUnlockedGraph(
onNavigateToSearchSend = { navController.navigateToSearch(searchType = it) },
onNavigateToAddSend = { navController.navigateToAddSend(AddSendType.AddItem) },
onNavigateToEditSend = { navController.navigateToAddSend(AddSendType.EditItem(it)) },
onNavigateToViewSend = { navController.navigateToViewSend(route = it) },
onNavigateToDeleteAccount = { navController.navigateToDeleteAccount() },
onNavigateToPendingRequests = { navController.navigateToPendingRequests() },
onNavigateToPasswordHistory = {
@ -199,6 +202,12 @@ fun NavGraphBuilder.vaultUnlockedGraph(
)
addSendDestination(onNavigateBack = { navController.popBackStack() })
viewSendDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToEditSend = {
navController.navigateToAddSend(sendAddType = AddSendType.EditItem(sendItemId = it))
},
)
passwordHistoryDestination(onNavigateBack = { navController.popBackStack() })
exportVaultDestination(onNavigateBack = { navController.popBackStack() })
foldersDestination(
@ -218,6 +227,7 @@ fun NavGraphBuilder.vaultUnlockedGraph(
searchDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToEditSend = { navController.navigateToAddSend(AddSendType.EditItem(it)) },
onNavigateToViewSend = { navController.navigateToViewSend(it) },
onNavigateToEditCipher = { navController.navigateToVaultAddEdit(it) },
onNavigateToViewCipher = { navController.navigateToVaultItem(it) },
)

View File

@ -6,6 +6,7 @@ import androidx.navigation.NavOptions
import com.bitwarden.ui.platform.base.util.composableWithStayTransitions
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.platform.manager.snackbar.SnackbarRelay
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditArgs
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemArgs
import kotlinx.serialization.Serializable
@ -35,6 +36,7 @@ fun NavGraphBuilder.vaultUnlockedNavBarDestination(
onNavigateToSearchVault: (searchType: SearchType.Vault) -> Unit,
onNavigateToAddSend: () -> Unit,
onNavigateToEditSend: (sendItemId: String) -> Unit,
onNavigateToViewSend: (ViewSendRoute) -> Unit,
onNavigateToDeleteAccount: () -> Unit,
onNavigateToExportVault: () -> Unit,
onNavigateToFolders: () -> Unit,
@ -52,6 +54,7 @@ fun NavGraphBuilder.vaultUnlockedNavBarDestination(
onNavigateToVaultAddItem = onNavigateToVaultAddItem,
onNavigateToVaultItem = onNavigateToVaultItem,
onNavigateToVaultEditItem = onNavigateToVaultEditItem,
onNavigateToViewSend = onNavigateToViewSend,
onNavigateToSearchSend = onNavigateToSearchSend,
onNavigateToSearchVault = onNavigateToSearchVault,
onNavigateToAddSend = onNavigateToAddSend,

View File

@ -36,6 +36,7 @@ import com.x8bit.bitwarden.ui.tools.feature.generator.generatorGraph
import com.x8bit.bitwarden.ui.tools.feature.generator.navigateToGeneratorGraph
import com.x8bit.bitwarden.ui.tools.feature.send.navigateToSendGraph
import com.x8bit.bitwarden.ui.tools.feature.send.sendGraph
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditArgs
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemArgs
import com.x8bit.bitwarden.ui.vault.feature.vault.VaultGraphRoute
@ -60,6 +61,7 @@ fun VaultUnlockedNavBarScreen(
onNavigateToSearchVault: (searchType: SearchType.Vault) -> Unit,
onNavigateToAddSend: () -> Unit,
onNavigateToEditSend: (sendItemId: String) -> Unit,
onNavigateToViewSend: (ViewSendRoute) -> Unit,
onNavigateToDeleteAccount: () -> Unit,
onNavigateToExportVault: () -> Unit,
onNavigateToFolders: () -> Unit,
@ -122,6 +124,7 @@ fun VaultUnlockedNavBarScreen(
onNavigateToSearchVault = onNavigateToSearchVault,
navigateToAddSend = onNavigateToAddSend,
onNavigateToEditSend = onNavigateToEditSend,
onNavigateToViewSend = onNavigateToViewSend,
navigateToDeleteAccount = onNavigateToDeleteAccount,
navigateToExportVault = onNavigateToExportVault,
navigateToFolders = onNavigateToFolders,
@ -167,6 +170,7 @@ private fun VaultUnlockedNavBarScaffold(
onNavigateToSearchVault: (searchType: SearchType.Vault) -> Unit,
navigateToAddSend: () -> Unit,
onNavigateToEditSend: (sendItemId: String) -> Unit,
onNavigateToViewSend: (ViewSendRoute) -> Unit,
navigateToDeleteAccount: () -> Unit,
navigateToExportVault: () -> Unit,
navigateToFolders: () -> Unit,
@ -240,6 +244,7 @@ private fun VaultUnlockedNavBarScaffold(
navController = navController,
onNavigateToAddSend = navigateToAddSend,
onNavigateToEditSend = onNavigateToEditSend,
onNavigateToViewSend = onNavigateToViewSend,
onNavigateToSearchSend = onNavigateToSearchSend,
)
generatorGraph(

View File

@ -5,6 +5,7 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.navigation
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.navigateToSendItemListing
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.sendItemListingDestination
import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType
@ -23,6 +24,7 @@ fun NavGraphBuilder.sendGraph(
navController: NavController,
onNavigateToAddSend: () -> Unit,
onNavigateToEditSend: (sendItemId: String) -> Unit,
onNavigateToViewSend: (ViewSendRoute) -> Unit,
onNavigateToSearchSend: (searchType: SearchType.Sends) -> Unit,
) {
navigation<SendGraphRoute>(
@ -31,6 +33,7 @@ fun NavGraphBuilder.sendGraph(
sendDestination(
onNavigateToAddSend = onNavigateToAddSend,
onNavigateToEditSend = onNavigateToEditSend,
onNavigateToViewSend = onNavigateToViewSend,
onNavigateToSendFilesList = {
navController.navigateToSendItemListing(VaultItemListingType.SendFile)
},
@ -42,6 +45,7 @@ fun NavGraphBuilder.sendGraph(
sendItemListingDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToAddSendItem = onNavigateToAddSend,
onNavigateToViewSendItem = onNavigateToViewSend,
onNavigateToEditSendItem = onNavigateToEditSend,
onNavigateToSearchSend = onNavigateToSearchSend,
)

View File

@ -5,6 +5,7 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import com.bitwarden.ui.platform.base.util.composableWithRootPushTransitions
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import kotlinx.serialization.Serializable
/**
@ -16,9 +17,11 @@ data object SendRoute
/**
* Add send destination to the nav graph.
*/
@Suppress("LongParameterList")
fun NavGraphBuilder.sendDestination(
onNavigateToAddSend: () -> Unit,
onNavigateToEditSend: (sendItemId: String) -> Unit,
onNavigateToViewSend: (ViewSendRoute) -> Unit,
onNavigateToSendFilesList: () -> Unit,
onNavigateToSendTextList: () -> Unit,
onNavigateToSearchSend: (searchType: SearchType.Sends) -> Unit,
@ -27,6 +30,7 @@ fun NavGraphBuilder.sendDestination(
SendScreen(
onNavigateToAddSend = onNavigateToAddSend,
onNavigateToEditSend = onNavigateToEditSend,
onNavigateToViewSend = onNavigateToViewSend,
onNavigateToSendFilesList = onNavigateToSendFilesList,
onNavigateToSendTextList = onNavigateToSendTextList,
onNavigateToSearchSend = onNavigateToSearchSend,

View File

@ -41,6 +41,7 @@ import com.x8bit.bitwarden.ui.platform.composition.LocalIntentManager
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.handlers.SendHandlers
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import kotlinx.collections.immutable.persistentListOf
/**
@ -52,6 +53,7 @@ import kotlinx.collections.immutable.persistentListOf
fun SendScreen(
onNavigateToAddSend: () -> Unit,
onNavigateToEditSend: (sendItemId: String) -> Unit,
onNavigateToViewSend: (ViewSendRoute) -> Unit,
onNavigateToSendFilesList: () -> Unit,
onNavigateToSendTextList: () -> Unit,
onNavigateToSearchSend: (searchType: SearchType.Sends) -> Unit,
@ -83,6 +85,12 @@ fun SendScreen(
is SendEvent.NavigateToEditSend -> onNavigateToEditSend(event.sendId)
is SendEvent.NavigateToViewSend -> {
onNavigateToViewSend(
ViewSendRoute(sendId = event.sendId, sendType = event.sendType),
)
}
is SendEvent.NavigateToAboutSend -> {
intentManager.launchUri("https://bitwarden.com/products/send".toUri())
}

View File

@ -21,6 +21,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.DeleteSendResult
import com.x8bit.bitwarden.data.vault.repository.model.RemovePasswordSendResult
import com.x8bit.bitwarden.data.vault.repository.model.SendData
import com.x8bit.bitwarden.ui.platform.components.model.IconData
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.tools.feature.send.util.toViewState
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemScreen
import dagger.hilt.android.lifecycle.HiltViewModel
@ -91,6 +92,7 @@ class SendViewModel @Inject constructor(
is SendAction.CopyClick -> handleCopyClick(action)
SendAction.FileTypeClick -> handleFileTypeClick()
is SendAction.SendClick -> handleSendClick(action)
is SendAction.EditClick -> handleEditSendClick(action)
is SendAction.ShareClick -> handleShareClick(action)
SendAction.TextTypeClick -> handleTextTypeClick()
is SendAction.DeleteSendClick -> handleDeleteSendClick(action)
@ -303,6 +305,10 @@ class SendViewModel @Inject constructor(
sendEvent(SendEvent.NavigateToEditSend(action.sendItem.id))
}
private fun handleEditSendClick(action: SendAction.EditClick) {
sendEvent(SendEvent.NavigateToEditSend(sendId = action.sendItem.id))
}
private fun handleShareClick(action: SendAction.ShareClick) {
sendEvent(SendEvent.ShowShareSheet(action.sendItem.shareUrl))
}
@ -530,6 +536,13 @@ sealed class SendAction {
val sendItem: SendState.ViewState.Content.SendItem,
) : SendAction()
/**
* User clicked the edit item row.
*/
data class EditClick(
val sendItem: SendState.ViewState.Content.SendItem,
) : SendAction()
/**
* User clicked the copy item button.
*/
@ -624,6 +637,14 @@ sealed class SendEvent {
*/
data class NavigateToEditSend(val sendId: String) : SendEvent()
/**
* Navigate to the view send screen.
*/
data class NavigateToViewSend(
val sendId: String,
val sendType: SendItemType,
) : SendEvent()
/**
* Navigate to the about send screen.
*/

View File

@ -30,7 +30,7 @@ data class SendHandlers(
onTextTypeClick = { viewModel.trySendAction(SendAction.TextTypeClick) },
onFileTypeClick = { viewModel.trySendAction(SendAction.FileTypeClick) },
onSendClick = { viewModel.trySendAction(SendAction.SendClick(it)) },
onEditSendClick = { viewModel.trySendAction(SendAction.SendClick(it)) },
onEditSendClick = { viewModel.trySendAction(SendAction.EditClick(it)) },
onCopySendClick = { viewModel.trySendAction(SendAction.CopyClick(it)) },
onShareSendClick = { viewModel.trySendAction(SendAction.ShareClick(it)) },
onDeleteSendClick = { viewModel.trySendAction(SendAction.DeleteSendClick(it)) },

View File

@ -8,6 +8,7 @@ import androidx.navigation.toRoute
import com.bitwarden.ui.platform.base.util.composableWithPushTransitions
import com.bitwarden.ui.platform.base.util.composableWithStayTransitions
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditArgs
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemArgs
import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType
@ -121,6 +122,7 @@ fun NavGraphBuilder.vaultItemListingDestination(
internalVaultItemListingDestination<VaultItemListingRoute.CipherItemListing>(
onNavigateBack = onNavigateBack,
onNavigateToAddSendItem = { },
onNavigateToViewSendItem = { },
onNavigateToEditSendItem = { },
onNavigateToVaultAddItemScreen = onNavigateToVaultAddItemScreen,
onNavigateToVaultItemListing = onNavigateToVaultItemListing,
@ -153,6 +155,7 @@ fun NavGraphBuilder.vaultItemListingDestinationAsRoot(
onNavigateToAddFolder = onNavigateToAddFolderScreen,
onNavigateToVaultItemListing = {},
onNavigateToAddSendItem = {},
onNavigateToViewSendItem = {},
onNavigateToEditSendItem = {},
)
}
@ -164,12 +167,14 @@ fun NavGraphBuilder.vaultItemListingDestinationAsRoot(
fun NavGraphBuilder.sendItemListingDestination(
onNavigateBack: () -> Unit,
onNavigateToAddSendItem: () -> Unit,
onNavigateToViewSendItem: (route: ViewSendRoute) -> Unit,
onNavigateToEditSendItem: (sendId: String) -> Unit,
onNavigateToSearchSend: (searchType: SearchType.Sends) -> Unit,
) {
internalVaultItemListingDestination<VaultItemListingRoute.SendItemListing>(
onNavigateBack = onNavigateBack,
onNavigateToAddSendItem = onNavigateToAddSendItem,
onNavigateToViewSendItem = onNavigateToViewSendItem,
onNavigateToEditSendItem = onNavigateToEditSendItem,
onNavigateToVaultAddItemScreen = { },
onNavigateToAddFolderScreen = { _ -> },
@ -192,6 +197,7 @@ private inline fun <reified T : VaultItemListingRoute> NavGraphBuilder.internalV
noinline onNavigateToVaultAddItemScreen: (args: VaultAddEditArgs) -> Unit,
noinline onNavigateToAddFolderScreen: (selectedFolderId: String?) -> Unit,
noinline onNavigateToAddSendItem: () -> Unit,
noinline onNavigateToViewSendItem: (route: ViewSendRoute) -> Unit,
noinline onNavigateToEditSendItem: (sendId: String) -> Unit,
noinline onNavigateToSearch: (searchType: SearchType) -> Unit,
) {
@ -202,6 +208,7 @@ private inline fun <reified T : VaultItemListingRoute> NavGraphBuilder.internalV
onNavigateToVaultEditItemScreen = onNavigateToVaultEditItemScreen,
onNavigateToVaultAddItemScreen = onNavigateToVaultAddItemScreen,
onNavigateToAddSendItem = onNavigateToAddSendItem,
onNavigateToViewSendItem = onNavigateToViewSendItem,
onNavigateToEditSendItem = onNavigateToEditSendItem,
onNavigateToVaultItemListing = onNavigateToVaultItemListing,
onNavigateToSearch = onNavigateToSearch,

View File

@ -52,6 +52,7 @@ import com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity.PinInput
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManager
import com.x8bit.bitwarden.ui.platform.manager.exit.ExitManager
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import com.x8bit.bitwarden.ui.vault.components.VaultItemSelectionDialog
import com.x8bit.bitwarden.ui.vault.components.model.CreateVaultItemType
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditArgs
@ -77,6 +78,7 @@ fun VaultItemListingScreen(
onNavigateToVaultAddItemScreen: (args: VaultAddEditArgs) -> Unit,
onNavigateToAddFolder: (selectedFolderId: String?) -> Unit,
onNavigateToAddSendItem: () -> Unit,
onNavigateToViewSendItem: (route: ViewSendRoute) -> Unit,
onNavigateToEditSendItem: (sendId: String) -> Unit,
onNavigateToSearch: (searchType: SearchType) -> Unit,
intentManager: IntentManager = LocalIntentManager.current,
@ -127,6 +129,12 @@ fun VaultItemListingScreen(
)
}
is VaultItemListingEvent.NavigateToViewSendItem -> {
onNavigateToViewSendItem(
ViewSendRoute(sendId = event.id, sendType = event.sendType),
)
}
is VaultItemListingEvent.NavigateToEditCipher -> {
onNavigateToVaultEditItemScreen(
VaultAddEditArgs(
@ -144,7 +152,7 @@ fun VaultItemListingScreen(
onNavigateToAddSendItem()
}
is VaultItemListingEvent.NavigateToSendItem -> {
is VaultItemListingEvent.NavigateToEditSendItem -> {
onNavigateToEditSendItem(event.id)
}

View File

@ -71,6 +71,7 @@ import com.x8bit.bitwarden.ui.platform.feature.search.SearchTypeData
import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.platform.feature.search.util.filterAndOrganize
import com.x8bit.bitwarden.ui.platform.util.persistentListOfNotNull
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.vault.components.model.CreateVaultItemType
import com.x8bit.bitwarden.ui.vault.components.util.toVaultItemCipherTypeOrNull
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.model.ListingItemOverflowAction
@ -676,7 +677,7 @@ class VaultItemListingViewModel @Inject constructor(
}
private fun handleEditSendClick(action: ListingItemOverflowAction.SendAction.EditClick) {
sendEvent(VaultItemListingEvent.NavigateToSendItem(id = action.sendId))
sendEvent(VaultItemListingEvent.NavigateToEditSendItem(id = action.sendId))
}
private fun handleItemClick(action: VaultItemListingsAction.ItemClick) {
@ -720,7 +721,7 @@ class VaultItemListingViewModel @Inject constructor(
}
is VaultItemListingState.ItemListingType.Send -> {
VaultItemListingEvent.NavigateToSendItem(id = action.id)
VaultItemListingEvent.NavigateToEditSendItem(id = action.id)
}
}
sendEvent(event)
@ -2508,7 +2509,15 @@ sealed class VaultItemListingEvent {
*
* @property id the id of the send to navigate to.
*/
data class NavigateToSendItem(val id: String) : VaultItemListingEvent()
data class NavigateToEditSendItem(val id: String) : VaultItemListingEvent()
/**
* Navigates to the ViewSendScreen.
*/
data class NavigateToViewSendItem(
val id: String,
val sendType: SendItemType,
) : VaultItemListingEvent()
/**
* Navigates to the VaultItemScreen.

View File

@ -19,14 +19,16 @@ import androidx.compose.ui.test.performScrollToNode
import androidx.compose.ui.test.performTextInput
import androidx.core.net.toUri
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.ui.util.asText
import com.bitwarden.vault.CipherType
import com.x8bit.bitwarden.data.platform.manager.util.AppResumeStateManager
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.ui.platform.feature.search.model.AutofillSelectionOption
import com.x8bit.bitwarden.ui.platform.feature.search.util.createMockDisplayItemForCipher
import com.x8bit.bitwarden.ui.platform.feature.search.util.createMockDisplayItemForSend
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import com.x8bit.bitwarden.ui.util.assertMasterPasswordDialogDisplayed
import com.x8bit.bitwarden.ui.util.assertNoDialogExists
import com.x8bit.bitwarden.ui.util.assertNoPopupExists
@ -65,6 +67,7 @@ class SearchScreenTest : BaseComposeTest() {
private var onNavigateBackCalled = false
private var onNavigateToEditSendId: String? = null
private var onNavigateToViewSendRoute: ViewSendRoute? = null
private var onNavigateToEditCipherArgs: VaultAddEditArgs? = null
private var onNavigateToViewCipherArgs: VaultItemArgs? = null
@ -78,6 +81,7 @@ class SearchScreenTest : BaseComposeTest() {
viewModel = viewModel,
onNavigateBack = { onNavigateBackCalled = true },
onNavigateToEditSend = { onNavigateToEditSendId = it },
onNavigateToViewSend = { onNavigateToViewSendRoute = it },
onNavigateToEditCipher = { onNavigateToEditCipherArgs = it },
onNavigateToViewCipher = { onNavigateToViewCipherArgs = it },
)
@ -97,6 +101,19 @@ class SearchScreenTest : BaseComposeTest() {
assertEquals(sendId, onNavigateToEditSendId)
}
@Test
fun `NavigateToViewSend should call onNavigateToViewSend`() {
val sendId = "sendId1234"
val sendType = SendItemType.TEXT
mutableEventFlow.tryEmit(
SearchEvent.NavigateToViewSend(sendId = sendId, sendType = sendType),
)
assertEquals(
ViewSendRoute(sendId = sendId, sendType = sendType),
onNavigateToViewSendRoute,
)
}
@Test
fun `NavigateToEditCipher should call onNavigateToEditCipher`() {
val cipherId = "cipherId"

View File

@ -49,6 +49,7 @@ class VaultUnlockedNavBarScreenTest : BaseComposeTest() {
onNavigateToVaultEditItem = {},
onNavigateToAddSend = {},
onNavigateToEditSend = {},
onNavigateToViewSend = {},
onNavigateToDeleteAccount = {},
onNavigateToExportVault = {},
onNavigateToFolders = {},

View File

@ -23,10 +23,12 @@ import androidx.compose.ui.test.performScrollTo
import androidx.compose.ui.test.performScrollToNode
import androidx.core.net.toUri
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.data.platform.manager.util.AppResumeStateManager
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import com.x8bit.bitwarden.ui.util.assertNoDialogExists
import com.x8bit.bitwarden.ui.util.assertNoPopupExists
import com.x8bit.bitwarden.ui.util.isProgressBar
@ -51,6 +53,7 @@ class SendScreenTest : BaseComposeTest() {
private var onNavigateToSendTextListCalled = false
private var onNavigateToSendSearchCalled = false
private var onNavigateToEditSendId: String? = null
private var onNavigateToViewSendRoute: ViewSendRoute? = null
private val intentManager = mockk<IntentManager> {
every { launchUri(any()) } just runs
@ -74,6 +77,7 @@ class SendScreenTest : BaseComposeTest() {
viewModel = viewModel,
onNavigateToAddSend = { onNavigateToNewSendCalled = true },
onNavigateToEditSend = { onNavigateToEditSendId = it },
onNavigateToViewSend = { onNavigateToViewSendRoute = it },
onNavigateToSendFilesList = { onNavigateToSendFilesListCalled = true },
onNavigateToSendTextList = { onNavigateToSendTextListCalled = true },
onNavigateToSearchSend = { onNavigateToSendSearchCalled = true },
@ -94,6 +98,14 @@ class SendScreenTest : BaseComposeTest() {
assertEquals(sendId, onNavigateToEditSendId)
}
@Test
fun `on NavigateToViewSend should call onNavigateToViewSend`() {
val sendId = "sendId1234"
val sendType = SendItemType.TEXT
mutableEventFlow.tryEmit(SendEvent.NavigateToViewSend(sendId = sendId, sendType = sendType))
assertEquals(ViewSendRoute(sendId = sendId, sendType = sendType), onNavigateToViewSendRoute)
}
@Test
fun `on NavigateToFileSends should call onNavigateToSendFilesList`() {
mutableEventFlow.tryEmit(SendEvent.NavigateToFileSends)
@ -472,7 +484,7 @@ class SendScreenTest : BaseComposeTest() {
}
@Test
fun `on send item overflow dialog edit click should send SendClick`() {
fun `on send item overflow dialog edit click should send EditClick`() {
mutableStateFlow.update {
it.copy(
viewState = SendState.ViewState.Content(
@ -501,7 +513,7 @@ class SendScreenTest : BaseComposeTest() {
.performClick()
verify {
viewModel.trySendAction(SendAction.SendClick(DEFAULT_SEND_ITEM))
viewModel.trySendAction(SendAction.EditClick(DEFAULT_SEND_ITEM))
}
composeTestRule.assertNoDialogExists()

View File

@ -300,6 +300,20 @@ class SendViewModelTest : BaseViewModelTest() {
}
}
@Test
fun `EditClick should emit NavigateToEditSend`() = runTest {
val sendId = "sendId1234"
val sendItem = mockk<SendState.ViewState.Content.SendItem> {
every { id } returns sendId
}
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(SendAction.EditClick(sendItem = sendItem))
assertEquals(SendEvent.NavigateToEditSend(sendId = sendId), awaitItem())
}
}
@Test
fun `ShareClick should emit ShowShareSheet`() = runTest {
val viewModel = createViewModel()

View File

@ -36,6 +36,8 @@ import com.x8bit.bitwarden.ui.platform.feature.search.model.SearchType
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManager
import com.x8bit.bitwarden.ui.platform.manager.exit.ExitManager
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import com.x8bit.bitwarden.ui.util.assertLockOrLogoutDialogIsDisplayed
import com.x8bit.bitwarden.ui.util.assertLogoutConfirmationDialogIsDisplayed
import com.x8bit.bitwarden.ui.util.assertMasterPasswordDialogDisplayed
@ -85,6 +87,7 @@ class VaultItemListingScreenTest : BaseComposeTest() {
private var onNavigateToVaultAddItemScreenCalled = false
private var onNavigateToAddSendScreenCalled = false
private var onNavigateToEditSendItemId: String? = null
private var onNavigateToViewSendScreenRoute: ViewSendRoute? = null
private var onNavigateToVaultItemArgs: VaultItemArgs? = null
private var onNavigateToVaultEditItemScreenArgs: VaultAddEditArgs? = null
private var onNavigateToSearchType: SearchType? = null
@ -128,6 +131,7 @@ class VaultItemListingScreenTest : BaseComposeTest() {
onNavigateToVaultItemScreen = { onNavigateToVaultItemArgs = it },
onNavigateToVaultAddItemScreen = { onNavigateToVaultAddItemScreenCalled = true },
onNavigateToAddSendItem = { onNavigateToAddSendScreenCalled = true },
onNavigateToViewSendItem = { onNavigateToViewSendScreenRoute = it },
onNavigateToEditSendItem = { onNavigateToEditSendItemId = it },
onNavigateToSearch = { onNavigateToSearchType = it },
onNavigateToVaultEditItemScreen = { onNavigateToVaultEditItemScreenArgs = it },
@ -479,6 +483,19 @@ class VaultItemListingScreenTest : BaseComposeTest() {
assertTrue(onNavigateToAddSendScreenCalled)
}
@Test
fun `NavigateToViewSendItem should call onNavigateToViewSendScreen`() {
val sendId = "id"
val sendType = SendItemType.TEXT
mutableEventFlow.tryEmit(
VaultItemListingEvent.NavigateToViewSendItem(id = sendId, sendType = sendType),
)
assertEquals(
ViewSendRoute(sendId = sendId, sendType = sendType),
onNavigateToViewSendScreenRoute,
)
}
@Test
fun `NavigateToVaultSearchScreen should call onNavigateToSearch`() {
val searchType = SearchType.Vault.SecureNotes
@ -503,9 +520,9 @@ class VaultItemListingScreenTest : BaseComposeTest() {
}
@Test
fun `NavigateToSendItem event should call onNavigateToEditSendItemId`() {
fun `NavigateToEditSendItem event should call onNavigateToEditSendItemId`() {
val sendId = "sendId"
mutableEventFlow.tryEmit(VaultItemListingEvent.NavigateToSendItem(sendId))
mutableEventFlow.tryEmit(VaultItemListingEvent.NavigateToEditSendItem(id = sendId))
assertEquals(sendId, onNavigateToEditSendItemId)
}

View File

@ -281,7 +281,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = createCredentialRequest,
)
)
every {
ProviderCreateCredentialRequest.fromBundle(any())
} returns mockk(relaxed = true) {
@ -595,7 +595,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = createMockCreateCredentialRequest(number = 1),
)
)
mutableVaultDataStateFlow.value = DataState.Loaded(
data = VaultData(
cipherViewList = listOf(),
@ -634,7 +634,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = createMockCreateCredentialRequest(number = 1),
)
)
mutableVaultDataStateFlow.value = DataState.Loaded(
data = VaultData(
cipherViewList = listOf(cipherView),
@ -691,7 +691,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = createMockCreateCredentialRequest(number = 1),
)
)
mutableVaultDataStateFlow.value = DataState.Loaded(
data = VaultData(
cipherViewList = listOf(cipherView),
@ -760,7 +760,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = mockFido2CredentialRequest,
)
)
mutableVaultDataStateFlow.value = DataState.Loaded(
data = VaultData(
cipherViewList = listOf(cipherView),
@ -823,7 +823,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = mockFido2CredentialRequest,
)
)
mutableVaultDataStateFlow.value = DataState.Loaded(
data = VaultData(
cipherViewList = listOf(cipherView),
@ -892,7 +892,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
}
@Test
fun `ItemClick for send item should emit NavigateToSendItem`() = runTest {
fun `ItemClick for send item should emit NavigateToEditSendItem`() = runTest {
val viewModel = createVaultItemListingViewModel(
createSavedStateHandleWithVaultItemListingType(VaultItemListingType.SendFile),
)
@ -900,7 +900,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
viewModel.trySendAction(
VaultItemListingsAction.ItemClick(id = "mock", cipherType = null),
)
assertEquals(VaultItemListingEvent.NavigateToSendItem(id = "mock"), awaitItem())
assertEquals(VaultItemListingEvent.NavigateToEditSendItem(id = "mock"), awaitItem())
}
}
@ -1293,7 +1293,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
}
@Test
fun `OverflowOptionClick Send EditClick should emit NavigateToSendItem`() = runTest {
fun `OverflowOptionClick Send EditClick should emit NavigateToEditSendItem`() = runTest {
val sendId = "sendId"
val viewModel = createVaultItemListingViewModel()
viewModel.eventFlow.test {
@ -1302,7 +1302,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
ListingItemOverflowAction.SendAction.EditClick(sendId = sendId),
),
)
assertEquals(VaultItemListingEvent.NavigateToSendItem(sendId), awaitItem())
assertEquals(VaultItemListingEvent.NavigateToEditSendItem(id = sendId), awaitItem())
}
}
@ -2663,7 +2663,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = providerCreateCredentialRequest,
)
)
every {
ProviderCreateCredentialRequest.fromBundle(any())
@ -2703,7 +2703,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = providerCreateCredentialRequest,
)
)
every {
ProviderCreateCredentialRequest.fromBundle(any())
@ -2743,7 +2743,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = providerCreateCredentialRequest,
)
)
every {
ProviderCreateCredentialRequest.fromBundle(any())
@ -2783,7 +2783,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = providerCreateCredentialRequest,
)
)
every {
ProviderCreateCredentialRequest.fromBundle(any())
@ -2878,8 +2878,8 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
runTest {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createMockCreateCredentialRequest(number = 1),
)
createMockCreateCredentialRequest(number = 1),
)
val viewModel = createVaultItemListingViewModel()
viewModel.trySendAction(
VaultItemListingsAction.DismissCredentialManagerErrorDialogClick(
@ -3699,8 +3699,8 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
runTest {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createMockCreateCredentialRequest(number = 1),
)
createMockCreateCredentialRequest(number = 1),
)
val viewModel = createVaultItemListingViewModel()
viewModel.trySendAction(VaultItemListingsAction.UserVerificationCancelled)
@ -3863,7 +3863,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = mockRequest,
)
)
every {
ProviderCreateCredentialRequest.fromBundle(any())
} returns mockk(relaxed = true) {
@ -4573,7 +4573,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = createMockCreateCredentialRequest(number = 1),
)
)
mutableVaultDataStateFlow.value = DataState.Loaded(
data = VaultData(
cipherViewList = listOf(cipherView),