diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/additem/VaultAddItemViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/additem/VaultAddItemViewModel.kt index e5ff764359..7d95f4107b 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/additem/VaultAddItemViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/additem/VaultAddItemViewModel.kt @@ -15,9 +15,9 @@ import com.x8bit.bitwarden.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.ui.platform.base.util.Text import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.base.util.concat -import com.x8bit.bitwarden.ui.vault.feature.additem.util.toViewState import com.x8bit.bitwarden.ui.vault.feature.additem.VaultAddItemAction.ItemType.SecureNotesType.TooltipClick.toCustomField import com.x8bit.bitwarden.ui.vault.feature.additem.model.CustomFieldType +import com.x8bit.bitwarden.ui.vault.feature.additem.util.toViewState import com.x8bit.bitwarden.ui.vault.feature.vault.util.toCipherView import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType import com.x8bit.bitwarden.ui.vault.model.VaultLinkedFieldType @@ -826,7 +826,32 @@ data class VaultAddItemState( abstract val masterPasswordReprompt: Boolean /** - * The ownership email associated with the login item. + * Indicates whether this item is marked as a favorite. + */ + abstract val favorite: Boolean + + /** + * Additional custom fields associated with the item. + */ + abstract val customFieldData: List + + /** + * Any additional notes or comments associated with the item. + */ + abstract val notes: String + + /** + * The folder that this item belongs too. + */ + abstract val folderName: Text + + /** + * The list of folders that this item could be added too. + */ + abstract val availableFolders: List + + /** + * The ownership email associated with the item. */ abstract val ownership: String @@ -841,33 +866,29 @@ data class VaultAddItemState( * @property username The username required for the login item. * @property password The password required for the login item. * @property uri The URI associated with the login item. - * @property folderName The folder used for the login item - * @property favorite Indicates whether this login item is marked as a favorite. - * @property notes Any additional notes or comments associated with the login item. - * @property availableFolders Retrieves a list of available folders. */ @Parcelize data class Login( @IgnoredOnParcel override val originalCipher: CipherView? = null, override val name: String = "", - val username: String = "", - val password: String = "", - val uri: String = "", - val folderName: Text = DEFAULT_FOLDER, - val favorite: Boolean = false, - override val masterPasswordReprompt: Boolean = false, - val customFieldData: List = emptyList(), - val notes: String = "", + override val folderName: Text = DEFAULT_FOLDER, // TODO: Update this property to get available owners from the data layer (BIT-501) - val availableFolders: List = listOf( + override val availableFolders: List = listOf( "Folder 1".asText(), "Folder 2".asText(), "Folder 3".asText(), ), + override val favorite: Boolean = false, + override val masterPasswordReprompt: Boolean = false, + override val customFieldData: List = emptyList(), + override val notes: String = "", // TODO: Update this property to get available owners from the data layer (BIT-501) override val ownership: String = DEFAULT_OWNERSHIP, override val availableOwners: List = listOf("a@b.com", "c@d.com"), + val username: String = "", + val password: String = "", + val uri: String = "", ) : Content() { override val displayStringResId: Int get() = ItemTypeOption.LOGIN.labelRes } @@ -880,7 +901,18 @@ data class VaultAddItemState( @IgnoredOnParcel override val originalCipher: CipherView? = null, override val name: String = "", + override val folderName: Text = DEFAULT_FOLDER, + // TODO: Update this property to get available owners from the data layer (BIT-501) + override val availableFolders: List = listOf( + "Folder 1".asText(), + "Folder 2".asText(), + "Folder 3".asText(), + ), + override val favorite: Boolean = false, override val masterPasswordReprompt: Boolean = false, + override val customFieldData: List = emptyList(), + override val notes: String = "", + // TODO: Update this property to get available owners from the data layer (BIT-501) override val ownership: String = DEFAULT_OWNERSHIP, override val availableOwners: List = listOf("a@b.com", "c@d.com"), ) : Content() { @@ -895,7 +927,18 @@ data class VaultAddItemState( @IgnoredOnParcel override val originalCipher: CipherView? = null, override val name: String = "", + override val folderName: Text = DEFAULT_FOLDER, + // TODO: Update this property to get available owners from the data layer (BIT-501) + override val availableFolders: List = listOf( + "Folder 1".asText(), + "Folder 2".asText(), + "Folder 3".asText(), + ), + override val favorite: Boolean = false, override val masterPasswordReprompt: Boolean = false, + override val customFieldData: List = emptyList(), + override val notes: String = "", + // TODO: Update this property to get available owners from the data layer (BIT-501) override val ownership: String = DEFAULT_OWNERSHIP, override val availableOwners: List = listOf("a@b.com", "c@d.com"), ) : Content() { @@ -906,8 +949,6 @@ data class VaultAddItemState( * Represents the `SecureNotes` item type. * * @property folderName The folder used for the SecureNotes item - * @property favorite Indicates whether this SecureNotes item is marked as a favorite. - * @property notes Notes or comments associated with the SecureNotes item. * @property availableFolders A list of available folders. */ @Parcelize @@ -915,16 +956,18 @@ data class VaultAddItemState( @IgnoredOnParcel override val originalCipher: CipherView? = null, override val name: String = "", - val folderName: Text = DEFAULT_FOLDER, - val favorite: Boolean = false, - override val masterPasswordReprompt: Boolean = false, - val notes: String = "", - val availableFolders: List = listOf( + override val folderName: Text = DEFAULT_FOLDER, + // TODO: Update this property to get available owners from the data layer (BIT-501) + override val availableFolders: List = listOf( "Folder 1".asText(), "Folder 2".asText(), "Folder 3".asText(), ), - val customFieldData: List = emptyList(), + override val favorite: Boolean = false, + override val masterPasswordReprompt: Boolean = false, + override val customFieldData: List = emptyList(), + override val notes: String = "", + // TODO: Update this property to get available owners from the data layer (BIT-501) override val ownership: String = DEFAULT_OWNERSHIP, override val availableOwners: List = listOf("a@b.com", "c@d.com"), ) : Content() { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensions.kt index 88e15b05aa..c40ddccbac 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensions.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/util/VaultDataExtensions.kt @@ -1,10 +1,12 @@ package com.x8bit.bitwarden.ui.vault.feature.vault.util +import com.bitwarden.core.CardView import com.bitwarden.core.CipherRepromptType import com.bitwarden.core.CipherType import com.bitwarden.core.CipherView import com.bitwarden.core.FieldType import com.bitwarden.core.FieldView +import com.bitwarden.core.IdentityView import com.bitwarden.core.LoginUriView import com.bitwarden.core.LoginView import com.bitwarden.core.SecureNoteType @@ -89,17 +91,6 @@ fun VaultData.toViewState(): VaultState.ViewState = * Transforms a [VaultAddItemState.ViewState.Content] into [CipherView]. */ fun VaultAddItemState.ViewState.Content.toCipherView(): CipherView = - when (this) { - is VaultAddItemState.ViewState.Content.Card -> toCardCipherView() - is VaultAddItemState.ViewState.Content.Identity -> toIdentityCipherView() - is VaultAddItemState.ViewState.Content.Login -> toLoginCipherView() - is VaultAddItemState.ViewState.Content.SecureNotes -> toSecureNotesCipherView() - } - -/** - * Transforms [VaultAddItemState.ViewState.Content.Login] into [CipherView]. - */ -private fun VaultAddItemState.ViewState.Content.Login.toLoginCipherView(): CipherView = CipherView( // Pulled from original cipher when editing, otherwise uses defaults id = this.originalCipher?.id, @@ -116,88 +107,94 @@ private fun VaultAddItemState.ViewState.Content.Login.toLoginCipherView(): Ciphe revisionDate = this.originalCipher?.revisionDate ?: Instant.now(), // Type specific section - type = CipherType.LOGIN, - login = LoginView( - username = this.username, - password = this.password, - passwordRevisionDate = this.originalCipher?.login?.passwordRevisionDate, + type = this.toCipherType(), + identity = this.toIdentityView(), + secureNote = this.toSecureNotesView(), + login = this.toLoginView(), + card = this.toCardView(), + + // Fields we always grab from the UI + name = this.name, + notes = this.notes, + favorite = this.favorite, + // TODO Use real folder ID (BIT-528) + folderId = this.originalCipher?.folderId, + // TODO Use real organization ID (BIT-780) + organizationId = this.originalCipher?.organizationId, + reprompt = this.toCipherRepromptType(), + fields = this.customFieldData.map { it.toFieldView() }, + ) + +private fun VaultAddItemState.ViewState.Content.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 + } + +private fun VaultAddItemState.ViewState.Content.toCardView(): CardView? = + (this as? VaultAddItemState.ViewState.Content.Card)?.let { + // TODO Create real CardView from Content (BIT-668) + CardView( + cardholderName = null, + expMonth = null, + expYear = null, + code = null, + brand = null, + number = null, + ) + } + +private fun VaultAddItemState.ViewState.Content.toIdentityView(): IdentityView? = + (this as? VaultAddItemState.ViewState.Content.Identity)?.let { + // TODO Create real IdentityView from Content (BIT-508) + IdentityView( + title = null, + firstName = null, + lastName = null, + middleName = null, + address1 = null, + address2 = null, + address3 = null, + city = null, + state = null, + postalCode = null, + country = null, + company = null, + email = null, + phone = null, + ssn = null, + username = null, + passportNumber = null, + licenseNumber = null, + ) + } + +private fun VaultAddItemState.ViewState.Content.toLoginView(): LoginView? = + (this as? VaultAddItemState.ViewState.Content.Login)?.let { + LoginView( + username = it.username, + password = it.password, + passwordRevisionDate = it.originalCipher?.login?.passwordRevisionDate, uris = listOf( // TODO Implement URI list (BIT-1094) LoginUriView( - uri = this.uri, + uri = it.uri, // TODO Implement URI settings in (BIT-1094) match = UriMatchType.DOMAIN, ), ), - // TODO implement totp in BIT-1066 - totp = this.originalCipher?.login?.totp, - autofillOnPageLoad = this.originalCipher?.login?.autofillOnPageLoad, - ), - identity = null, - card = null, - secureNote = null, + // TODO Implement TOTP (BIT-1066) + totp = it.originalCipher?.login?.totp, + autofillOnPageLoad = it.originalCipher?.login?.autofillOnPageLoad, + ) + } - // Fields we always grab from the UI - name = this.name, - notes = this.notes, - favorite = this.favorite, - // TODO Use real folder ID (BIT-528) - folderId = this.originalCipher?.folderId, - // TODO Use real organization ID (BIT-780) - organizationId = this.originalCipher?.organizationId, - reprompt = this.toCipherRepromptType(), - fields = this.customFieldData.map { it.toFieldView() }, - ) - -/** - * Transforms [VaultAddItemState.ViewState.Content.SecureNotes] into [CipherView]. - */ -private fun VaultAddItemState.ViewState.Content.SecureNotes.toSecureNotesCipherView(): 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(), - - // Type specific section - type = CipherType.SECURE_NOTE, - secureNote = SecureNoteView(type = SecureNoteType.GENERIC), - login = null, - identity = null, - card = null, - - // Fields we always grab from the UI - name = this.name, - notes = this.notes, - favorite = this.favorite, - // TODO Use real folder ID (BIT-528) - folderId = this.originalCipher?.folderId, - // TODO Use real organization ID (BIT-780) - organizationId = this.originalCipher?.organizationId, - reprompt = this.toCipherRepromptType(), - fields = this.customFieldData.map { it.toFieldView() }, - ) - -/** - * Transforms [VaultAddItemState.ViewState.Content.Identity] into [CipherView]. - */ -private fun VaultAddItemState.ViewState.Content.Identity.toIdentityCipherView(): CipherView = - TODO("create Identity CipherView BIT-508") - -/** - * Transforms [VaultAddItemState.ViewState.Content.Card] into [CipherView]. - */ -private fun VaultAddItemState.ViewState.Content.Card.toCardCipherView(): CipherView = - TODO("create Card CipherView BIT-668") +private fun VaultAddItemState.ViewState.Content.toSecureNotesView(): SecureNoteView? = + (this as? VaultAddItemState.ViewState.Content.SecureNotes)?.let { + SecureNoteView(type = SecureNoteType.GENERIC) + } private fun VaultAddItemState.ViewState.Content.toCipherRepromptType(): CipherRepromptType = if (this.masterPasswordReprompt) {