Refactored VaultAddItem UI State (#417)

This commit is contained in:
Ramsey Smith
2024-06-20 17:08:07 +01:00
committed by Álison Fernandes
parent acdce7a07b
commit 772d6693a6
13 changed files with 1007 additions and 1855 deletions
@@ -20,11 +20,11 @@ import kotlinx.collections.immutable.toImmutableList
*/
@Composable
fun AddEditItemContent(
viewState: VaultAddItemState.ViewState.Content,
state: VaultAddItemState.ViewState.Content,
isAddItemMode: Boolean,
onTypeOptionClicked: (VaultAddItemState.ItemTypeOption) -> Unit,
commonTypeHandlers: VaultAddItemCommonTypeHandlers,
loginItemTypeHandlers: VaultAddLoginItemTypeHandlers,
secureNotesTypeHandlers: VaultAddSecureNotesItemTypeHandlers,
modifier: Modifier = Modifier,
) {
LazyColumn(
@@ -42,35 +42,37 @@ fun AddEditItemContent(
item {
Spacer(modifier = Modifier.height(8.dp))
TypeOptionsItem(
content = viewState,
itemType = state.type,
onTypeOptionClicked = onTypeOptionClicked,
modifier = Modifier.padding(horizontal = 16.dp),
)
}
}
when (viewState) {
is VaultAddItemState.ViewState.Content.Login -> {
when (state.type) {
is VaultAddItemState.ViewState.Content.ItemType.Login -> {
addEditLoginItems(
state = viewState,
commonState = state.common,
loginState = state.type,
isAddItemMode = isAddItemMode,
commonActionHandler = commonTypeHandlers,
loginItemTypeHandlers = loginItemTypeHandlers,
)
}
is VaultAddItemState.ViewState.Content.Card -> {
is VaultAddItemState.ViewState.Content.ItemType.Card -> {
// TODO(BIT-507): Create UI for card-type item creation
}
is VaultAddItemState.ViewState.Content.Identity -> {
is VaultAddItemState.ViewState.Content.ItemType.Identity -> {
// TODO(BIT-667): Create UI for identity-type item creation
}
is VaultAddItemState.ViewState.Content.SecureNotes -> {
is VaultAddItemState.ViewState.Content.ItemType.SecureNotes -> {
addEditSecureNotesItems(
state = viewState,
commonState = state.common,
isAddItemMode = isAddItemMode,
secureNotesTypeHandlers = secureNotesTypeHandlers,
commonTypeHandlers = commonTypeHandlers,
)
}
}
@@ -83,7 +85,7 @@ fun AddEditItemContent(
@Composable
private fun TypeOptionsItem(
content: VaultAddItemState.ViewState.Content,
itemType: VaultAddItemState.ViewState.Content.ItemType,
onTypeOptionClicked: (VaultAddItemState.ItemTypeOption) -> Unit,
modifier: Modifier,
) {
@@ -93,7 +95,7 @@ private fun TypeOptionsItem(
BitwardenMultiSelectButton(
label = stringResource(id = R.string.type),
options = optionsWithStrings.values.toImmutableList(),
selectedOption = stringResource(id = content.displayStringResId),
selectedOption = stringResource(id = itemType.displayStringResId),
onOptionSelected = { selectedOption ->
val selectedOptionId = optionsWithStrings
.entries
@@ -34,16 +34,18 @@ import kotlinx.collections.immutable.toImmutableList
*/
@Suppress("LongMethod")
fun LazyListScope.addEditLoginItems(
state: VaultAddItemState.ViewState.Content.Login,
commonState: VaultAddItemState.ViewState.Content.Common,
loginState: VaultAddItemState.ViewState.Content.ItemType.Login,
isAddItemMode: Boolean,
commonActionHandler: VaultAddItemCommonTypeHandlers,
loginItemTypeHandlers: VaultAddLoginItemTypeHandlers,
) {
item {
Spacer(modifier = Modifier.height(8.dp))
BitwardenTextField(
label = stringResource(id = R.string.name),
value = state.name,
onValueChange = loginItemTypeHandlers.onNameTextChange,
value = commonState.name,
onValueChange = commonActionHandler.onNameTextChange,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
@@ -54,7 +56,7 @@ fun LazyListScope.addEditLoginItems(
Spacer(modifier = Modifier.height(8.dp))
BitwardenTextFieldWithActions(
label = stringResource(id = R.string.username),
value = state.username,
value = loginState.username,
onValueChange = loginItemTypeHandlers.onUsernameTextChange,
actions = {
BitwardenIconButtonWithResource(
@@ -73,7 +75,7 @@ fun LazyListScope.addEditLoginItems(
Spacer(modifier = Modifier.height(8.dp))
BitwardenPasswordFieldWithActions(
label = stringResource(id = R.string.password),
value = state.password,
value = loginState.password,
onValueChange = loginItemTypeHandlers.onPasswordTextChange,
modifier = Modifier
.padding(horizontal = 16.dp),
@@ -131,7 +133,7 @@ fun LazyListScope.addEditLoginItems(
Spacer(modifier = Modifier.height(8.dp))
BitwardenTextFieldWithActions(
label = stringResource(id = R.string.uri),
value = state.uri,
value = loginState.uri,
onValueChange = loginItemTypeHandlers.onUriTextChange,
actions = {
BitwardenIconButtonWithResource(
@@ -171,9 +173,9 @@ fun LazyListScope.addEditLoginItems(
Spacer(modifier = Modifier.height(8.dp))
BitwardenMultiSelectButton(
label = stringResource(id = R.string.folder),
options = state.availableFolders.map { it.invoke() }.toImmutableList(),
selectedOption = state.folderName.invoke(),
onOptionSelected = loginItemTypeHandlers.onFolderTextChange,
options = commonState.availableFolders.map { it.invoke() }.toImmutableList(),
selectedOption = commonState.folderName.invoke(),
onOptionSelected = commonActionHandler.onFolderTextChange,
modifier = Modifier.padding(horizontal = 16.dp),
)
}
@@ -184,8 +186,8 @@ fun LazyListScope.addEditLoginItems(
label = stringResource(
id = R.string.favorite,
),
isChecked = state.favorite,
onCheckedChange = loginItemTypeHandlers.onToggleFavorite,
isChecked = commonState.favorite,
onCheckedChange = commonActionHandler.onToggleFavorite,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
@@ -196,13 +198,13 @@ fun LazyListScope.addEditLoginItems(
Spacer(modifier = Modifier.height(16.dp))
BitwardenSwitchWithActions(
label = stringResource(id = R.string.password_prompt),
isChecked = state.masterPasswordReprompt,
onCheckedChange = loginItemTypeHandlers.onToggleMasterPasswordReprompt,
isChecked = commonState.masterPasswordReprompt,
onCheckedChange = commonActionHandler.onToggleMasterPasswordReprompt,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
actions = {
IconButton(onClick = loginItemTypeHandlers.onTooltipClick) {
IconButton(onClick = commonActionHandler.onTooltipClick) {
Icon(
painter = painterResource(id = R.drawable.ic_tooltip),
tint = MaterialTheme.colorScheme.onSurface,
@@ -230,8 +232,8 @@ fun LazyListScope.addEditLoginItems(
BitwardenTextField(
singleLine = false,
label = stringResource(id = R.string.notes),
value = state.notes,
onValueChange = loginItemTypeHandlers.onNotesTextChange,
value = commonState.notes,
onValueChange = commonActionHandler.onNotesTextChange,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
@@ -248,10 +250,10 @@ fun LazyListScope.addEditLoginItems(
)
}
items(state.customFieldData) { customItem ->
items(commonState.customFieldData) { customItem ->
AddEditCustomField(
customItem,
onCustomFieldValueChange = loginItemTypeHandlers.onCustomFieldValueChange,
onCustomFieldValueChange = commonActionHandler.onCustomFieldValueChange,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
@@ -265,7 +267,7 @@ fun LazyListScope.addEditLoginItems(
item {
Spacer(modifier = Modifier.height(16.dp))
AddEditCustomFieldsButton(
onFinishNamingClick = loginItemTypeHandlers.onAddNewCustomFieldClick,
onFinishNamingClick = commonActionHandler.onAddNewCustomFieldClick,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
@@ -287,9 +289,9 @@ fun LazyListScope.addEditLoginItems(
Spacer(modifier = Modifier.height(8.dp))
BitwardenMultiSelectButton(
label = stringResource(id = R.string.who_owns_this_item),
options = state.availableOwners.toImmutableList(),
selectedOption = state.ownership,
onOptionSelected = loginItemTypeHandlers.onOwnershipTextChange,
options = commonState.availableOwners.toImmutableList(),
selectedOption = commonState.ownership,
onOptionSelected = commonActionHandler.onOwnershipTextChange,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
@@ -28,16 +28,16 @@ import kotlinx.collections.immutable.toImmutableList
*/
@Suppress("LongMethod")
fun LazyListScope.addEditSecureNotesItems(
state: VaultAddItemState.ViewState.Content.SecureNotes,
commonState: VaultAddItemState.ViewState.Content.Common,
isAddItemMode: Boolean,
secureNotesTypeHandlers: VaultAddSecureNotesItemTypeHandlers,
commonTypeHandlers: VaultAddItemCommonTypeHandlers,
) {
item {
Spacer(modifier = Modifier.height(8.dp))
BitwardenTextField(
label = stringResource(id = R.string.name),
value = state.name,
onValueChange = secureNotesTypeHandlers.onNameTextChange,
value = commonState.name,
onValueChange = commonTypeHandlers.onNameTextChange,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
@@ -58,9 +58,9 @@ fun LazyListScope.addEditSecureNotesItems(
Spacer(modifier = Modifier.height(8.dp))
BitwardenMultiSelectButton(
label = stringResource(id = R.string.folder),
options = state.availableFolders.map { it.invoke() }.toImmutableList(),
selectedOption = state.folderName.invoke(),
onOptionSelected = secureNotesTypeHandlers.onFolderTextChange,
options = commonState.availableFolders.map { it.invoke() }.toImmutableList(),
selectedOption = commonState.folderName.invoke(),
onOptionSelected = commonTypeHandlers.onFolderTextChange,
modifier = Modifier
.padding(horizontal = 16.dp),
)
@@ -70,8 +70,8 @@ fun LazyListScope.addEditSecureNotesItems(
Spacer(modifier = Modifier.height(16.dp))
BitwardenSwitch(
label = stringResource(id = R.string.favorite),
isChecked = state.favorite,
onCheckedChange = secureNotesTypeHandlers.onToggleFavorite,
isChecked = commonState.favorite,
onCheckedChange = commonTypeHandlers.onToggleFavorite,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
@@ -82,13 +82,13 @@ fun LazyListScope.addEditSecureNotesItems(
Spacer(modifier = Modifier.height(16.dp))
BitwardenSwitchWithActions(
label = stringResource(id = R.string.password_prompt),
isChecked = state.masterPasswordReprompt,
onCheckedChange = secureNotesTypeHandlers.onToggleMasterPasswordReprompt,
isChecked = commonState.masterPasswordReprompt,
onCheckedChange = commonTypeHandlers.onToggleMasterPasswordReprompt,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
actions = {
IconButton(onClick = secureNotesTypeHandlers.onTooltipClick) {
IconButton(onClick = commonTypeHandlers.onTooltipClick) {
Icon(
painter = painterResource(id = R.drawable.ic_tooltip),
tint = MaterialTheme.colorScheme.onSurface,
@@ -116,8 +116,8 @@ fun LazyListScope.addEditSecureNotesItems(
BitwardenTextField(
singleLine = false,
label = stringResource(id = R.string.notes),
value = state.notes,
onValueChange = secureNotesTypeHandlers.onNotesTextChange,
value = commonState.notes,
onValueChange = commonTypeHandlers.onNotesTextChange,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
@@ -133,11 +133,10 @@ fun LazyListScope.addEditSecureNotesItems(
.padding(horizontal = 16.dp),
)
}
items(state.customFieldData) { customItem ->
items(commonState.customFieldData) { customItem ->
AddEditCustomField(
customItem,
onCustomFieldValueChange = secureNotesTypeHandlers.onCustomFieldValueChange,
onCustomFieldValueChange = commonTypeHandlers.onCustomFieldValueChange,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
@@ -147,7 +146,7 @@ fun LazyListScope.addEditSecureNotesItems(
item {
Spacer(modifier = Modifier.height(16.dp))
AddEditCustomFieldsButton(
onFinishNamingClick = secureNotesTypeHandlers.onAddNewCustomFieldClick,
onFinishNamingClick = commonTypeHandlers.onAddNewCustomFieldClick,
options = persistentListOf(
CustomFieldType.TEXT,
CustomFieldType.HIDDEN,
@@ -174,9 +173,9 @@ fun LazyListScope.addEditSecureNotesItems(
Spacer(modifier = Modifier.height(8.dp))
BitwardenMultiSelectButton(
label = stringResource(id = R.string.who_owns_this_item),
options = state.availableOwners.toImmutableList(),
selectedOption = state.ownership,
onOptionSelected = secureNotesTypeHandlers.onOwnershipTextChange,
options = commonState.availableOwners.toImmutableList(),
selectedOption = commonState.ownership,
onOptionSelected = commonTypeHandlers.onOwnershipTextChange,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
@@ -4,8 +4,8 @@ import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.vault.feature.additem.model.CustomFieldType
/**
* A collection of handler functions specifically tailored for managing actions
* within the context of adding secure note items to a vault.
* A collection of handler functions for managing actions common
* within the context of adding items to a vault.
*
* @property onNameTextChange Handles the action when the name text is changed.
* @property onFolderTextChange Handles the action when the folder text is changed.
@@ -20,7 +20,7 @@ import com.x8bit.bitwarden.ui.vault.feature.additem.model.CustomFieldType
* @property onCustomFieldValueChange Handles the action when the field's value changes
*/
@Suppress("LongParameterList")
class VaultAddSecureNotesItemTypeHandlers(
class VaultAddItemCommonTypeHandlers(
val onNameTextChange: (String) -> Unit,
val onFolderTextChange: (String) -> Unit,
val onToggleFavorite: (Boolean) -> Unit,
@@ -34,54 +34,54 @@ class VaultAddSecureNotesItemTypeHandlers(
companion object {
/**
* Creates an instance of [VaultAddSecureNotesItemTypeHandlers] by binding actions
* Creates an instance of [VaultAddItemCommonTypeHandlers] by binding actions
* to the provided [VaultAddItemViewModel].
*/
@Suppress("LongMethod")
fun create(viewModel: VaultAddItemViewModel): VaultAddSecureNotesItemTypeHandlers {
return VaultAddSecureNotesItemTypeHandlers(
fun create(viewModel: VaultAddItemViewModel): VaultAddItemCommonTypeHandlers {
return VaultAddItemCommonTypeHandlers(
onNameTextChange = { newName ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.SecureNotesType.NameTextChange(newName),
VaultAddItemAction.Common.NameTextChange(newName),
)
},
onFolderTextChange = { newFolder ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.SecureNotesType.FolderChange(
VaultAddItemAction.Common.FolderChange(
newFolder.asText(),
),
)
},
onToggleFavorite = { isFavorite ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.SecureNotesType.ToggleFavorite(isFavorite),
VaultAddItemAction.Common.ToggleFavorite(isFavorite),
)
},
onToggleMasterPasswordReprompt = { isMasterPasswordReprompt ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.SecureNotesType.ToggleMasterPasswordReprompt(
VaultAddItemAction.Common.ToggleMasterPasswordReprompt(
isMasterPasswordReprompt,
),
)
},
onNotesTextChange = { newNotes ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.SecureNotesType.NotesTextChange(newNotes),
VaultAddItemAction.Common.NotesTextChange(newNotes),
)
},
onOwnershipTextChange = { newOwnership ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.SecureNotesType.OwnershipChange(newOwnership),
VaultAddItemAction.Common.OwnershipChange(newOwnership),
)
},
onTooltipClick = {
viewModel.trySendAction(
VaultAddItemAction.ItemType.SecureNotesType.TooltipClick,
VaultAddItemAction.Common.TooltipClick,
)
},
onAddNewCustomFieldClick = { newCustomFieldType, name ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.SecureNotesType.AddNewCustomFieldClick(
VaultAddItemAction.Common.AddNewCustomFieldClick(
newCustomFieldType,
name,
),
@@ -89,7 +89,7 @@ class VaultAddSecureNotesItemTypeHandlers(
},
onCustomFieldValueChange = { newValue ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.SecureNotesType.CustomFieldValueChange(
VaultAddItemAction.Common.CustomFieldValueChange(
newValue,
),
)
@@ -55,14 +55,14 @@ fun VaultAddItemScreen(
VaultAddLoginItemTypeHandlers.create(viewModel = viewModel)
}
val secureNotesTypeHandlers = remember(viewModel) {
VaultAddSecureNotesItemTypeHandlers.create(viewModel = viewModel)
val commonTypeHandlers = remember(viewModel) {
VaultAddItemCommonTypeHandlers.create(viewModel = viewModel)
}
VaultAddEditItemDialogs(
dialogState = state.dialog,
onDismissRequest = remember(viewModel) {
{ viewModel.trySendAction(VaultAddItemAction.DismissDialog) }
{ viewModel.trySendAction(VaultAddItemAction.Common.DismissDialog) }
},
)
@@ -77,14 +77,14 @@ fun VaultAddItemScreen(
navigationIcon = painterResource(id = R.drawable.ic_close),
navigationIconContentDescription = stringResource(id = R.string.close),
onNavigationIconClick = remember(viewModel) {
{ viewModel.trySendAction(VaultAddItemAction.CloseClick) }
{ viewModel.trySendAction(VaultAddItemAction.Common.CloseClick) }
},
scrollBehavior = scrollBehavior,
actions = {
BitwardenTextButton(
label = stringResource(id = R.string.save),
onClick = remember(viewModel) {
{ viewModel.trySendAction(VaultAddItemAction.SaveClick) }
{ viewModel.trySendAction(VaultAddItemAction.Common.SaveClick) }
},
)
},
@@ -94,13 +94,13 @@ fun VaultAddItemScreen(
when (val viewState = state.viewState) {
is VaultAddItemState.ViewState.Content -> {
AddEditItemContent(
viewState = viewState,
state = viewState,
isAddItemMode = state.isAddItemMode,
onTypeOptionClicked = remember(viewModel) {
{ viewModel.trySendAction(VaultAddItemAction.TypeOptionSelect(it)) }
{ viewModel.trySendAction(VaultAddItemAction.Common.TypeOptionSelect(it)) }
},
loginItemTypeHandlers = loginItemTypeHandlers,
secureNotesTypeHandlers = secureNotesTypeHandlers,
commonTypeHandlers = commonTypeHandlers,
modifier = Modifier
.imePadding()
.padding(innerPadding)
@@ -1,22 +1,13 @@
package com.x8bit.bitwarden.ui.vault.feature.additem
import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.vault.feature.additem.model.CustomFieldType
/**
* A collection of handler functions specifically tailored for managing actions
* within the context of adding login items to a vault.
*
* @property onNameTextChange Handles the action when the name text is changed.
* @property onUsernameTextChange Handles the action when the username text is changed.
* @property onPasswordTextChange Handles the action when the password text is changed.
* @property onUriTextChange Handles the action when the URI text is changed.
* @property onFolderTextChange Handles the action when the folder text is changed.
* @property onToggleFavorite Handles the action when the favorite toggle is changed.
* @property onToggleMasterPasswordReprompt Handles the action when the master password
* reprompt toggle is changed.
* @property onNotesTextChange Handles the action when the notes text is changed.
* @property onOwnershipTextChange Handles the action when the ownership text is changed.
* @property onOpenUsernameGeneratorClick Handles the action when the username generator
* button is clicked.
* @property onPasswordCheckerClick Handles the action when the password checker
@@ -26,31 +17,18 @@ import com.x8bit.bitwarden.ui.vault.feature.additem.model.CustomFieldType
* @property onSetupTotpClick Handles the action when the setup TOTP button is clicked.
* @property onUriSettingsClick Handles the action when the URI settings button is clicked.
* @property onAddNewUriClick Handles the action when the add new URI button is clicked.
* @property onTooltipClick Handles the action when the tooltip button is clicked.
* @property onAddNewCustomFieldClick Handles the action when the add new custom field
* button is clicked.
* @property onCustomFieldValueChange Handles the action when the field's value changes
*/
@Suppress("LongParameterList")
class VaultAddLoginItemTypeHandlers(
val onNameTextChange: (String) -> Unit,
val onUsernameTextChange: (String) -> Unit,
val onPasswordTextChange: (String) -> Unit,
val onUriTextChange: (String) -> Unit,
val onFolderTextChange: (String) -> Unit,
val onToggleFavorite: (Boolean) -> Unit,
val onToggleMasterPasswordReprompt: (Boolean) -> Unit,
val onNotesTextChange: (String) -> Unit,
val onOwnershipTextChange: (String) -> Unit,
val onOpenUsernameGeneratorClick: () -> Unit,
val onPasswordCheckerClick: () -> Unit,
val onOpenPasswordGeneratorClick: () -> Unit,
val onSetupTotpClick: () -> Unit,
val onUriSettingsClick: () -> Unit,
val onAddNewUriClick: () -> Unit,
val onTooltipClick: () -> Unit,
val onAddNewCustomFieldClick: (CustomFieldType, String) -> Unit,
val onCustomFieldValueChange: (VaultAddItemState.Custom) -> Unit,
) {
companion object {
@@ -64,11 +42,6 @@ class VaultAddLoginItemTypeHandlers(
@Suppress("LongMethod")
fun create(viewModel: VaultAddItemViewModel): VaultAddLoginItemTypeHandlers {
return VaultAddLoginItemTypeHandlers(
onNameTextChange = { newName ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.LoginType.NameTextChange(newName),
)
},
onUsernameTextChange = { newUsername ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.LoginType.UsernameTextChange(newUsername),
@@ -84,33 +57,6 @@ class VaultAddLoginItemTypeHandlers(
VaultAddItemAction.ItemType.LoginType.UriTextChange(newUri),
)
},
onFolderTextChange = { newFolder ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.LoginType.FolderChange(newFolder.asText()),
)
},
onToggleFavorite = { isFavorite ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.LoginType.ToggleFavorite(isFavorite),
)
},
onToggleMasterPasswordReprompt = { isMasterPasswordReprompt ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.LoginType.ToggleMasterPasswordReprompt(
isMasterPasswordReprompt,
),
)
},
onNotesTextChange = { newNotes ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.LoginType.NotesTextChange(newNotes),
)
},
onOwnershipTextChange = { newOwnership ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.LoginType.OwnershipChange(newOwnership),
)
},
onOpenUsernameGeneratorClick = {
viewModel.trySendAction(
VaultAddItemAction.ItemType.LoginType.OpenUsernameGeneratorClick,
@@ -135,24 +81,6 @@ class VaultAddLoginItemTypeHandlers(
onAddNewUriClick = {
viewModel.trySendAction(VaultAddItemAction.ItemType.LoginType.AddNewUriClick)
},
onTooltipClick = {
viewModel.trySendAction(VaultAddItemAction.ItemType.LoginType.TooltipClick)
},
onAddNewCustomFieldClick = { customFieldType, name ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.LoginType.AddNewCustomFieldClick(
customFieldType = customFieldType,
name = name,
),
)
},
onCustomFieldValueChange = { customField ->
viewModel.trySendAction(
VaultAddItemAction.ItemType.LoginType.CustomFieldValueChange(
customField = customField,
),
)
},
)
}
}
@@ -15,55 +15,36 @@ import java.util.UUID
* Transforms [CipherView] into [VaultAddItemState.ViewState].
*/
fun CipherView.toViewState(): VaultAddItemState.ViewState =
when (type) {
CipherType.LOGIN -> {
val loginView = requireNotNull(this.login)
VaultAddItemState.ViewState.Content.Login(
originalCipher = this,
name = this.name,
username = loginView.username.orEmpty(),
password = loginView.password.orEmpty(),
uri = loginView.uris?.firstOrNull()?.uri.orEmpty(),
favorite = this.favorite,
masterPasswordReprompt = this.reprompt == CipherRepromptType.PASSWORD,
notes = this.notes.orEmpty(),
// TODO: Update these properties to pull folder from data layer (BIT-501)
folderName = this.folderId?.asText() ?: R.string.folder_none.asText(),
availableFolders = emptyList(),
// TODO: Update this property to pull owner from data layer (BIT-501)
ownership = "",
// TODO: Update this property to pull available owners from data layer (BIT-501)
availableOwners = emptyList(),
customFieldData = this.fields.orEmpty().map { it.toCustomField() },
)
}
VaultAddItemState.ViewState.Content(
type = when (type) {
CipherType.LOGIN -> {
VaultAddItemState.ViewState.Content.ItemType.Login(
username = login?.username.orEmpty(),
password = login?.password.orEmpty(),
uri = login?.uris?.firstOrNull()?.uri.orEmpty(),
)
}
CipherType.SECURE_NOTE -> {
VaultAddItemState.ViewState.Content.SecureNotes(
originalCipher = this,
name = this.name,
favorite = this.favorite,
masterPasswordReprompt = this.reprompt == CipherRepromptType.PASSWORD,
notes = this.notes.orEmpty(),
// TODO: Update these properties to pull folder from data layer (BIT-501)
folderName = this.folderId?.asText() ?: R.string.folder_none.asText(),
availableFolders = emptyList(),
// TODO: Update this property to pull owner from data layer (BIT-501)
ownership = "",
// TODO: Update this property to pull available owners from data layer (BIT-501)
availableOwners = emptyList(),
customFieldData = this.fields.orEmpty().map { it.toCustomField() },
)
}
CipherType.CARD -> VaultAddItemState.ViewState.Error(
message = "Not yet implemented.".asText(),
)
CipherType.IDENTITY -> VaultAddItemState.ViewState.Error(
message = "Not yet implemented.".asText(),
)
}
CipherType.SECURE_NOTE -> VaultAddItemState.ViewState.Content.ItemType.SecureNotes
CipherType.CARD -> VaultAddItemState.ViewState.Content.ItemType.Card
CipherType.IDENTITY -> VaultAddItemState.ViewState.Content.ItemType.Identity
},
common = VaultAddItemState.ViewState.Content.Common(
originalCipher = this,
name = this.name,
favorite = this.favorite,
masterPasswordReprompt = this.reprompt == CipherRepromptType.PASSWORD,
notes = this.notes.orEmpty(),
// TODO: Update these properties to pull folder from data layer (BIT-501)
folderName = this.folderId?.asText() ?: R.string.folder_none.asText(),
availableFolders = emptyList(),
// TODO: Update this property to pull owner from data layer (BIT-501)
ownership = "",
// TODO: Update this property to pull available owners from data layer (BIT-501)
availableOwners = emptyList(),
customFieldData = this.fields.orEmpty().map { it.toCustomField() },
),
)
private fun FieldView.toCustomField() =
when (this.type) {
@@ -100,53 +100,53 @@ fun VaultData.toViewState(): VaultState.ViewState =
}
/**
* Transforms a [VaultAddItemState.ViewState.Content] into [CipherView].
* Transforms a [VaultAddItemState.ViewState.ItemType] into [CipherView].
*/
fun VaultAddItemState.ViewState.Content.toCipherView(): CipherView =
CipherView(
// Pulled from original cipher when editing, otherwise uses defaults
id = this.originalCipher?.id,
collectionIds = this.originalCipher?.collectionIds.orEmpty(),
key = this.originalCipher?.key,
edit = this.originalCipher?.edit ?: true,
viewPassword = this.originalCipher?.viewPassword ?: true,
localData = this.originalCipher?.localData,
attachments = this.originalCipher?.attachments,
organizationUseTotp = this.originalCipher?.organizationUseTotp ?: false,
passwordHistory = this.originalCipher?.passwordHistory,
creationDate = this.originalCipher?.creationDate ?: Instant.now(),
deletedDate = this.originalCipher?.deletedDate,
revisionDate = this.originalCipher?.revisionDate ?: Instant.now(),
id = common.originalCipher?.id,
collectionIds = common.originalCipher?.collectionIds.orEmpty(),
key = common.originalCipher?.key,
edit = common.originalCipher?.edit ?: true,
viewPassword = common.originalCipher?.viewPassword ?: true,
localData = common.originalCipher?.localData,
attachments = common.originalCipher?.attachments,
organizationUseTotp = common.originalCipher?.organizationUseTotp ?: false,
passwordHistory = common.originalCipher?.passwordHistory,
creationDate = common.originalCipher?.creationDate ?: Instant.now(),
deletedDate = common.originalCipher?.deletedDate,
revisionDate = common.originalCipher?.revisionDate ?: Instant.now(),
// Type specific section
type = this.toCipherType(),
identity = this.toIdentityView(),
secureNote = this.toSecureNotesView(),
login = this.toLoginView(),
card = this.toCardView(),
type = type.toCipherType(),
identity = type.toIdentityView(),
secureNote = type.toSecureNotesView(),
login = type.toLoginView(common = common),
card = type.toCardView(),
// Fields we always grab from the UI
name = this.name,
notes = this.notes,
favorite = this.favorite,
name = common.name,
notes = common.notes,
favorite = common.favorite,
// TODO Use real folder ID (BIT-528)
folderId = this.originalCipher?.folderId,
folderId = common.originalCipher?.folderId,
// TODO Use real organization ID (BIT-780)
organizationId = this.originalCipher?.organizationId,
reprompt = this.toCipherRepromptType(),
fields = this.customFieldData.map { it.toFieldView() },
organizationId = common.originalCipher?.organizationId,
reprompt = common.toCipherRepromptType(),
fields = common.customFieldData.map { it.toFieldView() },
)
private fun VaultAddItemState.ViewState.Content.toCipherType(): CipherType =
private fun VaultAddItemState.ViewState.Content.ItemType.toCipherType(): CipherType =
when (this) {
is VaultAddItemState.ViewState.Content.Card -> CipherType.CARD
is VaultAddItemState.ViewState.Content.Identity -> CipherType.IDENTITY
is VaultAddItemState.ViewState.Content.Login -> CipherType.LOGIN
is VaultAddItemState.ViewState.Content.SecureNotes -> CipherType.SECURE_NOTE
is VaultAddItemState.ViewState.Content.ItemType.Card -> CipherType.CARD
is VaultAddItemState.ViewState.Content.ItemType.Identity -> CipherType.IDENTITY
is VaultAddItemState.ViewState.Content.ItemType.Login -> CipherType.LOGIN
is VaultAddItemState.ViewState.Content.ItemType.SecureNotes -> CipherType.SECURE_NOTE
}
private fun VaultAddItemState.ViewState.Content.toCardView(): CardView? =
(this as? VaultAddItemState.ViewState.Content.Card)?.let {
private fun VaultAddItemState.ViewState.Content.ItemType.toCardView(): CardView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.Card)?.let {
// TODO Create real CardView from Content (BIT-668)
CardView(
cardholderName = null,
@@ -158,8 +158,8 @@ private fun VaultAddItemState.ViewState.Content.toCardView(): CardView? =
)
}
private fun VaultAddItemState.ViewState.Content.toIdentityView(): IdentityView? =
(this as? VaultAddItemState.ViewState.Content.Identity)?.let {
private fun VaultAddItemState.ViewState.Content.ItemType.toIdentityView(): IdentityView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.Identity)?.let {
// TODO Create real IdentityView from Content (BIT-508)
IdentityView(
title = null,
@@ -183,12 +183,14 @@ private fun VaultAddItemState.ViewState.Content.toIdentityView(): IdentityView?
)
}
private fun VaultAddItemState.ViewState.Content.toLoginView(): LoginView? =
(this as? VaultAddItemState.ViewState.Content.Login)?.let {
private fun VaultAddItemState.ViewState.Content.ItemType.toLoginView(
common: VaultAddItemState.ViewState.Content.Common,
): LoginView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.Login)?.let {
LoginView(
username = it.username,
password = it.password,
passwordRevisionDate = it.originalCipher?.login?.passwordRevisionDate,
passwordRevisionDate = common.originalCipher?.login?.passwordRevisionDate,
uris = listOf(
// TODO Implement URI list (BIT-1094)
LoginUriView(
@@ -198,18 +200,18 @@ private fun VaultAddItemState.ViewState.Content.toLoginView(): LoginView? =
),
),
// TODO Implement TOTP (BIT-1066)
totp = it.originalCipher?.login?.totp,
autofillOnPageLoad = it.originalCipher?.login?.autofillOnPageLoad,
totp = common.originalCipher?.login?.totp,
autofillOnPageLoad = common.originalCipher?.login?.autofillOnPageLoad,
)
}
private fun VaultAddItemState.ViewState.Content.toSecureNotesView(): SecureNoteView? =
(this as? VaultAddItemState.ViewState.Content.SecureNotes)?.let {
private fun VaultAddItemState.ViewState.Content.ItemType.toSecureNotesView(): SecureNoteView? =
(this as? VaultAddItemState.ViewState.Content.ItemType.SecureNotes)?.let {
SecureNoteView(type = SecureNoteType.GENERIC)
}
private fun VaultAddItemState.ViewState.Content.toCipherRepromptType(): CipherRepromptType =
if (this.masterPasswordReprompt) {
private fun VaultAddItemState.ViewState.Content.Common.toCipherRepromptType(): CipherRepromptType =
if (masterPasswordReprompt) {
CipherRepromptType.PASSWORD
} else {
CipherRepromptType.NONE