mirror of
https://github.com/bitwarden/android.git
synced 2026-07-29 17:33:28 -05:00
Refactored VaultAddItem UI State (#417)
This commit is contained in:
committed by
Álison Fernandes
parent
acdce7a07b
commit
772d6693a6
+15
-13
@@ -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
|
||||
|
||||
+24
-22
@@ -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),
|
||||
|
||||
+20
-21
@@ -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),
|
||||
|
||||
+15
-15
@@ -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,
|
||||
),
|
||||
)
|
||||
+8
-8
@@ -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)
|
||||
|
||||
+350
-640
File diff suppressed because it is too large
Load Diff
-72
@@ -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,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+29
-48
@@ -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) {
|
||||
|
||||
+45
-43
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user