Rename AddSend UI to AddEditSend (#5221)

This commit is contained in:
David Perez
2025-05-19 16:26:31 -05:00
committed by GitHub
parent 6719534494
commit fc4f02c4d5
35 changed files with 581 additions and 553 deletions

View File

@@ -56,9 +56,9 @@ import com.x8bit.bitwarden.ui.platform.feature.splash.splashDestination
import com.x8bit.bitwarden.ui.platform.feature.vaultunlocked.VaultUnlockedGraphRoute
import com.x8bit.bitwarden.ui.platform.feature.vaultunlocked.navigateToVaultUnlockedGraph
import com.x8bit.bitwarden.ui.platform.feature.vaultunlocked.vaultUnlockedGraph
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.navigateToAddSend
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.navigateToAddEditSend
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditArgs
import com.x8bit.bitwarden.ui.vault.feature.addedit.navigateToVaultAddEdit
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.navigateToVaultItemListingAsRoot
@@ -202,7 +202,7 @@ fun RootNavScreen(
is RootNavState.VaultUnlockedForNewSend -> {
navController.navigateToVaultUnlock(rootNavOptions)
navController.navigateToAddSend(
navController.navigateToAddEditSend(
route = AddEditSendRoute(
sendType = currentState.sendType,
modeType = ModeType.ADD,

View File

@@ -7,7 +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.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
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

View File

@@ -35,8 +35,8 @@ 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.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.ModeType
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

View File

@@ -36,8 +36,8 @@ import com.x8bit.bitwarden.ui.tools.feature.generator.model.GeneratorPasswordHis
import com.x8bit.bitwarden.ui.tools.feature.generator.navigateToGeneratorModal
import com.x8bit.bitwarden.ui.tools.feature.generator.passwordhistory.navigateToPasswordHistory
import com.x8bit.bitwarden.ui.tools.feature.generator.passwordhistory.passwordHistoryDestination
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.addSendDestination
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.navigateToAddSend
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.addEditSendDestination
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.navigateToAddEditSend
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
@@ -101,7 +101,7 @@ fun NavGraphBuilder.vaultUnlockedGraph(
onNavigateToVaultEditItem = { navController.navigateToVaultAddEdit(it) },
onNavigateToSearchVault = { navController.navigateToSearch(searchType = it) },
onNavigateToSearchSend = { navController.navigateToSearch(searchType = it) },
onNavigateToAddEditSend = { navController.navigateToAddSend(it) },
onNavigateToAddEditSend = { navController.navigateToAddEditSend(it) },
onNavigateToViewSend = { navController.navigateToViewSend(route = it) },
onNavigateToDeleteAccount = { navController.navigateToDeleteAccount() },
onNavigateToPendingRequests = { navController.navigateToPendingRequests() },
@@ -199,13 +199,13 @@ fun NavGraphBuilder.vaultUnlockedGraph(
onNavigateBack = { navController.popBackStack() },
)
addSendDestination(
addEditSendDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateUpToRoot = { navController.navigateToVaultUnlockedRoot() },
)
viewSendDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToAddEditSend = { navController.navigateToAddSend(it) },
onNavigateToAddEditSend = { navController.navigateToAddEditSend(it) },
)
passwordHistoryDestination(onNavigateBack = { navController.popBackStack() })
exportVaultDestination(onNavigateBack = { navController.popBackStack() })
@@ -225,7 +225,7 @@ fun NavGraphBuilder.vaultUnlockedGraph(
generatorModalDestination(onNavigateBack = { navController.popBackStack() })
searchDestination(
onNavigateBack = { navController.popBackStack() },
onNavigateToAddEditSend = { navController.navigateToAddSend(it) },
onNavigateToAddEditSend = { navController.navigateToAddEditSend(it) },
onNavigateToViewSend = { navController.navigateToViewSend(it) },
onNavigateToEditCipher = { navController.navigateToVaultAddEdit(it) },
onNavigateToViewCipher = { navController.navigateToVaultItem(it) },

View File

@@ -6,7 +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.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
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

View File

@@ -34,7 +34,7 @@ import com.x8bit.bitwarden.ui.platform.feature.vaultunlockednavbar.model.VaultUn
import com.x8bit.bitwarden.ui.platform.manager.snackbar.SnackbarRelay
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.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
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

View File

@@ -5,7 +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.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
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

View File

@@ -5,7 +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.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.viewsend.ViewSendRoute
import kotlinx.serialization.Serializable

View File

@@ -42,8 +42,8 @@ import com.x8bit.bitwarden.ui.platform.composition.LocalAppResumeStateManager
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.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.handlers.SendHandlers
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.tools.feature.send.util.selectionText

View File

@@ -1,4 +1,4 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend
package com.x8bit.bitwarden.ui.tools.feature.send.addedit
import android.Manifest
import androidx.compose.animation.AnimatedVisibility
@@ -51,20 +51,20 @@ 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.tools.feature.send.addsend.handlers.AddSendHandlers
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.handlers.AddEditSendHandlers
/**
* Content view for the [AddSendScreen].
* Content view for the [AddEditSendScreen].
*/
@Suppress("LongMethod")
@Composable
fun AddSendContent(
state: AddSendState.ViewState.Content,
fun AddEditSendContent(
state: AddEditSendState.ViewState.Content,
policyDisablesSend: Boolean,
policySendOptionsInEffect: Boolean,
isAddMode: Boolean,
isShared: Boolean,
addSendHandlers: AddSendHandlers,
addSendHandlers: AddEditSendHandlers,
permissionsManager: PermissionsManager,
modifier: Modifier = Modifier,
) {
@@ -115,7 +115,7 @@ fun AddSendContent(
)
when (val type = state.selectedType) {
is AddSendState.ViewState.Content.SendType.File -> {
is AddEditSendState.ViewState.Content.SendType.File -> {
FileTypeContent(
fileType = type,
addSendHandlers = addSendHandlers,
@@ -125,7 +125,7 @@ fun AddSendContent(
)
}
is AddSendState.ViewState.Content.SendType.Text -> {
is AddEditSendState.ViewState.Content.SendType.Text -> {
TextTypeContent(
textType = type,
addSendHandlers = addSendHandlers,
@@ -137,7 +137,7 @@ fun AddSendContent(
Spacer(modifier = Modifier.height(height = 8.dp))
if (isAddMode) {
SendDeletionDateChooser(
AddEditSendDeletionDateChooser(
modifier = Modifier
.testTag("SendDeletionOptionsPicker")
.fillMaxWidth()
@@ -156,7 +156,7 @@ fun AddSendContent(
.defaultMinSize(minHeight = 60.dp)
.cardStyle(cardStyle = CardStyle.Full, paddingVertical = 0.dp),
) {
AddSendCustomDateChooser(
AddEditSendCustomDateChooser(
modifier = Modifier
.testTag("SendCustomDeletionDatePicker")
.fillMaxWidth(),
@@ -182,7 +182,7 @@ fun AddSendContent(
}
}
AddSendOptions(
AddEditSendOptions(
state = state,
sendRestrictionPolicy = policyDisablesSend,
isAddMode = isAddMode,
@@ -233,8 +233,8 @@ private fun DeleteButton(
@Composable
private fun ColumnScope.TextTypeContent(
textType: AddSendState.ViewState.Content.SendType.Text,
addSendHandlers: AddSendHandlers,
textType: AddEditSendState.ViewState.Content.SendType.Text,
addSendHandlers: AddEditSendHandlers,
policyDisablesSend: Boolean,
) {
Spacer(modifier = Modifier.height(height = 8.dp))
@@ -267,8 +267,8 @@ private fun ColumnScope.TextTypeContent(
@Suppress("LongMethod")
@Composable
private fun ColumnScope.FileTypeContent(
fileType: AddSendState.ViewState.Content.SendType.File,
addSendHandlers: AddSendHandlers,
fileType: AddEditSendState.ViewState.Content.SendType.File,
addSendHandlers: AddEditSendHandlers,
permissionsManager: PermissionsManager,
isAddMode: Boolean,
isShared: Boolean,
@@ -383,11 +383,11 @@ private fun ColumnScope.FileTypeContent(
*/
@Suppress("LongMethod")
@Composable
private fun AddSendOptions(
state: AddSendState.ViewState.Content,
private fun AddEditSendOptions(
state: AddEditSendState.ViewState.Content,
sendRestrictionPolicy: Boolean,
isAddMode: Boolean,
addSendHandlers: AddSendHandlers,
addSendHandlers: AddEditSendHandlers,
) {
var isExpanded by rememberSaveable { mutableStateOf(false) }
BitwardenExpandingHeader(

View File

@@ -1,4 +1,4 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend
package com.x8bit.bitwarden.ui.tools.feature.send.addedit
import androidx.compose.foundation.layout.Row
import androidx.compose.runtime.Composable
@@ -31,7 +31,7 @@ import kotlin.time.Duration.Companion.minutes
* @param modifier A [Modifier] that you can use to apply custom modifications to the composable.
*/
@Composable
fun AddSendCustomDateChooser(
fun AddEditSendCustomDateChooser(
dateLabel: String,
timeLabel: String,
currentZonedDateTime: ZonedDateTime?,

View File

@@ -1,4 +1,4 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend
package com.x8bit.bitwarden.ui.tools.feature.send.addedit
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Column
@@ -36,7 +36,7 @@ import kotlin.time.Duration.Companion.hours
*/
@Suppress("LongMethod")
@Composable
fun SendDeletionDateChooser(
fun AddEditSendDeletionDateChooser(
currentZonedDateTime: ZonedDateTime,
dateFormatPattern: String,
timeFormatPattern: String,
@@ -72,7 +72,7 @@ fun SendDeletionDateChooser(
AnimatedVisibility(visible = selectedOption == DeletionOptions.CUSTOM) {
Column {
BitwardenHorizontalDivider(modifier = Modifier.padding(start = 16.dp))
AddSendCustomDateChooser(
AddEditSendCustomDateChooser(
dateLabel = stringResource(id = R.string.deletion_date),
timeLabel = stringResource(id = R.string.deletion_time),
currentZonedDateTime = currentZonedDateTime,

View File

@@ -1,4 +1,4 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend
package com.x8bit.bitwarden.ui.tools.feature.send.addedit
import androidx.lifecycle.SavedStateHandle
import androidx.navigation.NavController
@@ -6,7 +6,7 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.toRoute
import com.bitwarden.ui.platform.base.util.composableWithSlideTransitions
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.model.AddSendType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.model.AddEditSendType
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import kotlinx.serialization.Serializable
@@ -32,34 +32,34 @@ enum class ModeType {
/**
* Class to retrieve send add & edit arguments from the [SavedStateHandle].
*/
data class AddSendArgs(
data class AddEditSendArgs(
val sendType: SendItemType,
val sendAddType: AddSendType,
val addEditSendType: AddEditSendType,
)
/**
* Constructs a [AddSendArgs] from the [SavedStateHandle] and internal route data.
* Constructs a [AddEditSendArgs] from the [SavedStateHandle] and internal route data.
*/
fun SavedStateHandle.toAddSendArgs(): AddSendArgs {
fun SavedStateHandle.toAddEditSendArgs(): AddEditSendArgs {
val route = this.toRoute<AddEditSendRoute>()
return AddSendArgs(
return AddEditSendArgs(
sendType = route.sendType,
sendAddType = when (route.modeType) {
ModeType.ADD -> AddSendType.AddItem
ModeType.EDIT -> AddSendType.EditItem(sendItemId = requireNotNull(route.sendId))
addEditSendType = when (route.modeType) {
ModeType.ADD -> AddEditSendType.AddItem
ModeType.EDIT -> AddEditSendType.EditItem(sendItemId = requireNotNull(route.sendId))
},
)
}
/**
* Add the new send screen to the nav graph.
* Add the add/edit send screen to the nav graph.
*/
fun NavGraphBuilder.addSendDestination(
fun NavGraphBuilder.addEditSendDestination(
onNavigateBack: () -> Unit,
onNavigateUpToRoot: () -> Unit,
) {
composableWithSlideTransitions<AddEditSendRoute> {
AddSendScreen(
AddEditSendScreen(
onNavigateBack = onNavigateBack,
onNavigateUpToRoot = onNavigateUpToRoot,
)
@@ -67,9 +67,9 @@ fun NavGraphBuilder.addSendDestination(
}
/**
* Navigate to the new send screen.
* Navigate to the add/edit send screen.
*/
fun NavController.navigateToAddSend(
fun NavController.navigateToAddEditSend(
route: AddEditSendRoute,
navOptions: NavOptions? = null,
) {

View File

@@ -1,4 +1,4 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend
package com.x8bit.bitwarden.ui.tools.feature.send.addedit
import android.widget.Toast
import androidx.activity.compose.BackHandler
@@ -37,7 +37,7 @@ import com.x8bit.bitwarden.ui.platform.manager.exit.ExitManager
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 com.x8bit.bitwarden.ui.tools.feature.send.addedit.handlers.AddEditSendHandlers
/**
* Displays new send UX.
@@ -45,8 +45,8 @@ import com.x8bit.bitwarden.ui.tools.feature.send.addsend.handlers.AddSendHandler
@Suppress("LongMethod", "CyclomaticComplexMethod")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AddSendScreen(
viewModel: AddSendViewModel = hiltViewModel(),
fun AddEditSendScreen(
viewModel: AddEditSendViewModel = hiltViewModel(),
exitManager: ExitManager = LocalExitManager.current,
intentManager: IntentManager = LocalIntentManager.current,
permissionsManager: PermissionsManager = LocalPermissionsManager.current,
@@ -54,7 +54,7 @@ fun AddSendScreen(
onNavigateUpToRoot: () -> Unit,
) {
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
val addSendHandlers = remember(viewModel) { AddSendHandlers.create(viewModel) }
val addSendHandlers = remember(viewModel) { AddEditSendHandlers.create(viewModel) }
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val context = LocalContext.current
val resources = context.resources
@@ -67,37 +67,37 @@ fun AddSendScreen(
BackHandler(
onBack = remember(viewModel) {
{ viewModel.trySendAction(AddSendAction.CloseClick) }
{ viewModel.trySendAction(AddEditSendAction.CloseClick) }
},
)
EventsEffect(viewModel = viewModel) { event ->
when (event) {
AddSendEvent.ExitApp -> exitManager.exitApplication()
AddEditSendEvent.ExitApp -> exitManager.exitApplication()
is AddSendEvent.NavigateBack -> onNavigateBack()
is AddEditSendEvent.NavigateBack -> onNavigateBack()
is AddSendEvent.NavigateToRoot -> onNavigateUpToRoot()
is AddEditSendEvent.NavigateToRoot -> onNavigateUpToRoot()
is AddSendEvent.ShowChooserSheet -> {
is AddEditSendEvent.ShowChooserSheet -> {
fileChooserLauncher.launch(
intentManager.createFileChooserIntent(event.withCameraOption),
)
}
is AddSendEvent.ShowShareSheet -> {
is AddEditSendEvent.ShowShareSheet -> {
intentManager.shareText(event.message)
}
is AddSendEvent.ShowToast -> {
is AddEditSendEvent.ShowToast -> {
Toast.makeText(context, event.message(resources), Toast.LENGTH_SHORT).show()
}
}
}
AddSendDialogs(
AddEditSendDialogs(
dialogState = state.dialogState,
onDismissRequest = remember(viewModel) {
{ viewModel.trySendAction(AddSendAction.DismissDialogClick) }
{ viewModel.trySendAction(AddEditSendAction.DismissDialogClick) }
},
)
BitwardenScaffold(
@@ -111,7 +111,7 @@ fun AddSendScreen(
navigationIcon = rememberVectorPainter(id = R.drawable.ic_close),
navigationIconContentDescription = stringResource(id = R.string.close),
onNavigationIconClick = remember(viewModel) {
{ viewModel.trySendAction(AddSendAction.CloseClick) }
{ viewModel.trySendAction(AddEditSendAction.CloseClick) }
},
)
.takeUnless { state.isShared },
@@ -122,7 +122,7 @@ fun AddSendScreen(
label = stringResource(id = R.string.save),
isEnabled = !state.policyDisablesSend,
onClick = remember(viewModel) {
{ viewModel.trySendAction(AddSendAction.SaveClick) }
{ viewModel.trySendAction(AddEditSendAction.SaveClick) }
},
modifier = Modifier.testTag("SaveButton"),
)
@@ -134,7 +134,7 @@ fun AddSendScreen(
onClick = remember(viewModel) {
{
viewModel.trySendAction(
AddSendAction.RemovePasswordClick,
AddEditSendAction.RemovePasswordClick,
)
}
},
@@ -143,14 +143,18 @@ fun AddSendScreen(
OverflowMenuItemData(
text = stringResource(id = R.string.copy_link),
onClick = remember(viewModel) {
{ viewModel.trySendAction(AddSendAction.CopyLinkClick) }
{ viewModel.trySendAction(AddEditSendAction.CopyLinkClick) }
},
)
.takeIf { !state.policyDisablesSend },
OverflowMenuItemData(
text = stringResource(id = R.string.share_link),
onClick = remember(viewModel) {
{ viewModel.trySendAction(AddSendAction.ShareLinkClick) }
{
viewModel.trySendAction(
AddEditSendAction.ShareLinkClick,
)
}
},
)
.takeIf { !state.policyDisablesSend },
@@ -165,7 +169,7 @@ fun AddSendScreen(
.fillMaxSize()
when (val viewState = state.viewState) {
is AddSendState.ViewState.Content -> AddSendContent(
is AddEditSendState.ViewState.Content -> AddEditSendContent(
state = viewState,
policyDisablesSend = state.policyDisablesSend,
policySendOptionsInEffect = state.shouldDisplayPolicyWarning,
@@ -176,12 +180,12 @@ fun AddSendScreen(
modifier = modifier,
)
is AddSendState.ViewState.Error -> BitwardenErrorContent(
is AddEditSendState.ViewState.Error -> BitwardenErrorContent(
message = viewState.message(),
modifier = modifier,
)
AddSendState.ViewState.Loading -> BitwardenLoadingContent(
AddEditSendState.ViewState.Loading -> BitwardenLoadingContent(
modifier = modifier,
)
}
@@ -189,19 +193,19 @@ fun AddSendScreen(
}
@Composable
private fun AddSendDialogs(
dialogState: AddSendState.DialogState?,
private fun AddEditSendDialogs(
dialogState: AddEditSendState.DialogState?,
onDismissRequest: () -> Unit,
) {
when (dialogState) {
is AddSendState.DialogState.Error -> BitwardenBasicDialog(
is AddEditSendState.DialogState.Error -> BitwardenBasicDialog(
title = dialogState.title?.invoke(),
message = dialogState.message(),
onDismissRequest = onDismissRequest,
throwable = dialogState.throwable,
)
is AddSendState.DialogState.Loading -> BitwardenLoadingDialog(
is AddEditSendState.DialogState.Loading -> BitwardenLoadingDialog(
text = dialogState.message(),
)

View File

@@ -1,4 +1,4 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend
package com.x8bit.bitwarden.ui.tools.feature.send.addedit
import android.net.Uri
import android.os.Parcelable
@@ -28,12 +28,12 @@ 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.UpdateSendResult
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.model.AddSendType
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.util.shouldFinishOnComplete
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.util.toSendName
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.util.toSendType
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.util.toSendView
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.util.toViewState
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.model.AddEditSendType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.util.shouldFinishOnComplete
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.util.toSendName
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.util.toSendType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.util.toSendView
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.util.toViewState
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.tools.feature.send.util.toSendUrl
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -57,11 +57,11 @@ private const val KEY_STATE = "state"
private const val MAX_FILE_SIZE_BYTES: Long = 100 * 1024 * 1024
/**
* View model for the new send screen.
* View model for the add/edit send screen.
*/
@Suppress("TooManyFunctions", "LongParameterList")
@HiltViewModel
class AddSendViewModel @Inject constructor(
class AddEditSendViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val clock: Clock,
private val clipboardManager: BitwardenClipboardManager,
@@ -70,23 +70,23 @@ class AddSendViewModel @Inject constructor(
private val vaultRepo: VaultRepository,
private val policyManager: PolicyManager,
private val networkConnectionManager: NetworkConnectionManager,
) : BaseViewModel<AddSendState, AddSendEvent, AddSendAction>(
) : BaseViewModel<AddEditSendState, AddEditSendEvent, AddEditSendAction>(
// We load the state from the savedStateHandle for testing purposes.
initialState = savedStateHandle[KEY_STATE] ?: run {
// Check to see if we are navigating here from an external source
val specialCircumstance = specialCircumstanceManager.specialCircumstance
val shareSendType = specialCircumstance.toSendType()
val args = savedStateHandle.toAddSendArgs()
val args = savedStateHandle.toAddEditSendArgs()
val sendType = args.sendType
val sendAddType = args.sendAddType
AddSendState(
val addEditSendType = args.addEditSendType
AddEditSendState(
sendType = sendType,
shouldFinishOnComplete = specialCircumstance.shouldFinishOnComplete(),
isShared = shareSendType != null,
addSendType = sendAddType,
viewState = when (sendAddType) {
AddSendType.AddItem -> AddSendState.ViewState.Content(
common = AddSendState.ViewState.Content.Common(
addEditSendType = addEditSendType,
viewState = when (addEditSendType) {
AddEditSendType.AddItem -> AddEditSendState.ViewState.Content(
common = AddEditSendState.ViewState.Content.Common(
name = specialCircumstance.toSendName().orEmpty(),
currentAccessCount = null,
maxAccessCount = null,
@@ -109,7 +109,7 @@ class AddSendViewModel @Inject constructor(
),
selectedType = shareSendType ?: when (sendType) {
SendItemType.FILE -> {
AddSendState.ViewState.Content.SendType.File(
AddEditSendState.ViewState.Content.SendType.File(
uri = null,
name = null,
displaySize = null,
@@ -118,7 +118,7 @@ class AddSendViewModel @Inject constructor(
}
SendItemType.TEXT -> {
AddSendState.ViewState.Content.SendType.Text(
AddEditSendState.ViewState.Content.SendType.Text(
input = "",
isHideByDefaultChecked = false,
)
@@ -126,7 +126,7 @@ class AddSendViewModel @Inject constructor(
},
)
is AddSendType.EditItem -> AddSendState.ViewState.Loading
is AddEditSendType.EditItem -> AddEditSendState.ViewState.Loading
},
dialogState = null,
baseWebSendUrl = environmentRepo.environment.environmentUrlData.baseWebSendUrl,
@@ -138,61 +138,70 @@ class AddSendViewModel @Inject constructor(
) {
init {
when (val addSendType = state.addSendType) {
AddSendType.AddItem -> Unit
is AddSendType.EditItem -> {
when (val addSendType = state.addEditSendType) {
AddEditSendType.AddItem -> Unit
is AddEditSendType.EditItem -> {
vaultRepo
.getSendStateFlow(addSendType.sendItemId)
// We'll stop getting updates as soon as we get some loaded data.
.takeUntilLoaded()
.map { AddSendAction.Internal.SendDataReceive(it) }
.map { AddEditSendAction.Internal.SendDataReceive(it) }
.onEach(::sendAction)
.launchIn(viewModelScope)
}
}
}
override fun handleAction(action: AddSendAction): Unit = when (action) {
AddSendAction.CopyLinkClick -> handleCopyLinkClick()
AddSendAction.DeleteClick -> handleDeleteClick()
is AddSendAction.FileChoose -> handeFileChose(action)
AddSendAction.RemovePasswordClick -> handleRemovePasswordClick()
AddSendAction.ShareLinkClick -> handleShareLinkClick()
is AddSendAction.CloseClick -> handleCloseClick()
is AddSendAction.DeletionDateChange -> handleDeletionDateChange(action)
AddSendAction.DismissDialogClick -> handleDismissDialogClick()
is AddSendAction.SaveClick -> handleSaveClick()
is AddSendAction.ChooseFileClick -> handleChooseFileClick(action)
is AddSendAction.NameChange -> handleNameChange(action)
is AddSendAction.MaxAccessCountChange -> handleMaxAccessCountChange(action)
is AddSendAction.TextChange -> handleTextChange(action)
is AddSendAction.NoteChange -> handleNoteChange(action)
is AddSendAction.PasswordChange -> handlePasswordChange(action)
is AddSendAction.HideByDefaultToggle -> handleHideByDefaultToggle(action)
is AddSendAction.DeactivateThisSendToggle -> handleDeactivateThisSendToggle(action)
is AddSendAction.HideMyEmailToggle -> handleHideMyEmailToggle(action)
is AddSendAction.Internal -> handleInternalAction(action)
override fun handleAction(action: AddEditSendAction): Unit = when (action) {
AddEditSendAction.CopyLinkClick -> handleCopyLinkClick()
AddEditSendAction.DeleteClick -> handleDeleteClick()
is AddEditSendAction.FileChoose -> handeFileChose(action)
AddEditSendAction.RemovePasswordClick -> handleRemovePasswordClick()
AddEditSendAction.ShareLinkClick -> handleShareLinkClick()
is AddEditSendAction.CloseClick -> handleCloseClick()
is AddEditSendAction.DeletionDateChange -> handleDeletionDateChange(action)
AddEditSendAction.DismissDialogClick -> handleDismissDialogClick()
is AddEditSendAction.SaveClick -> handleSaveClick()
is AddEditSendAction.ChooseFileClick -> handleChooseFileClick(action)
is AddEditSendAction.NameChange -> handleNameChange(action)
is AddEditSendAction.MaxAccessCountChange -> handleMaxAccessCountChange(action)
is AddEditSendAction.TextChange -> handleTextChange(action)
is AddEditSendAction.NoteChange -> handleNoteChange(action)
is AddEditSendAction.PasswordChange -> handlePasswordChange(action)
is AddEditSendAction.HideByDefaultToggle -> handleHideByDefaultToggle(action)
is AddEditSendAction.DeactivateThisSendToggle -> handleDeactivateThisSendToggle(action)
is AddEditSendAction.HideMyEmailToggle -> handleHideMyEmailToggle(action)
is AddEditSendAction.Internal -> handleInternalAction(action)
}
private fun handleInternalAction(action: AddSendAction.Internal): Unit = when (action) {
is AddSendAction.Internal.CreateSendResultReceive -> handleCreateSendResultReceive(action)
is AddSendAction.Internal.UpdateSendResultReceive -> handleUpdateSendResultReceive(action)
is AddSendAction.Internal.DeleteSendResultReceive -> handleDeleteSendResultReceive(action)
is AddSendAction.Internal.RemovePasswordResultReceive -> handleRemovePasswordResultReceive(
action,
)
private fun handleInternalAction(action: AddEditSendAction.Internal): Unit = when (action) {
is AddEditSendAction.Internal.CreateSendResultReceive -> {
handleCreateSendResultReceive(action)
}
is AddSendAction.Internal.SendDataReceive -> handleSendDataReceive(action)
is AddEditSendAction.Internal.UpdateSendResultReceive -> {
handleUpdateSendResultReceive(action)
}
is AddEditSendAction.Internal.DeleteSendResultReceive -> {
handleDeleteSendResultReceive(action)
}
is AddEditSendAction.Internal.RemovePasswordResultReceive -> {
handleRemovePasswordResultReceive(action)
}
is AddEditSendAction.Internal.SendDataReceive -> handleSendDataReceive(action)
}
private fun handleCreateSendResultReceive(
action: AddSendAction.Internal.CreateSendResultReceive,
action: AddEditSendAction.Internal.CreateSendResultReceive,
) {
when (val result = action.result) {
is CreateSendResult.Error -> {
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = result.message?.asText()
?: R.string.generic_error_message.asText(),
@@ -206,7 +215,7 @@ class AddSendViewModel @Inject constructor(
mutableStateFlow.update { it.copy(dialogState = null) }
navigateBack()
sendEvent(
AddSendEvent.ShowShareSheet(
AddEditSendEvent.ShowShareSheet(
message = result.sendView.toSendUrl(state.baseWebSendUrl),
),
)
@@ -215,13 +224,13 @@ class AddSendViewModel @Inject constructor(
}
private fun handleUpdateSendResultReceive(
action: AddSendAction.Internal.UpdateSendResultReceive,
action: AddEditSendAction.Internal.UpdateSendResultReceive,
) {
when (val result = action.result) {
is UpdateSendResult.Error -> {
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = result
.errorMessage
@@ -237,7 +246,7 @@ class AddSendViewModel @Inject constructor(
mutableStateFlow.update { it.copy(dialogState = null) }
navigateBack()
sendEvent(
AddSendEvent.ShowShareSheet(
AddEditSendEvent.ShowShareSheet(
message = result.sendView.toSendUrl(state.baseWebSendUrl),
),
)
@@ -246,13 +255,13 @@ class AddSendViewModel @Inject constructor(
}
private fun handleDeleteSendResultReceive(
action: AddSendAction.Internal.DeleteSendResultReceive,
action: AddEditSendAction.Internal.DeleteSendResultReceive,
) {
when (val result = action.result) {
is DeleteSendResult.Error -> {
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.generic_error_message.asText(),
throwable = result.error,
@@ -264,19 +273,19 @@ class AddSendViewModel @Inject constructor(
is DeleteSendResult.Success -> {
mutableStateFlow.update { it.copy(dialogState = null) }
navigateBack(isDeleted = true)
sendEvent(AddSendEvent.ShowToast(message = R.string.send_deleted.asText()))
sendEvent(AddEditSendEvent.ShowToast(message = R.string.send_deleted.asText()))
}
}
}
private fun handleRemovePasswordResultReceive(
action: AddSendAction.Internal.RemovePasswordResultReceive,
action: AddEditSendAction.Internal.RemovePasswordResultReceive,
) {
when (val result = action.result) {
is RemovePasswordSendResult.Error -> {
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = result
.errorMessage
@@ -291,18 +300,20 @@ class AddSendViewModel @Inject constructor(
is RemovePasswordSendResult.Success -> {
updateCommonContent { it.copy(hasPassword = false) }
mutableStateFlow.update { it.copy(dialogState = null) }
sendEvent(AddSendEvent.ShowToast(message = R.string.send_password_removed.asText()))
sendEvent(
AddEditSendEvent.ShowToast(message = R.string.send_password_removed.asText()),
)
}
}
}
@Suppress("LongMethod")
private fun handleSendDataReceive(action: AddSendAction.Internal.SendDataReceive) {
private fun handleSendDataReceive(action: AddEditSendAction.Internal.SendDataReceive) {
when (val sendDataState = action.sendDataState) {
is DataState.Error -> {
mutableStateFlow.update {
it.copy(
viewState = AddSendState.ViewState.Error(
viewState = AddEditSendState.ViewState.Error(
message = R.string.generic_error_message.asText(),
),
)
@@ -322,7 +333,7 @@ class AddSendViewModel @Inject constructor(
.baseWebSendUrl,
isHideEmailAddressEnabled = isHideEmailAddressEnabled,
)
?: AddSendState.ViewState.Error(
?: AddEditSendState.ViewState.Error(
message = R.string.generic_error_message.asText(),
),
)
@@ -331,14 +342,14 @@ class AddSendViewModel @Inject constructor(
DataState.Loading -> {
mutableStateFlow.update {
it.copy(viewState = AddSendState.ViewState.Loading)
it.copy(viewState = AddEditSendState.ViewState.Loading)
}
}
is DataState.NoNetwork -> {
mutableStateFlow.update {
it.copy(
viewState = AddSendState.ViewState.Error(
viewState = AddEditSendState.ViewState.Error(
message = R.string.internet_connection_required_title
.asText()
.concat(
@@ -363,7 +374,7 @@ class AddSendViewModel @Inject constructor(
.baseWebSendUrl,
isHideEmailAddressEnabled = isHideEmailAddressEnabled,
)
?: AddSendState.ViewState.Error(
?: AddEditSendState.ViewState.Error(
message = R.string.generic_error_message.asText(),
),
)
@@ -386,16 +397,18 @@ class AddSendViewModel @Inject constructor(
private fun handleDeleteClick() {
onEdit {
mutableStateFlow.update {
it.copy(dialogState = AddSendState.DialogState.Loading(R.string.deleting.asText()))
it.copy(
dialogState = AddEditSendState.DialogState.Loading(R.string.deleting.asText()),
)
}
viewModelScope.launch {
val result = vaultRepo.deleteSend(it.sendItemId)
sendAction(AddSendAction.Internal.DeleteSendResultReceive(result))
sendAction(AddEditSendAction.Internal.DeleteSendResultReceive(result))
}
}
}
private fun handeFileChose(action: AddSendAction.FileChoose) {
private fun handeFileChose(action: AddEditSendAction.FileChoose) {
updateFileContent {
it.copy(
uri = action.fileData.uri,
@@ -409,14 +422,14 @@ class AddSendViewModel @Inject constructor(
onEdit {
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Loading(
dialogState = AddEditSendState.DialogState.Loading(
message = R.string.removing_send_password.asText(),
),
)
}
viewModelScope.launch {
val result = vaultRepo.removePasswordSend(it.sendItemId)
sendAction(AddSendAction.Internal.RemovePasswordResultReceive(result))
sendAction(AddEditSendAction.Internal.RemovePasswordResultReceive(result))
}
}
}
@@ -424,30 +437,30 @@ class AddSendViewModel @Inject constructor(
private fun handleShareLinkClick() {
onContent {
it.common.sendUrl?.let { sendUrl ->
sendEvent(AddSendEvent.ShowShareSheet(sendUrl))
sendEvent(AddEditSendEvent.ShowShareSheet(sendUrl))
}
}
}
private fun handlePasswordChange(action: AddSendAction.PasswordChange) {
private fun handlePasswordChange(action: AddEditSendAction.PasswordChange) {
updateCommonContent {
it.copy(passwordInput = action.input)
}
}
private fun handleNoteChange(action: AddSendAction.NoteChange) {
private fun handleNoteChange(action: AddEditSendAction.NoteChange) {
updateCommonContent {
it.copy(noteInput = action.input)
}
}
private fun handleHideMyEmailToggle(action: AddSendAction.HideMyEmailToggle) {
private fun handleHideMyEmailToggle(action: AddEditSendAction.HideMyEmailToggle) {
updateCommonContent {
it.copy(isHideEmailChecked = action.isChecked)
}
}
private fun handleDeactivateThisSendToggle(action: AddSendAction.DeactivateThisSendToggle) {
private fun handleDeactivateThisSendToggle(action: AddEditSendAction.DeactivateThisSendToggle) {
updateCommonContent {
it.copy(isDeactivateChecked = action.isChecked)
}
@@ -455,7 +468,7 @@ class AddSendViewModel @Inject constructor(
private fun handleCloseClick() = navigateBack()
private fun handleDeletionDateChange(action: AddSendAction.DeletionDateChange) {
private fun handleDeletionDateChange(action: AddEditSendAction.DeletionDateChange) {
updateCommonContent {
it.copy(deletionDate = action.deletionDate)
}
@@ -467,7 +480,7 @@ class AddSendViewModel @Inject constructor(
if (content.common.name.isBlank()) {
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.validation_field_required.asText(
R.string.name.asText(),
@@ -477,37 +490,38 @@ class AddSendViewModel @Inject constructor(
}
return@onContent
}
(content.selectedType as? AddSendState.ViewState.Content.SendType.File)?.let { file ->
if (file.name.isNullOrBlank()) {
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.validation_field_required.asText(
R.string.file.asText(),
(content.selectedType as? AddEditSendState.ViewState.Content.SendType.File)
?.let { fileType ->
if (fileType.name.isNullOrBlank()) {
mutableStateFlow.update {
it.copy(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.validation_field_required.asText(
R.string.file.asText(),
),
),
),
)
)
}
return@onContent
}
return@onContent
}
if ((file.sizeBytes ?: 0) > MAX_FILE_SIZE_BYTES) {
// Must be under 100 MB
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.max_file_size.asText(),
),
)
if ((fileType.sizeBytes ?: 0) > MAX_FILE_SIZE_BYTES) {
// Must be under 100 MB
mutableStateFlow.update {
it.copy(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.max_file_size.asText(),
),
)
}
return@onContent
}
return@onContent
}
}
if (!networkConnectionManager.isNetworkConnected) {
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.internet_connection_required_title.asText(),
message = R.string.internet_connection_required_message.asText(),
),
@@ -517,30 +531,29 @@ class AddSendViewModel @Inject constructor(
}
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Loading(
dialogState = AddEditSendState.DialogState.Loading(
message = R.string.saving.asText(),
),
)
}
viewModelScope.launch {
when (val addSendType = state.addSendType) {
AddSendType.AddItem -> {
when (val addSendType = state.addEditSendType) {
AddEditSendType.AddItem -> {
val fileType = content
.selectedType
as? AddSendState.ViewState.Content.SendType.File
.selectedType as? AddEditSendState.ViewState.Content.SendType.File
val result = vaultRepo.createSend(
sendView = content.toSendView(clock),
fileUri = fileType?.uri,
)
sendAction(AddSendAction.Internal.CreateSendResultReceive(result))
sendAction(AddEditSendAction.Internal.CreateSendResultReceive(result))
}
is AddSendType.EditItem -> {
is AddEditSendType.EditItem -> {
val result = vaultRepo.updateSend(
sendId = addSendType.sendItemId,
sendView = content.toSendView(clock),
)
sendAction(AddSendAction.Internal.UpdateSendResultReceive(result))
sendAction(AddEditSendAction.Internal.UpdateSendResultReceive(result))
}
}
}
@@ -551,29 +564,29 @@ class AddSendViewModel @Inject constructor(
mutableStateFlow.update { it.copy(dialogState = null) }
}
private fun handleNameChange(action: AddSendAction.NameChange) {
private fun handleNameChange(action: AddEditSendAction.NameChange) {
updateCommonContent {
it.copy(name = action.input)
}
}
private fun handleTextChange(action: AddSendAction.TextChange) {
private fun handleTextChange(action: AddEditSendAction.TextChange) {
updateTextContent {
it.copy(input = action.input)
}
}
private fun handleHideByDefaultToggle(action: AddSendAction.HideByDefaultToggle) {
private fun handleHideByDefaultToggle(action: AddEditSendAction.HideByDefaultToggle) {
updateTextContent {
it.copy(isHideByDefaultChecked = action.isChecked)
}
}
private fun handleChooseFileClick(action: AddSendAction.ChooseFileClick) {
sendEvent(AddSendEvent.ShowChooserSheet(action.isCameraPermissionGranted))
private fun handleChooseFileClick(action: AddEditSendAction.ChooseFileClick) {
sendEvent(AddEditSendEvent.ShowChooserSheet(action.isCameraPermissionGranted))
}
private fun handleMaxAccessCountChange(action: AddSendAction.MaxAccessCountChange) {
private fun handleMaxAccessCountChange(action: AddEditSendAction.MaxAccessCountChange) {
updateCommonContent { common ->
common.copy(maxAccessCount = action.value.takeUnless { it == 0 })
}
@@ -583,13 +596,13 @@ class AddSendViewModel @Inject constructor(
specialCircumstanceManager.specialCircumstance = null
sendEvent(
event = if (state.shouldFinishOnComplete) {
AddSendEvent.ExitApp
AddEditSendEvent.ExitApp
} else if (isDeleted) {
// We need to make sure we don't land on the View Send screen
// since it has now been deleted.
AddSendEvent.NavigateToRoot
AddEditSendEvent.NavigateToRoot
} else {
AddSendEvent.NavigateBack
AddEditSendEvent.NavigateBack
},
)
}
@@ -600,24 +613,24 @@ class AddSendViewModel @Inject constructor(
.any { it.shouldDisableHideEmail ?: false }
private inline fun onContent(
crossinline block: (AddSendState.ViewState.Content) -> Unit,
crossinline block: (AddEditSendState.ViewState.Content) -> Unit,
) {
(state.viewState as? AddSendState.ViewState.Content)?.let(block)
(state.viewState as? AddEditSendState.ViewState.Content)?.let(block)
}
private inline fun onEdit(
crossinline block: (AddSendType.EditItem) -> Unit,
crossinline block: (AddEditSendType.EditItem) -> Unit,
) {
(state.addSendType as? AddSendType.EditItem)?.let(block)
(state.addEditSendType as? AddEditSendType.EditItem)?.let(block)
}
private inline fun updateContent(
crossinline block: (
AddSendState.ViewState.Content,
) -> AddSendState.ViewState.Content?,
AddEditSendState.ViewState.Content,
) -> AddEditSendState.ViewState.Content?,
) {
val currentViewState = state.viewState
val updatedContent = (currentViewState as? AddSendState.ViewState.Content)
val updatedContent = (currentViewState as? AddEditSendState.ViewState.Content)
?.let(block)
?: return
mutableStateFlow.update { it.copy(viewState = updatedContent) }
@@ -625,42 +638,42 @@ class AddSendViewModel @Inject constructor(
private inline fun updateCommonContent(
crossinline block: (
AddSendState.ViewState.Content.Common,
) -> AddSendState.ViewState.Content.Common,
AddEditSendState.ViewState.Content.Common,
) -> AddEditSendState.ViewState.Content.Common,
) {
updateContent { it.copy(common = block(it.common)) }
}
private inline fun updateFileContent(
crossinline block: (
AddSendState.ViewState.Content.SendType.File,
) -> AddSendState.ViewState.Content.SendType.File,
AddEditSendState.ViewState.Content.SendType.File,
) -> AddEditSendState.ViewState.Content.SendType.File,
) {
updateContent { currentContent ->
(currentContent.selectedType as? AddSendState.ViewState.Content.SendType.File)
(currentContent.selectedType as? AddEditSendState.ViewState.Content.SendType.File)
?.let { currentContent.copy(selectedType = block(it)) }
}
}
private inline fun updateTextContent(
crossinline block: (
AddSendState.ViewState.Content.SendType.Text,
) -> AddSendState.ViewState.Content.SendType.Text,
AddEditSendState.ViewState.Content.SendType.Text,
) -> AddEditSendState.ViewState.Content.SendType.Text,
) {
updateContent { currentContent ->
(currentContent.selectedType as? AddSendState.ViewState.Content.SendType.Text)
(currentContent.selectedType as? AddEditSendState.ViewState.Content.SendType.Text)
?.let { currentContent.copy(selectedType = block(it)) }
}
}
}
/**
* Models state for the new send screen.
* Models state for the add/edit send screen.
*/
@Parcelize
data class AddSendState(
data class AddEditSendState(
val sendType: SendItemType,
val addSendType: AddSendType,
val addEditSendType: AddEditSendType,
val dialogState: DialogState?,
val viewState: ViewState,
val shouldFinishOnComplete: Boolean,
@@ -673,13 +686,13 @@ data class AddSendState(
* Helper to determine the screen display name.
*/
val screenDisplayName: Text
get() = when (addSendType) {
AddSendType.AddItem -> when (sendType) {
get() = when (addEditSendType) {
AddEditSendType.AddItem -> when (sendType) {
SendItemType.FILE -> R.string.add_file_send.asText()
SendItemType.TEXT -> R.string.add_text_send.asText()
}
is AddSendType.EditItem -> when (sendType) {
is AddEditSendType.EditItem -> when (sendType) {
SendItemType.FILE -> R.string.edit_file_send.asText()
SendItemType.TEXT -> R.string.edit_text_send.asText()
}
@@ -695,7 +708,7 @@ data class AddSendState(
/**
* Helper to determine if the UI should display the content in add send mode.
*/
val isAddMode: Boolean get() = addSendType is AddSendType.AddItem
val isAddMode: Boolean get() = addEditSendType is AddEditSendType.AddItem
/**
* Helper to determine if the currently displayed send has a password already set.
@@ -704,23 +717,24 @@ data class AddSendState(
get() = (viewState as? ViewState.Content)?.common?.hasPassword == true
/**
* Represents the specific view states for the [AddSendScreen].
* Represents the specific view states for the [AddEditSendScreen].
*/
sealed class ViewState : Parcelable {
/**
* Represents an error state for the [AddSendScreen].
* Represents an error state for the [AddEditSendScreen].
*/
@Parcelize
data class Error(val message: Text) : ViewState()
/**
* Loading state for the [AddSendScreen], signifying that the content is being processed.
* Loading state for the [AddEditSendScreen], signifying that the content is being
* processed.
*/
@Parcelize
data object Loading : ViewState()
/**
* Represents a loaded content state for the [AddSendScreen].
* Represents a loaded content state for the [AddEditSendScreen].
*/
@Parcelize
data class Content(
@@ -805,143 +819,143 @@ data class AddSendState(
}
/**
* Models events for the new send screen.
* Models events for the add/edit send screen.
*/
sealed class AddSendEvent {
sealed class AddEditSendEvent {
/**
* Closes the app.
*/
data object ExitApp : AddSendEvent()
data object ExitApp : AddEditSendEvent()
/**
* Navigate back.
*/
data object NavigateBack : AddSendEvent()
data object NavigateBack : AddEditSendEvent()
/**
* Navigate up to the root.
*/
data object NavigateToRoot : AddSendEvent()
data object NavigateToRoot : AddEditSendEvent()
/**
* Show file chooser sheet.
*/
data class ShowChooserSheet(val withCameraOption: Boolean) : AddSendEvent()
data class ShowChooserSheet(val withCameraOption: Boolean) : AddEditSendEvent()
/**
* Show share sheet.
*/
data class ShowShareSheet(
val message: String,
) : BackgroundEvent, AddSendEvent()
) : BackgroundEvent, AddEditSendEvent()
/**
* Show Toast.
*/
data class ShowToast(val message: Text) : AddSendEvent()
data class ShowToast(val message: Text) : AddEditSendEvent()
}
/**
* Models actions for the new send screen.
* Models actions for the add/edit send screen.
*/
sealed class AddSendAction {
sealed class AddEditSendAction {
/**
* User has chosen a file to be part of the send.
*/
data class FileChoose(val fileData: IntentManager.FileData) : AddSendAction()
data class FileChoose(val fileData: IntentManager.FileData) : AddEditSendAction()
/**
* User clicked the remove password button.
*/
data object RemovePasswordClick : AddSendAction()
data object RemovePasswordClick : AddEditSendAction()
/**
* User clicked the copy link button.
*/
data object CopyLinkClick : AddSendAction()
data object CopyLinkClick : AddEditSendAction()
/**
* User clicked the share link button.
*/
data object ShareLinkClick : AddSendAction()
data object ShareLinkClick : AddEditSendAction()
/**
* User clicked the delete button.
*/
data object DeleteClick : AddSendAction()
data object DeleteClick : AddEditSendAction()
/**
* User clicked the close button.
*/
data object CloseClick : AddSendAction()
data object CloseClick : AddEditSendAction()
/**
* User clicked to dismiss the current dialog.
*/
data object DismissDialogClick : AddSendAction()
data object DismissDialogClick : AddEditSendAction()
/**
* User clicked the save button.
*/
data object SaveClick : AddSendAction()
data object SaveClick : AddEditSendAction()
/**
* Value of the name field was updated.
*/
data class NameChange(val input: String) : AddSendAction()
data class NameChange(val input: String) : AddEditSendAction()
/**
* Value of the send text field updated.
*/
data class TextChange(val input: String) : AddSendAction()
data class TextChange(val input: String) : AddEditSendAction()
/**
* Value of the password field updated.
*/
data class PasswordChange(val input: String) : AddSendAction()
data class PasswordChange(val input: String) : AddEditSendAction()
/**
* Value of the note text field updated.
*/
data class NoteChange(val input: String) : AddSendAction()
data class NoteChange(val input: String) : AddEditSendAction()
/**
* User clicked the choose file button.
*/
data class ChooseFileClick(
val isCameraPermissionGranted: Boolean,
) : AddSendAction()
) : AddEditSendAction()
/**
* User toggled the "hide text by default" toggle.
*/
data class HideByDefaultToggle(val isChecked: Boolean) : AddSendAction()
data class HideByDefaultToggle(val isChecked: Boolean) : AddEditSendAction()
/**
* User incremented the max access count.
*/
data class MaxAccessCountChange(val value: Int) : AddSendAction()
data class MaxAccessCountChange(val value: Int) : AddEditSendAction()
/**
* User toggled the "hide my email" toggle.
*/
data class HideMyEmailToggle(val isChecked: Boolean) : AddSendAction()
data class HideMyEmailToggle(val isChecked: Boolean) : AddEditSendAction()
/**
* User toggled the "deactivate this send" toggle.
*/
data class DeactivateThisSendToggle(val isChecked: Boolean) : AddSendAction()
data class DeactivateThisSendToggle(val isChecked: Boolean) : AddEditSendAction()
/**
* The user changed the deletion date.
*/
data class DeletionDateChange(val deletionDate: ZonedDateTime) : AddSendAction()
data class DeletionDateChange(val deletionDate: ZonedDateTime) : AddEditSendAction()
/**
* Models actions that the [AddSendViewModel] itself might send.
* Models actions that the [AddEditSendViewModel] itself might send.
*/
sealed class Internal : AddSendAction() {
sealed class Internal : AddEditSendAction() {
/**
* Indicates a result for creating a send has been received.
*/

View File

@@ -0,0 +1,64 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addedit.handlers
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendAction
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendViewModel
import java.time.ZonedDateTime
/**
* A collection of handler functions for managing actions within the context of adding and editing
* send items.
*/
data class AddEditSendHandlers(
val onNameChange: (String) -> Unit,
val onChooseFileClick: (hasPermission: Boolean) -> Unit,
val onFileChoose: (IntentManager.FileData) -> Unit,
val onTextChange: (String) -> Unit,
val onIsHideByDefaultToggle: (Boolean) -> Unit,
val onMaxAccessCountChange: (Int) -> Unit,
val onPasswordChange: (String) -> Unit,
val onNoteChange: (String) -> Unit,
val onHideEmailToggle: (Boolean) -> Unit,
val onDeactivateSendToggle: (Boolean) -> Unit,
val onDeletionDateChange: (ZonedDateTime) -> Unit,
val onDeleteClick: () -> Unit,
) {
@Suppress("UndocumentedPublicClass")
companion object {
/**
* Creates an instance of [AddEditSendHandlers] by binding actions to the provided
* [AddEditSendViewModel].
*/
fun create(
viewModel: AddEditSendViewModel,
): AddEditSendHandlers =
AddEditSendHandlers(
onNameChange = { viewModel.trySendAction(AddEditSendAction.NameChange(it)) },
onChooseFileClick = {
viewModel.trySendAction(AddEditSendAction.ChooseFileClick(it))
},
onFileChoose = { viewModel.trySendAction(AddEditSendAction.FileChoose(it)) },
onTextChange = { viewModel.trySendAction(AddEditSendAction.TextChange(it)) },
onIsHideByDefaultToggle = {
viewModel.trySendAction(AddEditSendAction.HideByDefaultToggle(it))
},
onMaxAccessCountChange = {
viewModel.trySendAction(AddEditSendAction.MaxAccessCountChange(it))
},
onPasswordChange = {
viewModel.trySendAction(AddEditSendAction.PasswordChange(it))
},
onNoteChange = { viewModel.trySendAction(AddEditSendAction.NoteChange(it)) },
onHideEmailToggle = {
viewModel.trySendAction(AddEditSendAction.HideMyEmailToggle(it))
},
onDeactivateSendToggle = {
viewModel.trySendAction(AddEditSendAction.DeactivateThisSendToggle(it))
},
onDeletionDateChange = {
viewModel.trySendAction(AddEditSendAction.DeletionDateChange(it))
},
onDeleteClick = { viewModel.trySendAction(AddEditSendAction.DeleteClick) },
)
}
}

View File

@@ -1,4 +1,4 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend.model
package com.x8bit.bitwarden.ui.tools.feature.send.addedit.model
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@@ -6,12 +6,12 @@ import kotlinx.parcelize.Parcelize
/**
* Represents the difference between create a completely new send and editing an existing one.
*/
sealed class AddSendType : Parcelable {
sealed class AddEditSendType : Parcelable {
/**
* Indicates that we want to create a completely new send item.
*/
@Parcelize
data object AddItem : AddSendType()
data object AddItem : AddEditSendType()
/**
* Indicates that we want to edit an existing send item.
@@ -19,5 +19,5 @@ sealed class AddSendType : Parcelable {
* @param sendItemId The ID of the send item to edit.
*/
@Parcelize
data class EditItem(val sendItemId: String) : AddSendType()
data class EditItem(val sendItemId: String) : AddEditSendType()
}

View File

@@ -1,17 +1,17 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend.util
package com.x8bit.bitwarden.ui.tools.feature.send.addedit.util
import com.bitwarden.send.SendFileView
import com.bitwarden.send.SendTextView
import com.bitwarden.send.SendType
import com.bitwarden.send.SendView
import com.bitwarden.ui.platform.base.util.orNullIfBlank
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddSendState
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendState
import java.time.Clock
/**
* Transforms [AddSendState] into [SendView].
* Transforms [AddEditSendState] into [SendView].
*/
fun AddSendState.ViewState.Content.toSendView(
fun AddEditSendState.ViewState.Content.toSendView(
clock: Clock,
): SendView =
SendView(
@@ -38,14 +38,14 @@ fun AddSendState.ViewState.Content.toSendView(
},
)
private fun AddSendState.ViewState.Content.SendType.toSendType(): SendType =
private fun AddEditSendState.ViewState.Content.SendType.toSendType(): SendType =
when (this) {
is AddSendState.ViewState.Content.SendType.File -> SendType.FILE
is AddSendState.ViewState.Content.SendType.Text -> SendType.TEXT
is AddEditSendState.ViewState.Content.SendType.File -> SendType.FILE
is AddEditSendState.ViewState.Content.SendType.Text -> SendType.TEXT
}
private fun AddSendState.ViewState.Content.toSendFileView(): SendFileView? =
(this.selectedType as? AddSendState.ViewState.Content.SendType.File)?.let {
private fun AddEditSendState.ViewState.Content.toSendFileView(): SendFileView? =
(this.selectedType as? AddEditSendState.ViewState.Content.SendType.File)?.let {
SendFileView(
id = null,
fileName = it.name.orEmpty(),
@@ -54,8 +54,8 @@ private fun AddSendState.ViewState.Content.toSendFileView(): SendFileView? =
)
}
private fun AddSendState.ViewState.Content.toSendTextView(): SendTextView? =
(this.selectedType as? AddSendState.ViewState.Content.SendType.Text)?.let {
private fun AddEditSendState.ViewState.Content.toSendTextView(): SendTextView? =
(this.selectedType as? AddEditSendState.ViewState.Content.SendType.Text)?.let {
SendTextView(
text = it.input,
hidden = it.isHideByDefaultChecked,

View File

@@ -1,22 +1,22 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend.util
package com.x8bit.bitwarden.ui.tools.feature.send.addedit.util
import com.bitwarden.send.SendType
import com.bitwarden.send.SendView
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddSendState
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendState
import com.x8bit.bitwarden.ui.tools.feature.send.util.toSendUrl
import java.time.Clock
import java.time.ZonedDateTime
/**
* Transforms [SendView] into [AddSendState.ViewState.Content].
* Transforms [SendView] into [AddEditSendState.ViewState.Content].
*/
fun SendView.toViewState(
clock: Clock,
baseWebSendUrl: String,
isHideEmailAddressEnabled: Boolean,
): AddSendState.ViewState.Content =
AddSendState.ViewState.Content(
common = AddSendState.ViewState.Content.Common(
): AddEditSendState.ViewState.Content =
AddEditSendState.ViewState.Content(
common = AddEditSendState.ViewState.Content.Common(
originalSendView = this,
name = this.name,
currentAccessCount = this.accessCount.toInt(),
@@ -35,7 +35,7 @@ fun SendView.toViewState(
),
selectedType = when (type) {
SendType.TEXT -> {
AddSendState.ViewState.Content.SendType.Text(
AddEditSendState.ViewState.Content.SendType.Text(
input = this.text?.text.orEmpty(),
isHideByDefaultChecked = this.text?.hidden == true,
)
@@ -43,7 +43,7 @@ fun SendView.toViewState(
SendType.FILE -> {
val fileView = requireNotNull(this.file)
AddSendState.ViewState.Content.SendType.File(
AddEditSendState.ViewState.Content.SendType.File(
uri = null,
name = fileView.fileName,
displaySize = fileView.sizeName,

View File

@@ -1,28 +1,32 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend.util
package com.x8bit.bitwarden.ui.tools.feature.send.addedit.util
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddSendState
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendState
/**
* Determines the initial [AddSendState.ViewState.Content.SendType] based on the data in the
* Determines the initial [AddEditSendState.ViewState.Content.SendType] based on the data in the
* [SpecialCircumstance].
*/
fun SpecialCircumstance?.toSendType(): AddSendState.ViewState.Content.SendType? =
fun SpecialCircumstance?.toSendType(): AddEditSendState.ViewState.Content.SendType? =
when (this) {
is SpecialCircumstance.ShareNewSend -> {
when (data) {
is IntentManager.ShareData.FileSend -> AddSendState.ViewState.Content.SendType.File(
uri = data.fileData.uri,
name = data.fileData.fileName,
sizeBytes = data.fileData.sizeBytes,
displaySize = null,
)
is IntentManager.ShareData.FileSend -> {
AddEditSendState.ViewState.Content.SendType.File(
uri = data.fileData.uri,
name = data.fileData.fileName,
sizeBytes = data.fileData.sizeBytes,
displaySize = null,
)
}
is IntentManager.ShareData.TextSend -> AddSendState.ViewState.Content.SendType.Text(
input = data.text,
isHideByDefaultChecked = false,
)
is IntentManager.ShareData.TextSend -> {
AddEditSendState.ViewState.Content.SendType.Text(
input = data.text,
isHideByDefaultChecked = false,
)
}
}
}

View File

@@ -1,60 +0,0 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend.handlers
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddSendAction
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddSendViewModel
import java.time.ZonedDateTime
/**
* A collection of handler functions for managing actions within the context of adding
* send items.
*/
data class AddSendHandlers(
val onNameChange: (String) -> Unit,
val onChooseFileClick: (hasPermission: Boolean) -> Unit,
val onFileChoose: (IntentManager.FileData) -> Unit,
val onTextChange: (String) -> Unit,
val onIsHideByDefaultToggle: (Boolean) -> Unit,
val onMaxAccessCountChange: (Int) -> Unit,
val onPasswordChange: (String) -> Unit,
val onNoteChange: (String) -> Unit,
val onHideEmailToggle: (Boolean) -> Unit,
val onDeactivateSendToggle: (Boolean) -> Unit,
val onDeletionDateChange: (ZonedDateTime) -> Unit,
val onDeleteClick: () -> Unit,
) {
@Suppress("UndocumentedPublicClass")
companion object {
/**
* Creates an instance of [AddSendHandlers] by binding actions to the provided
* [AddSendViewModel].
*/
fun create(
viewModel: AddSendViewModel,
): AddSendHandlers =
AddSendHandlers(
onNameChange = { viewModel.trySendAction(AddSendAction.NameChange(it)) },
onChooseFileClick = { viewModel.trySendAction(AddSendAction.ChooseFileClick(it)) },
onFileChoose = { viewModel.trySendAction(AddSendAction.FileChoose(it)) },
onTextChange = { viewModel.trySendAction(AddSendAction.TextChange(it)) },
onIsHideByDefaultToggle = {
viewModel.trySendAction(AddSendAction.HideByDefaultToggle(it))
},
onMaxAccessCountChange = {
viewModel.trySendAction(AddSendAction.MaxAccessCountChange(it))
},
onPasswordChange = { viewModel.trySendAction(AddSendAction.PasswordChange(it)) },
onNoteChange = { viewModel.trySendAction(AddSendAction.NoteChange(it)) },
onHideEmailToggle = {
viewModel.trySendAction(AddSendAction.HideMyEmailToggle(it))
},
onDeactivateSendToggle = {
viewModel.trySendAction(AddSendAction.DeactivateThisSendToggle(it))
},
onDeletionDateChange = {
viewModel.trySendAction(AddSendAction.DeletionDateChange(it))
},
onDeleteClick = { viewModel.trySendAction(AddSendAction.DeleteClick) },
)
}
}

View File

@@ -6,7 +6,7 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.toRoute
import com.bitwarden.ui.platform.base.util.composableWithSlideTransitions
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import kotlinx.serialization.Serializable

View File

@@ -69,8 +69,8 @@ import com.x8bit.bitwarden.ui.platform.components.stepper.BitwardenStepper
import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.x8bit.bitwarden.ui.platform.composition.LocalIntentManager
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.ModeType
/**
* Displays view send screen.

View File

@@ -8,7 +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.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
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

View File

@@ -52,8 +52,8 @@ 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.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.ModeType
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

View File

@@ -17,8 +17,8 @@ import com.x8bit.bitwarden.ui.auth.feature.welcome.WelcomeRoute
import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
import com.x8bit.bitwarden.ui.platform.feature.splash.SplashRoute
import com.x8bit.bitwarden.ui.platform.feature.vaultunlocked.VaultUnlockedGraphRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditMode
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditRoute

View File

@@ -27,8 +27,8 @@ import com.x8bit.bitwarden.ui.platform.feature.search.model.AutofillSelectionOpt
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.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.ModeType
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

View File

@@ -27,8 +27,8 @@ import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.data.platform.manager.util.AppResumeStateManager
import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.ModeType
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

View File

@@ -1,4 +1,4 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend
package com.x8bit.bitwarden.ui.tools.feature.send.addedit
import androidx.compose.ui.test.assert
import androidx.compose.ui.test.assertCountEquals
@@ -27,7 +27,7 @@ import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
import com.x8bit.bitwarden.ui.platform.manager.exit.ExitManager
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.platform.manager.permissions.FakePermissionManager
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.model.AddSendType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.model.AddEditSendType
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.util.assertNoDialogExists
import com.x8bit.bitwarden.ui.util.isEditableText
@@ -46,7 +46,7 @@ import org.junit.Test
import java.time.ZonedDateTime
@Suppress("LargeClass")
class AddSendScreenTest : BitwardenComposeTest() {
class AddEditSendScreenTest : BitwardenComposeTest() {
private var onNavigateBackCalled = false
private var onNavigateUpToRootCalled = false
@@ -58,9 +58,9 @@ class AddSendScreenTest : BitwardenComposeTest() {
private val intentManager: IntentManager = mockk(relaxed = true) {
every { shareText(any()) } just runs
}
private val mutableEventFlow = bufferedMutableSharedFlow<AddSendEvent>()
private val mutableEventFlow = bufferedMutableSharedFlow<AddEditSendEvent>()
private val mutableStateFlow = MutableStateFlow(DEFAULT_STATE)
private val viewModel = mockk<AddSendViewModel>(relaxed = true) {
private val viewModel = mockk<AddEditSendViewModel>(relaxed = true) {
every { eventFlow } returns mutableEventFlow
every { stateFlow } returns mutableStateFlow
}
@@ -72,7 +72,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
intentManager = intentManager,
permissionsManager = permissionsManager,
) {
AddSendScreen(
AddEditSendScreen(
viewModel = viewModel,
onNavigateBack = { onNavigateBackCalled = true },
onNavigateUpToRoot = { onNavigateUpToRootCalled = true },
@@ -82,19 +82,19 @@ class AddSendScreenTest : BitwardenComposeTest() {
@Test
fun `on NavigateBack should call onNavigateBack`() {
mutableEventFlow.tryEmit(AddSendEvent.NavigateBack)
mutableEventFlow.tryEmit(AddEditSendEvent.NavigateBack)
assertTrue(onNavigateBackCalled)
}
@Test
fun `on NavigateToRoot should call onNavigateUpToRoot`() {
mutableEventFlow.tryEmit(AddSendEvent.NavigateToRoot)
mutableEventFlow.tryEmit(AddEditSendEvent.NavigateToRoot)
assertTrue(onNavigateUpToRootCalled)
}
@Test
fun `ExitApp should call exitApplication on ExitManager`() {
mutableEventFlow.tryEmit(AddSendEvent.ExitApp)
mutableEventFlow.tryEmit(AddEditSendEvent.ExitApp)
verify {
exitManager.exitApplication()
}
@@ -103,7 +103,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
@Test
fun `on ShowShareSheet should call shareText on IntentManager`() {
val text = "sharable stuff"
mutableEventFlow.tryEmit(AddSendEvent.ShowShareSheet(text))
mutableEventFlow.tryEmit(AddEditSendEvent.ShowShareSheet(text))
verify {
intentManager.shareText(text)
}
@@ -114,13 +114,13 @@ class AddSendScreenTest : BitwardenComposeTest() {
composeTestRule
.onNodeWithContentDescription("Close")
.performClick()
verify { viewModel.trySendAction(AddSendAction.CloseClick) }
verify { viewModel.trySendAction(AddEditSendAction.CloseClick) }
}
@Test
fun `on system back should send CloseClick`() {
backDispatcher?.onBackPressed()
verify { viewModel.trySendAction(AddSendAction.CloseClick) }
verify { viewModel.trySendAction(AddEditSendAction.CloseClick) }
}
@Test
@@ -134,25 +134,25 @@ class AddSendScreenTest : BitwardenComposeTest() {
@Test
fun `screen title should update according to state`() {
mutableStateFlow.update {
it.copy(sendType = SendItemType.TEXT, addSendType = AddSendType.AddItem)
it.copy(sendType = SendItemType.TEXT, addEditSendType = AddEditSendType.AddItem)
}
composeTestRule.onNodeWithText(text = "New text Send").assertIsDisplayed()
mutableStateFlow.update {
it.copy(
sendType = SendItemType.TEXT,
addSendType = AddSendType.EditItem(sendItemId = "send_id"),
addEditSendType = AddEditSendType.EditItem(sendItemId = "send_id"),
)
}
composeTestRule.onNodeWithText(text = "Edit text Send").assertIsDisplayed()
mutableStateFlow.update {
it.copy(sendType = SendItemType.FILE, addSendType = AddSendType.AddItem)
it.copy(sendType = SendItemType.FILE, addEditSendType = AddEditSendType.AddItem)
}
composeTestRule.onNodeWithText(text = "New file Send").assertIsDisplayed()
mutableStateFlow.update {
it.copy(
sendType = SendItemType.FILE,
addSendType = AddSendType.EditItem(sendItemId = "send_id"),
addEditSendType = AddEditSendType.EditItem(sendItemId = "send_id"),
)
}
composeTestRule.onNodeWithText(text = "Edit file Send").assertIsDisplayed()
@@ -163,13 +163,13 @@ class AddSendScreenTest : BitwardenComposeTest() {
composeTestRule
.onNodeWithText("Save")
.performClick()
verify { viewModel.trySendAction(AddSendAction.SaveClick) }
verify { viewModel.trySendAction(AddEditSendAction.SaveClick) }
}
@Test
fun `on overflow button click should display overflow menu`() {
mutableStateFlow.value = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendItemId = "sendId"),
addEditSendType = AddEditSendType.EditItem(sendItemId = "sendId"),
)
composeTestRule
@@ -193,7 +193,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
@Test
fun `on overflow button should not be present when policy disables send`() {
mutableStateFlow.value = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendItemId = "sendId"),
addEditSendType = AddEditSendType.EditItem(sendItemId = "sendId"),
policyDisablesSend = true,
)
@@ -205,7 +205,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
@Test
fun `overflow remove password button should be hidden when hasPassword is false`() {
mutableStateFlow.value = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendItemId = "sendId"),
addEditSendType = AddEditSendType.EditItem(sendItemId = "sendId"),
viewState = DEFAULT_VIEW_STATE.copy(
common = DEFAULT_COMMON_STATE.copy(hasPassword = false),
),
@@ -223,7 +223,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
@Test
fun `on overflow remove password button click should send RemovePasswordClick`() {
mutableStateFlow.value = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendItemId = "sendId"),
addEditSendType = AddEditSendType.EditItem(sendItemId = "sendId"),
)
composeTestRule
@@ -235,14 +235,14 @@ class AddSendScreenTest : BitwardenComposeTest() {
.performClick()
verify(exactly = 1) {
viewModel.trySendAction(AddSendAction.RemovePasswordClick)
viewModel.trySendAction(AddEditSendAction.RemovePasswordClick)
}
}
@Test
fun `on overflow remove Share link button click should send ShareLinkClick`() {
mutableStateFlow.value = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendItemId = "sendId"),
addEditSendType = AddEditSendType.EditItem(sendItemId = "sendId"),
)
composeTestRule
@@ -254,14 +254,14 @@ class AddSendScreenTest : BitwardenComposeTest() {
.performClick()
verify(exactly = 1) {
viewModel.trySendAction(AddSendAction.ShareLinkClick)
viewModel.trySendAction(AddEditSendAction.ShareLinkClick)
}
}
@Test
fun `on overflow remove Copy link button click should send CopyLinkClick`() {
mutableStateFlow.value = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendItemId = "sendId"),
addEditSendType = AddEditSendType.EditItem(sendItemId = "sendId"),
)
composeTestRule
@@ -273,14 +273,14 @@ class AddSendScreenTest : BitwardenComposeTest() {
.performClick()
verify(exactly = 1) {
viewModel.trySendAction(AddSendAction.CopyLinkClick)
viewModel.trySendAction(AddEditSendAction.CopyLinkClick)
}
}
@Test
fun `on Delete button click should Display delete confirmation dialog`() {
mutableStateFlow.value = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendItemId = "sendId"),
addEditSendType = AddEditSendType.EditItem(sendItemId = "sendId"),
)
composeTestRule
@@ -297,7 +297,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
@Test
fun `on delete confirmation dialog yes click should send DeleteClick`() {
mutableStateFlow.value = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendItemId = "sendId"),
addEditSendType = AddEditSendType.EditItem(sendItemId = "sendId"),
)
composeTestRule
@@ -311,7 +311,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
.performClick()
verify(exactly = 1) {
viewModel.trySendAction(AddSendAction.DeleteClick)
viewModel.trySendAction(AddEditSendAction.DeleteClick)
}
}
@@ -339,7 +339,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
composeTestRule
.onNodeWithText("Send name (required)")
.performTextInput("input")
verify { viewModel.trySendAction(AddSendAction.NameChange("input")) }
verify { viewModel.trySendAction(AddEditSendAction.NameChange("input")) }
}
@Test
@@ -365,7 +365,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
permissionsManager.checkPermissionResult = true
mutableStateFlow.value = DEFAULT_STATE.copy(
viewState = DEFAULT_VIEW_STATE.copy(
selectedType = AddSendState.ViewState.Content.SendType.File(
selectedType = AddEditSendState.ViewState.Content.SendType.File(
name = null,
displaySize = null,
sizeBytes = null,
@@ -379,7 +379,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
.performClick()
verify {
viewModel.trySendAction(
AddSendAction.ChooseFileClick(isCameraPermissionGranted = true),
AddEditSendAction.ChooseFileClick(isCameraPermissionGranted = true),
)
}
}
@@ -391,7 +391,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
permissionsManager.getPermissionsResult = false
mutableStateFlow.value = DEFAULT_STATE.copy(
viewState = DEFAULT_VIEW_STATE.copy(
selectedType = AddSendState.ViewState.Content.SendType.File(
selectedType = AddEditSendState.ViewState.Content.SendType.File(
name = null,
displaySize = null,
sizeBytes = null,
@@ -405,7 +405,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
.performClick()
verify {
viewModel.trySendAction(
AddSendAction.ChooseFileClick(isCameraPermissionGranted = false),
AddEditSendAction.ChooseFileClick(isCameraPermissionGranted = false),
)
}
}
@@ -418,7 +418,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
.performScrollTo()
.performTextInput("input")
verify(exactly = 1) {
viewModel.trySendAction(AddSendAction.TextChange("input"))
viewModel.trySendAction(AddEditSendAction.TextChange("input"))
}
}
@@ -432,7 +432,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
mutableStateFlow.update {
it.copy(
viewState = DEFAULT_VIEW_STATE.copy(
selectedType = AddSendState.ViewState.Content.SendType.Text(
selectedType = AddEditSendState.ViewState.Content.SendType.Text(
input = "input",
isHideByDefaultChecked = false,
),
@@ -450,7 +450,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
composeTestRule
.onNodeWithText(text = "When accessing the Send", substring = true)
.performClick()
viewModel.trySendAction(AddSendAction.HideByDefaultToggle(true))
viewModel.trySendAction(AddEditSendAction.HideByDefaultToggle(true))
}
@Test
@@ -462,7 +462,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
mutableStateFlow.update {
it.copy(
viewState = DEFAULT_VIEW_STATE.copy(
selectedType = AddSendState.ViewState.Content.SendType.Text(
selectedType = AddEditSendState.ViewState.Content.SendType.Text(
input = "",
isHideByDefaultChecked = true,
),
@@ -542,7 +542,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
.onNodeWithContentDescription("\u2212")
.performScrollTo()
.performClick()
verify { viewModel.trySendAction(AddSendAction.MaxAccessCountChange(2)) }
verify { viewModel.trySendAction(AddEditSendAction.MaxAccessCountChange(2)) }
}
@Test
@@ -557,7 +557,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
.onNodeWithContentDescription("+")
.performScrollTo()
.performClick()
verify { viewModel.trySendAction(AddSendAction.MaxAccessCountChange(1)) }
verify { viewModel.trySendAction(AddEditSendAction.MaxAccessCountChange(1)) }
}
@Test
@@ -571,7 +571,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
composeTestRule
.onNodeWithText("New password")
.performTextInput("input")
verify { viewModel.trySendAction(AddSendAction.PasswordChange("input")) }
verify { viewModel.trySendAction(AddEditSendAction.PasswordChange("input")) }
}
@Test
@@ -608,7 +608,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
composeTestRule
.onNodeWithText("Private notes")
.performTextInput("input")
verify { viewModel.trySendAction(AddSendAction.NoteChange("input")) }
verify { viewModel.trySendAction(AddEditSendAction.NoteChange("input")) }
}
@Test
@@ -646,7 +646,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
.onNodeWithText("Hide my email address", substring = true)
.performScrollTo()
.performClick()
verify { viewModel.trySendAction(AddSendAction.HideMyEmailToggle(true)) }
verify { viewModel.trySendAction(AddEditSendAction.HideMyEmailToggle(true)) }
}
@Test
@@ -718,13 +718,13 @@ class AddSendScreenTest : BitwardenComposeTest() {
@Test
fun `progressbar should be displayed according to state`() {
mutableStateFlow.update {
it.copy(viewState = AddSendState.ViewState.Loading)
it.copy(viewState = AddEditSendState.ViewState.Loading)
}
// There are 2 because of the pull-to-refresh
composeTestRule.onAllNodes(isProgressBar).assertCountEquals(2)
mutableStateFlow.update {
it.copy(viewState = AddSendState.ViewState.Error("Fail".asText()))
it.copy(viewState = AddEditSendState.ViewState.Error("Fail".asText()))
}
// Only pull-to-refresh remains
composeTestRule.onAllNodes(isProgressBar).assertCountEquals(1)
@@ -740,12 +740,12 @@ class AddSendScreenTest : BitwardenComposeTest() {
fun `error should be displayed according to state`() {
val errorMessage = "Fail"
mutableStateFlow.update {
it.copy(viewState = AddSendState.ViewState.Error(errorMessage.asText()))
it.copy(viewState = AddEditSendState.ViewState.Error(errorMessage.asText()))
}
composeTestRule.onNodeWithText(errorMessage).assertIsDisplayed()
mutableStateFlow.update {
it.copy(viewState = AddSendState.ViewState.Loading)
it.copy(viewState = AddEditSendState.ViewState.Loading)
}
composeTestRule.onNodeWithText(errorMessage).assertDoesNotExist()
}
@@ -759,7 +759,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = errorTitle.asText(),
message = errorMessage.asText(),
),
@@ -776,7 +776,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
fun `error dialog Ok click should send DismissDialogClick`() {
mutableStateFlow.update {
it.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = "Fail Title".asText(),
message = "Fail Message".asText(),
),
@@ -785,7 +785,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
composeTestRule
.onNodeWithText("Ok")
.performClick()
verify { viewModel.trySendAction(AddSendAction.DismissDialogClick) }
verify { viewModel.trySendAction(AddEditSendAction.DismissDialogClick) }
}
@Test
@@ -795,7 +795,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
composeTestRule.onNodeWithText(loadingMessage).assertDoesNotExist()
mutableStateFlow.update {
it.copy(dialogState = AddSendState.DialogState.Loading(loadingMessage.asText()))
it.copy(dialogState = AddEditSendState.DialogState.Loading(loadingMessage.asText()))
}
composeTestRule
@@ -836,7 +836,7 @@ class AddSendScreenTest : BitwardenComposeTest() {
}
}
private val DEFAULT_COMMON_STATE = AddSendState.ViewState.Content.Common(
private val DEFAULT_COMMON_STATE = AddEditSendState.ViewState.Content.Common(
name = "",
currentAccessCount = null,
maxAccessCount = null,
@@ -851,18 +851,18 @@ private val DEFAULT_COMMON_STATE = AddSendState.ViewState.Content.Common(
isHideEmailAddressEnabled = true,
)
private val DEFAULT_SELECTED_TYPE_STATE = AddSendState.ViewState.Content.SendType.Text(
private val DEFAULT_SELECTED_TYPE_STATE = AddEditSendState.ViewState.Content.SendType.Text(
input = "",
isHideByDefaultChecked = false,
)
private val DEFAULT_VIEW_STATE = AddSendState.ViewState.Content(
private val DEFAULT_VIEW_STATE = AddEditSendState.ViewState.Content(
common = DEFAULT_COMMON_STATE,
selectedType = DEFAULT_SELECTED_TYPE_STATE,
)
private val DEFAULT_STATE = AddSendState(
addSendType = AddSendType.AddItem,
private val DEFAULT_STATE = AddEditSendState(
addEditSendType = AddEditSendType.AddItem,
viewState = DEFAULT_VIEW_STATE,
dialogState = null,
shouldFinishOnComplete = false,

View File

@@ -1,4 +1,4 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend
package com.x8bit.bitwarden.ui.tools.feature.send.addedit
import android.net.Uri
import androidx.lifecycle.SavedStateHandle
@@ -25,9 +25,9 @@ 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.UpdateSendResult
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.model.AddSendType
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.util.toSendView
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.util.toViewState
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.model.AddEditSendType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.util.toSendView
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.util.toViewState
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.tools.feature.send.util.toSendUrl
import io.mockk.coEvery
@@ -54,7 +54,7 @@ import java.time.ZoneOffset
import java.time.ZonedDateTime
@Suppress("LargeClass")
class AddSendViewModelTest : BaseViewModelTest() {
class AddEditSendViewModelTest : BaseViewModelTest() {
private val clock = Clock.fixed(
Instant.parse("2023-10-27T12:00:00Z"),
@@ -85,8 +85,8 @@ class AddSendViewModelTest : BaseViewModelTest() {
@BeforeEach
fun setup() {
mockkStatic(
SavedStateHandle::toAddSendArgs,
AddSendState.ViewState.Content::toSendView,
SavedStateHandle::toAddEditSendArgs,
AddEditSendState.ViewState.Content::toSendView,
SendView::toSendUrl,
SendView::toViewState,
)
@@ -95,8 +95,8 @@ class AddSendViewModelTest : BaseViewModelTest() {
@AfterEach
fun tearDown() {
unmockkStatic(
SavedStateHandle::toAddSendArgs,
AddSendState.ViewState.Content::toSendView,
SavedStateHandle::toAddEditSendArgs,
AddEditSendState.ViewState.Content::toSendView,
SendView::toSendUrl,
SendView::toViewState,
)
@@ -135,7 +135,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
@Test
fun `initial state should read from saved state when present`() {
val savedState = DEFAULT_STATE.copy(
dialogState = AddSendState.DialogState.Loading("Loading".asText()),
dialogState = AddEditSendState.DialogState.Loading("Loading".asText()),
)
val viewModel = createViewModel(savedState)
assertEquals(savedState, viewModel.stateFlow.value)
@@ -145,8 +145,8 @@ class AddSendViewModelTest : BaseViewModelTest() {
fun `CloseClick should emit NavigateBack`() = runTest {
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(AddSendAction.CloseClick)
assertEquals(AddSendEvent.NavigateBack, awaitItem())
viewModel.trySendAction(AddEditSendAction.CloseClick)
assertEquals(AddEditSendEvent.NavigateBack, awaitItem())
}
}
@@ -174,10 +174,10 @@ class AddSendViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel(initialState)
viewModel.eventFlow.test {
viewModel.trySendAction(AddSendAction.SaveClick)
assertEquals(AddSendEvent.NavigateBack, awaitItem())
viewModel.trySendAction(AddEditSendAction.SaveClick)
assertEquals(AddEditSendEvent.NavigateBack, awaitItem())
assertEquals(
AddSendEvent.ShowShareSheet(message = "www.test.com/send/test"),
AddEditSendEvent.ShowShareSheet(message = "www.test.com/send/test"),
awaitItem(),
)
}
@@ -212,10 +212,10 @@ class AddSendViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel(initialState)
viewModel.eventFlow.test {
viewModel.trySendAction(AddSendAction.SaveClick)
assertEquals(AddSendEvent.ExitApp, awaitItem())
viewModel.trySendAction(AddEditSendAction.SaveClick)
assertEquals(AddEditSendEvent.ExitApp, awaitItem())
assertEquals(
AddSendEvent.ShowShareSheet(message = "www.test.com/send/test"),
AddEditSendEvent.ShowShareSheet(message = "www.test.com/send/test"),
awaitItem(),
)
}
@@ -241,10 +241,10 @@ class AddSendViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test {
assertEquals(initialState, awaitItem())
viewModel.trySendAction(AddSendAction.SaveClick)
viewModel.trySendAction(AddEditSendAction.SaveClick)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Loading(
dialogState = AddEditSendState.DialogState.Loading(
message = R.string.saving.asText(),
),
),
@@ -252,7 +252,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = "Fail".asText(),
),
@@ -273,7 +273,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
common = DEFAULT_COMMON_STATE.copy(name = "input"),
)
val initialState = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendId),
addEditSendType = AddEditSendType.EditItem(sendId),
viewState = viewState,
)
val mockSendView = createMockSendView(number = 1)
@@ -294,12 +294,12 @@ class AddSendViewModelTest : BaseViewModelTest() {
vaultRepository.updateSend(sendId = sendId, sendView = mockSendView)
} returns UpdateSendResult.Success(sendView = resultSendView)
mutableSendDataStateFlow.value = DataState.Loaded(mockSendView)
val viewModel = createViewModel(initialState, AddSendType.EditItem(sendId))
val viewModel = createViewModel(initialState, AddEditSendType.EditItem(sendId))
viewModel.eventFlow.test {
viewModel.trySendAction(AddSendAction.SaveClick)
assertEquals(AddSendEvent.NavigateBack, awaitItem())
assertEquals(AddSendEvent.ShowShareSheet(sendUrl), awaitItem())
viewModel.trySendAction(AddEditSendAction.SaveClick)
assertEquals(AddEditSendEvent.NavigateBack, awaitItem())
assertEquals(AddEditSendEvent.ShowShareSheet(sendUrl), awaitItem())
}
assertEquals(initialState, viewModel.stateFlow.value)
coVerify(exactly = 1) {
@@ -314,7 +314,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
common = DEFAULT_COMMON_STATE.copy(name = "input"),
)
val initialState = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendId),
addEditSendType = AddEditSendType.EditItem(sendId),
viewState = viewState,
)
val mockSendView = mockk<SendView> {
@@ -333,14 +333,14 @@ class AddSendViewModelTest : BaseViewModelTest() {
vaultRepository.updateSend(sendId = sendId, sendView = mockSendView)
} returns UpdateSendResult.Error(errorMessage = errorMessage, error = null)
mutableSendDataStateFlow.value = DataState.Loaded(mockSendView)
val viewModel = createViewModel(initialState, AddSendType.EditItem(sendId))
val viewModel = createViewModel(initialState, AddEditSendType.EditItem(sendId))
viewModel.stateFlow.test {
assertEquals(initialState, awaitItem())
viewModel.trySendAction(AddSendAction.SaveClick)
viewModel.trySendAction(AddEditSendAction.SaveClick)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Loading(
dialogState = AddEditSendState.DialogState.Loading(
message = R.string.saving.asText(),
),
),
@@ -348,7 +348,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = errorMessage.asText(),
),
@@ -365,11 +365,11 @@ class AddSendViewModelTest : BaseViewModelTest() {
fun `SaveClick with blank name should show error dialog`() {
val viewModel = createViewModel(DEFAULT_STATE)
viewModel.trySendAction(AddSendAction.SaveClick)
viewModel.trySendAction(AddEditSendAction.SaveClick)
assertEquals(
DEFAULT_STATE.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.validation_field_required.asText(
R.string.name.asText(),
@@ -385,7 +385,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
val initialState = DEFAULT_STATE.copy(
viewState = DEFAULT_VIEW_STATE.copy(
common = DEFAULT_COMMON_STATE.copy(name = "test"),
selectedType = AddSendState.ViewState.Content.SendType.File(
selectedType = AddEditSendState.ViewState.Content.SendType.File(
uri = null,
name = null,
displaySize = null,
@@ -395,11 +395,11 @@ class AddSendViewModelTest : BaseViewModelTest() {
)
val viewModel = createViewModel(initialState)
viewModel.trySendAction(AddSendAction.SaveClick)
viewModel.trySendAction(AddEditSendAction.SaveClick)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.validation_field_required.asText(R.string.file.asText()),
),
@@ -413,7 +413,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
val initialState = DEFAULT_STATE.copy(
viewState = DEFAULT_VIEW_STATE.copy(
common = DEFAULT_COMMON_STATE.copy(name = "test"),
selectedType = AddSendState.ViewState.Content.SendType.File(
selectedType = AddEditSendState.ViewState.Content.SendType.File(
uri = mockk(),
name = "test.png",
displaySize = null,
@@ -424,11 +424,11 @@ class AddSendViewModelTest : BaseViewModelTest() {
)
val viewModel = createViewModel(initialState)
viewModel.trySendAction(AddSendAction.SaveClick)
viewModel.trySendAction(AddEditSendAction.SaveClick)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.max_file_size.asText(),
),
@@ -454,13 +454,13 @@ class AddSendViewModelTest : BaseViewModelTest() {
mutableSendDataStateFlow.value = DataState.Loaded(mockSendView)
val viewModel = createViewModel(
state = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem("sendId"),
addEditSendType = AddEditSendType.EditItem("sendId"),
viewState = viewState,
),
addSendType = AddSendType.EditItem("sendId"),
addEditSendType = AddEditSendType.EditItem("sendId"),
)
viewModel.trySendAction(AddSendAction.CopyLinkClick)
viewModel.trySendAction(AddEditSendAction.CopyLinkClick)
verify(exactly = 1) {
clipboardManager.setText(
@@ -475,7 +475,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(AddSendAction.RemovePasswordClick)
viewModel.trySendAction(AddEditSendAction.RemovePasswordClick)
expectNoEvents()
}
}
@@ -489,7 +489,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
vaultRepository.removePasswordSend(sendId)
} returns RemovePasswordSendResult.Error(errorMessage = null, error = null)
val initialState = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendItemId = sendId),
addEditSendType = AddEditSendType.EditItem(sendItemId = sendId),
)
val mockSendView = createMockSendView(number = 1)
every {
@@ -502,15 +502,15 @@ class AddSendViewModelTest : BaseViewModelTest() {
mutableSendDataStateFlow.value = DataState.Loaded(mockSendView)
val viewModel = createViewModel(
state = initialState,
addSendType = AddSendType.EditItem(sendItemId = sendId),
addEditSendType = AddEditSendType.EditItem(sendItemId = sendId),
)
viewModel.stateFlow.test {
assertEquals(initialState, awaitItem())
viewModel.trySendAction(AddSendAction.RemovePasswordClick)
viewModel.trySendAction(AddEditSendAction.RemovePasswordClick)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Loading(
dialogState = AddEditSendState.DialogState.Loading(
message = R.string.removing_send_password.asText(),
),
),
@@ -518,7 +518,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.generic_error_message.asText(),
),
@@ -547,19 +547,19 @@ class AddSendViewModelTest : BaseViewModelTest() {
} returns DEFAULT_VIEW_STATE
mutableSendDataStateFlow.value = DataState.Loaded(mockSendView)
val initialState = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendItemId = sendId),
addEditSendType = AddEditSendType.EditItem(sendItemId = sendId),
)
val viewModel = createViewModel(
state = initialState,
addSendType = AddSendType.EditItem(sendItemId = sendId),
addEditSendType = AddEditSendType.EditItem(sendItemId = sendId),
)
viewModel.stateFlow.test {
assertEquals(initialState, awaitItem())
viewModel.trySendAction(AddSendAction.RemovePasswordClick)
viewModel.trySendAction(AddEditSendAction.RemovePasswordClick)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Loading(
dialogState = AddEditSendState.DialogState.Loading(
message = R.string.removing_send_password.asText(),
),
),
@@ -567,7 +567,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = errorMessage.asText(),
),
@@ -587,14 +587,14 @@ class AddSendViewModelTest : BaseViewModelTest() {
vaultRepository.removePasswordSend(sendId)
} returns RemovePasswordSendResult.Success(mockSendView)
val viewModel = createViewModel(
state = DEFAULT_STATE.copy(addSendType = AddSendType.EditItem(sendItemId = sendId)),
addSendType = AddSendType.EditItem(sendItemId = sendId),
state = DEFAULT_STATE.copy(addEditSendType = AddEditSendType.EditItem(sendItemId = sendId)),
addEditSendType = AddEditSendType.EditItem(sendItemId = sendId),
)
viewModel.eventFlow.test {
viewModel.trySendAction(AddSendAction.RemovePasswordClick)
viewModel.trySendAction(AddEditSendAction.RemovePasswordClick)
assertEquals(
AddSendEvent.ShowToast(R.string.send_password_removed.asText()),
AddEditSendEvent.ShowToast(R.string.send_password_removed.asText()),
awaitItem(),
)
}
@@ -608,7 +608,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
error = error,
)
val initialState = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem(sendItemId = sendId),
addEditSendType = AddEditSendType.EditItem(sendItemId = sendId),
)
val mockSendView = createMockSendView(number = 1)
every {
@@ -621,15 +621,15 @@ class AddSendViewModelTest : BaseViewModelTest() {
mutableSendDataStateFlow.value = DataState.Loaded(mockSendView)
val viewModel = createViewModel(
state = initialState,
addSendType = AddSendType.EditItem(sendItemId = sendId),
addEditSendType = AddEditSendType.EditItem(sendItemId = sendId),
)
viewModel.stateFlow.test {
assertEquals(initialState, awaitItem())
viewModel.trySendAction(AddSendAction.DeleteClick)
viewModel.trySendAction(AddEditSendAction.DeleteClick)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Loading(
dialogState = AddEditSendState.DialogState.Loading(
message = R.string.deleting.asText(),
),
),
@@ -637,7 +637,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.generic_error_message.asText(),
throwable = error,
@@ -653,14 +653,16 @@ class AddSendViewModelTest : BaseViewModelTest() {
val sendId = "mockId-1"
coEvery { vaultRepository.deleteSend(sendId) } returns DeleteSendResult.Success
val viewModel = createViewModel(
state = DEFAULT_STATE.copy(addSendType = AddSendType.EditItem(sendItemId = sendId)),
addSendType = AddSendType.EditItem(sendItemId = sendId),
state = DEFAULT_STATE.copy(
addEditSendType = AddEditSendType.EditItem(sendItemId = sendId),
),
addEditSendType = AddEditSendType.EditItem(sendItemId = sendId),
)
viewModel.eventFlow.test {
viewModel.trySendAction(AddSendAction.DeleteClick)
assertEquals(AddSendEvent.NavigateToRoot, awaitItem())
assertEquals(AddSendEvent.ShowToast(R.string.send_deleted.asText()), awaitItem())
viewModel.trySendAction(AddEditSendAction.DeleteClick)
assertEquals(AddEditSendEvent.NavigateToRoot, awaitItem())
assertEquals(AddEditSendEvent.ShowToast(R.string.send_deleted.asText()), awaitItem())
}
}
@@ -681,15 +683,15 @@ class AddSendViewModelTest : BaseViewModelTest() {
mutableSendDataStateFlow.value = DataState.Loaded(mockSendView)
val viewModel = createViewModel(
state = DEFAULT_STATE.copy(
addSendType = AddSendType.EditItem("sendId"),
addEditSendType = AddEditSendType.EditItem("sendId"),
viewState = viewState,
),
addSendType = AddSendType.EditItem("sendId"),
addEditSendType = AddEditSendType.EditItem("sendId"),
)
viewModel.eventFlow.test {
viewModel.trySendAction(AddSendAction.ShareLinkClick)
assertEquals(AddSendEvent.ShowShareSheet(sendUrl), awaitItem())
viewModel.trySendAction(AddEditSendAction.ShareLinkClick)
assertEquals(AddEditSendEvent.ShowShareSheet(sendUrl), awaitItem())
}
}
@@ -697,13 +699,13 @@ class AddSendViewModelTest : BaseViewModelTest() {
fun `DismissDialogClick should clear the dialog state`() {
val viewModel = createViewModel(
DEFAULT_STATE.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = "Fail Title".asText(),
message = "Fail Message".asText(),
),
),
)
viewModel.trySendAction(AddSendAction.DismissDialogClick)
viewModel.trySendAction(AddEditSendAction.DismissDialogClick)
assertEquals(DEFAULT_STATE, viewModel.stateFlow.value)
}
@@ -714,7 +716,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
// DEFAULT deletion date is "2023-11-03T00:00Z"
assertEquals(DEFAULT_STATE, viewModel.stateFlow.value)
viewModel.trySendAction(AddSendAction.DeletionDateChange(newDeletionDate))
viewModel.trySendAction(AddEditSendAction.DeletionDateChange(newDeletionDate))
assertEquals(
DEFAULT_STATE.copy(
@@ -732,7 +734,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
fun `FileChose should emit ShowToast`() = runTest {
val initialState = DEFAULT_STATE.copy(
viewState = DEFAULT_VIEW_STATE.copy(
selectedType = AddSendState.ViewState.Content.SendType.File(
selectedType = AddEditSendState.ViewState.Content.SendType.File(
uri = null,
name = null,
displaySize = null,
@@ -750,12 +752,12 @@ class AddSendViewModelTest : BaseViewModelTest() {
)
val viewModel = createViewModel(initialState)
viewModel.trySendAction(AddSendAction.FileChoose(fileData = fileData))
viewModel.trySendAction(AddEditSendAction.FileChoose(fileData = fileData))
assertEquals(
initialState.copy(
viewState = DEFAULT_VIEW_STATE.copy(
selectedType = AddSendState.ViewState.Content.SendType.File(
selectedType = AddEditSendState.ViewState.Content.SendType.File(
uri = uri,
name = fileName,
displaySize = null,
@@ -772,8 +774,8 @@ class AddSendViewModelTest : BaseViewModelTest() {
val arePermissionsGranted = true
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(AddSendAction.ChooseFileClick(arePermissionsGranted))
assertEquals(AddSendEvent.ShowChooserSheet(arePermissionsGranted), awaitItem())
viewModel.trySendAction(AddEditSendAction.ChooseFileClick(arePermissionsGranted))
assertEquals(AddEditSendEvent.ShowChooserSheet(arePermissionsGranted), awaitItem())
}
}
@@ -786,7 +788,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem())
viewModel.trySendAction(AddSendAction.NameChange("input"))
viewModel.trySendAction(AddEditSendAction.NameChange("input"))
assertEquals(DEFAULT_STATE.copy(viewState = expectedViewState), awaitItem())
}
}
@@ -800,7 +802,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem())
viewModel.trySendAction(AddSendAction.MaxAccessCountChange(5))
viewModel.trySendAction(AddEditSendAction.MaxAccessCountChange(5))
assertEquals(DEFAULT_STATE.copy(viewState = expectedViewState), awaitItem())
}
}
@@ -819,7 +821,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test {
assertEquals(initialState, awaitItem())
viewModel.trySendAction(AddSendAction.MaxAccessCountChange(0))
viewModel.trySendAction(AddEditSendAction.MaxAccessCountChange(0))
assertEquals(initialState.copy(viewState = expectedViewState), awaitItem())
}
}
@@ -828,7 +830,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
fun `TextChange should update text input`() = runTest {
val viewModel = createViewModel()
val expectedViewState = DEFAULT_VIEW_STATE.copy(
selectedType = AddSendState.ViewState.Content.SendType.Text(
selectedType = AddEditSendState.ViewState.Content.SendType.Text(
input = "input",
isHideByDefaultChecked = false,
),
@@ -836,7 +838,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem())
viewModel.trySendAction(AddSendAction.TextChange("input"))
viewModel.trySendAction(AddEditSendAction.TextChange("input"))
assertEquals(DEFAULT_STATE.copy(viewState = expectedViewState), awaitItem())
}
}
@@ -850,7 +852,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem())
viewModel.trySendAction(AddSendAction.NoteChange("input"))
viewModel.trySendAction(AddEditSendAction.NoteChange("input"))
assertEquals(DEFAULT_STATE.copy(viewState = expectedViewState), awaitItem())
}
}
@@ -864,7 +866,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem())
viewModel.trySendAction(AddSendAction.PasswordChange("input"))
viewModel.trySendAction(AddEditSendAction.PasswordChange("input"))
assertEquals(DEFAULT_STATE.copy(viewState = expectedViewState), awaitItem())
}
}
@@ -878,7 +880,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem())
viewModel.trySendAction(AddSendAction.DeactivateThisSendToggle(true))
viewModel.trySendAction(AddEditSendAction.DeactivateThisSendToggle(true))
assertEquals(DEFAULT_STATE.copy(viewState = expectedViewState), awaitItem())
}
}
@@ -892,7 +894,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem())
viewModel.trySendAction(AddSendAction.HideMyEmailToggle(isChecked = true))
viewModel.trySendAction(AddEditSendAction.HideMyEmailToggle(isChecked = true))
assertEquals(DEFAULT_STATE.copy(viewState = expectedViewState), awaitItem())
}
}
@@ -919,10 +921,10 @@ class AddSendViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel(initialState)
every { networkConnectionManager.isNetworkConnected } returns false
viewModel.trySendAction(AddSendAction.SaveClick)
viewModel.trySendAction(AddEditSendAction.SaveClick)
assertEquals(
initialState.copy(
dialogState = AddSendState.DialogState.Error(
dialogState = AddEditSendState.DialogState.Error(
title = R.string.internet_connection_required_title.asText(),
message = R.string.internet_connection_required_message.asText(),
),
@@ -938,17 +940,17 @@ class AddSendViewModelTest : BaseViewModelTest() {
}
private fun createViewModel(
state: AddSendState? = null,
addSendType: AddSendType = AddSendType.AddItem,
state: AddEditSendState? = null,
addEditSendType: AddEditSendType = AddEditSendType.AddItem,
sendType: SendItemType = SendItemType.TEXT,
activityToken: String? = null,
): AddSendViewModel = AddSendViewModel(
): AddEditSendViewModel = AddEditSendViewModel(
savedStateHandle = SavedStateHandle().apply {
set("state", state?.copy(addSendType = addSendType))
set("state", state?.copy(addEditSendType = addEditSendType))
set("activityToken", activityToken)
every {
toAddSendArgs()
} returns AddSendArgs(sendType = sendType, sendAddType = addSendType)
toAddEditSendArgs()
} returns AddEditSendArgs(sendType = sendType, addEditSendType = addEditSendType)
},
environmentRepo = environmentRepository,
specialCircumstanceManager = specialCircumstanceManager,
@@ -960,7 +962,7 @@ class AddSendViewModelTest : BaseViewModelTest() {
)
}
private val DEFAULT_COMMON_STATE = AddSendState.ViewState.Content.Common(
private val DEFAULT_COMMON_STATE = AddEditSendState.ViewState.Content.Common(
name = "",
currentAccessCount = null,
maxAccessCount = null,
@@ -975,20 +977,20 @@ private val DEFAULT_COMMON_STATE = AddSendState.ViewState.Content.Common(
isHideEmailAddressEnabled = true,
)
private val DEFAULT_SELECTED_TYPE_STATE = AddSendState.ViewState.Content.SendType.Text(
private val DEFAULT_SELECTED_TYPE_STATE = AddEditSendState.ViewState.Content.SendType.Text(
input = "",
isHideByDefaultChecked = false,
)
private val DEFAULT_VIEW_STATE = AddSendState.ViewState.Content(
private val DEFAULT_VIEW_STATE = AddEditSendState.ViewState.Content(
common = DEFAULT_COMMON_STATE,
selectedType = DEFAULT_SELECTED_TYPE_STATE,
)
private const val DEFAULT_ENVIRONMENT_URL = "https://send.bitwarden.com/#"
private val DEFAULT_STATE = AddSendState(
addSendType = AddSendType.AddItem,
private val DEFAULT_STATE = AddEditSendState(
addEditSendType = AddEditSendType.AddItem,
viewState = DEFAULT_VIEW_STATE,
dialogState = null,
shouldFinishOnComplete = false,

View File

@@ -1,9 +1,9 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend.util
package com.x8bit.bitwarden.ui.tools.feature.send.addedit.util
import com.bitwarden.send.SendType
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFileView
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSendView
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddSendState
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendState
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import java.time.Clock
@@ -11,7 +11,7 @@ import java.time.Instant
import java.time.ZoneOffset
import java.time.ZonedDateTime
class AddSendStateExtensionsTest {
class AddEditSendStateExtensionsTest {
@Test
fun `toSendView should create an appropriate SendView with file type`() {
@@ -31,7 +31,7 @@ class AddSendStateExtensionsTest {
val result = DEFAULT_VIEW_STATE
.copy(
selectedType = AddSendState.ViewState.Content.SendType.File(
selectedType = AddEditSendState.ViewState.Content.SendType.File(
name = "mockFileName-1",
displaySize = "mockSizeName-1",
sizeBytes = 1,
@@ -90,7 +90,7 @@ private val FIXED_CLOCK: Clock = Clock.fixed(
ZoneOffset.UTC,
)
private val DEFAULT_COMMON_STATE = AddSendState.ViewState.Content.Common(
private val DEFAULT_COMMON_STATE = AddEditSendState.ViewState.Content.Common(
name = "mockName-1",
currentAccessCount = 1,
maxAccessCount = 1,
@@ -105,12 +105,12 @@ private val DEFAULT_COMMON_STATE = AddSendState.ViewState.Content.Common(
isHideEmailAddressEnabled = true,
)
private val DEFAULT_SELECTED_TYPE_STATE = AddSendState.ViewState.Content.SendType.Text(
private val DEFAULT_SELECTED_TYPE_STATE = AddEditSendState.ViewState.Content.SendType.Text(
input = "mockText-1",
isHideByDefaultChecked = false,
)
private val DEFAULT_VIEW_STATE = AddSendState.ViewState.Content(
private val DEFAULT_VIEW_STATE = AddEditSendState.ViewState.Content(
common = DEFAULT_COMMON_STATE,
selectedType = DEFAULT_SELECTED_TYPE_STATE,
)

View File

@@ -1,8 +1,8 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend.util
package com.x8bit.bitwarden.ui.tools.feature.send.addedit.util
import com.bitwarden.send.SendType
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSendView
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddSendState
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendState
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import java.time.Clock
@@ -55,8 +55,8 @@ private val FIXED_CLOCK: Clock = Clock.fixed(
ZoneOffset.UTC,
)
private val DEFAULT_COMMON: AddSendState.ViewState.Content.Common =
AddSendState.ViewState.Content.Common(
private val DEFAULT_COMMON: AddEditSendState.ViewState.Content.Common =
AddEditSendState.ViewState.Content.Common(
name = "mockName-1",
currentAccessCount = 1,
maxAccessCount = 1,
@@ -77,22 +77,22 @@ private val DEFAULT_COMMON: AddSendState.ViewState.Content.Common =
isHideEmailAddressEnabled = true,
)
private val DEFAULT_TEXT_TYPE: AddSendState.ViewState.Content.SendType.Text =
AddSendState.ViewState.Content.SendType.Text(
private val DEFAULT_TEXT_TYPE: AddEditSendState.ViewState.Content.SendType.Text =
AddEditSendState.ViewState.Content.SendType.Text(
input = "mockText-1",
isHideByDefaultChecked = false,
)
private val DEFAULT_FILE_TYPE: AddSendState.ViewState.Content.SendType.File =
AddSendState.ViewState.Content.SendType.File(
private val DEFAULT_FILE_TYPE: AddEditSendState.ViewState.Content.SendType.File =
AddEditSendState.ViewState.Content.SendType.File(
name = "mockFileName-1",
displaySize = "mockSizeName-1",
sizeBytes = null,
uri = null,
)
private val DEFAULT_STATE: AddSendState.ViewState.Content =
AddSendState.ViewState.Content(
private val DEFAULT_STATE: AddEditSendState.ViewState.Content =
AddEditSendState.ViewState.Content(
common = DEFAULT_COMMON,
selectedType = DEFAULT_FILE_TYPE,
)

View File

@@ -1,9 +1,9 @@
package com.x8bit.bitwarden.ui.tools.feature.send.addsend.util
package com.x8bit.bitwarden.ui.tools.feature.send.addedit.util
import android.net.Uri
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddSendState
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendState
import io.mockk.mockk
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
@@ -16,7 +16,7 @@ class SpecialCircumstanceExtensionsTest {
@Test
fun `toSendType with TextSend should return Text SendType with correct text`() {
val text = "Share Text"
val expected = AddSendState.ViewState.Content.SendType.Text(
val expected = AddEditSendState.ViewState.Content.SendType.Text(
input = text,
isHideByDefaultChecked = false,
)
@@ -38,7 +38,7 @@ class SpecialCircumstanceExtensionsTest {
val uri = mockk<Uri>()
val fileName = "Share Name"
val sizeBytes = 100L
val expected = AddSendState.ViewState.Content.SendType.File(
val expected = AddEditSendState.ViewState.Content.SendType.File(
uri = uri,
name = fileName,
sizeBytes = sizeBytes,

View File

@@ -15,8 +15,8 @@ import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.model.SendItemType
import com.x8bit.bitwarden.ui.util.assertNoDialogExists
import com.x8bit.bitwarden.ui.util.isProgressBar

View File

@@ -37,8 +37,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.addsend.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.ModeType
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.AddEditSendRoute
import com.x8bit.bitwarden.ui.tools.feature.send.addedit.ModeType
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