diff --git a/app/schemas/com.bitwarden.authenticator.data.authenticator.datasource.disk.database.AuthenticatorDatabase/1.json b/app/schemas/com.bitwarden.authenticator.data.authenticator.datasource.disk.database.AuthenticatorDatabase/1.json index 4cc0203531..0e0b7bf8ea 100644 --- a/app/schemas/com.bitwarden.authenticator.data.authenticator.datasource.disk.database.AuthenticatorDatabase/1.json +++ b/app/schemas/com.bitwarden.authenticator.data.authenticator.datasource.disk.database.AuthenticatorDatabase/1.json @@ -2,11 +2,11 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "8724b95439edde85bd15e0bd2e02195e", + "identityHash": "480a4540e7704429515a28eb9c38ab14", "entities": [ { "tableName": "items", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `key` TEXT NOT NULL, `accountName` TEXT NOT NULL, `type` TEXT NOT NULL, `algorithm` TEXT NOT NULL, `period` INTEGER NOT NULL, `digits` INTEGER NOT NULL, `issuer` TEXT, `userId` TEXT, PRIMARY KEY(`id`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `key` TEXT NOT NULL, `type` TEXT NOT NULL, `algorithm` TEXT NOT NULL, `period` INTEGER NOT NULL, `digits` INTEGER NOT NULL, `issuer` TEXT NOT NULL, `userId` TEXT, `accountName` TEXT, PRIMARY KEY(`id`))", "fields": [ { "fieldPath": "id", @@ -20,12 +20,6 @@ "affinity": "TEXT", "notNull": true }, - { - "fieldPath": "accountName", - "columnName": "accountName", - "affinity": "TEXT", - "notNull": true - }, { "fieldPath": "type", "columnName": "type", @@ -54,13 +48,19 @@ "fieldPath": "issuer", "columnName": "issuer", "affinity": "TEXT", - "notNull": false + "notNull": true }, { "fieldPath": "userId", "columnName": "userId", "affinity": "TEXT", "notNull": false + }, + { + "fieldPath": "accountName", + "columnName": "accountName", + "affinity": "TEXT", + "notNull": false } ], "primaryKey": { @@ -76,7 +76,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8724b95439edde85bd15e0bd2e02195e')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '480a4540e7704429515a28eb9c38ab14')" ] } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/datasource/disk/entity/AuthenticatorItemEntity.kt b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/datasource/disk/entity/AuthenticatorItemEntity.kt index b250b2a90a..afebf2b9fc 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/datasource/disk/entity/AuthenticatorItemEntity.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/datasource/disk/entity/AuthenticatorItemEntity.kt @@ -1,5 +1,7 @@ package com.bitwarden.authenticator.data.authenticator.datasource.disk.entity +import android.net.Uri +import androidx.core.text.htmlEncode import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey @@ -16,9 +18,6 @@ data class AuthenticatorItemEntity( @ColumnInfo(name = "key") val key: String, - @ColumnInfo(name = "accountName") - val accountName: String, - @ColumnInfo(name = "type") val type: AuthenticatorItemType = AuthenticatorItemType.TOTP, @@ -32,8 +31,42 @@ data class AuthenticatorItemEntity( val digits: Int = 6, @ColumnInfo(name = "issuer") - val issuer: String? = null, + val issuer: String, @ColumnInfo(name = "userId") val userId: String? = null, -) + + @ColumnInfo(name = "accountName") + val accountName: String? = null, +) { + fun toOtpAuthUriString(): String { + return when (type) { + AuthenticatorItemType.TOTP -> { + val label = if (accountName.isNullOrBlank()) { + issuer + } else { + "$issuer:$accountName" + } + Uri.Builder() + .scheme("otpauth") + .authority("totp") + .appendPath(label.htmlEncode()) + .appendQueryParameter("secret", key) + .appendQueryParameter("algorithm", algorithm.name) + .appendQueryParameter("digits", digits.toString()) + .appendQueryParameter("period", period.toString()) + .appendQueryParameter("issuer", issuer) + .build() + .toString() + } + + AuthenticatorItemType.STEAM -> { + if (key.startsWith("steam://")) { + key + } else { + "steam://$key" + } + } + } + } +} diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/TotpCodeManagerImpl.kt b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/TotpCodeManagerImpl.kt index ce0e0e1676..3f7278f0d4 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/TotpCodeManagerImpl.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/TotpCodeManagerImpl.kt @@ -75,7 +75,7 @@ class TotpCodeManagerImpl @Inject constructor( return mutableVerificationCodeStateFlowMap.getOrPut(itemEntity) { flow> { - val totpCode = itemEntity.key + val totpCode = itemEntity.toOtpAuthUriString() var item: VerificationCodeItem? = null while (currentCoroutineContext().isActive) { diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/model/ExportJsonData.kt b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/model/ExportJsonData.kt index 3c4cf2a663..84fcade3b4 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/model/ExportJsonData.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/model/ExportJsonData.kt @@ -36,16 +36,10 @@ data class ExportJsonData( * This model is loosely based off of Bitwarden's Cipher.Login JSON. * * @property totp OTP secret used to generate a verification code. - * @property issuer Optional issuer of the 2fa code. - * @property period Optional refresh period in seconds. Default is 30. - * @property digits Optional number of digits in the verification code. Default is 6 */ @Serializable data class ItemLoginData( val totp: String, - val issuer: String?, - val period: Int, - val digits: Int, ) } } diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/model/VerificationCodeItem.kt b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/model/VerificationCodeItem.kt index 9e61f67af7..517e59278a 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/model/VerificationCodeItem.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/manager/model/VerificationCodeItem.kt @@ -22,7 +22,7 @@ data class VerificationCodeItem( val issuer: String?, ) { /** - * The composite label of the authenticator item. + * The composite label of the authenticator item. Used for constructing an OTPAuth URI. * ``` * label = issuer (“:” / “%3A”) *”%20” username * ``` diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/repository/AuthenticatorRepositoryImpl.kt b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/repository/AuthenticatorRepositoryImpl.kt index 1d653ee196..7a3e696eaf 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/repository/AuthenticatorRepositoryImpl.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/repository/AuthenticatorRepositoryImpl.kt @@ -233,7 +233,7 @@ class AuthenticatorRepositoryImpl @Inject constructor( private suspend fun encodeVaultDataToCsv(fileUri: Uri): ExportDataResult { val headerLine = - "folder,favorite,type,name,login_uri,login_totp,issuer,period,digits" + "folder,favorite,type,name,login_uri,login_totp" val dataLines = authenticatorDiskSource .getItems() .firstOrNull() @@ -250,7 +250,7 @@ class AuthenticatorRepositoryImpl @Inject constructor( } private fun AuthenticatorItemEntity.toCsvFormat() = - ",,1,$accountName,,$key,$issuer,$period,$digits" + ",,1,$issuer,,${toOtpAuthUriString()},$issuer,$period,$digits" private suspend fun encodeVaultDataToJson(fileUri: Uri): ExportDataResult { val dataString: String = Json.encodeToString( @@ -281,14 +281,11 @@ class AuthenticatorRepositoryImpl @Inject constructor( folderId = null, organizationId = null, collectionIds = null, - name = accountName, + name = issuer, notes = null, type = 1, login = ExportJsonData.ExportItem.ItemLoginData( - totp = key, - issuer = issuer, - period = period, - digits = digits, + totp = toOtpAuthUriString(), ), favorite = false, ) diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/repository/model/UpdateItemRequest.kt b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/repository/model/UpdateItemRequest.kt index 70b6b7271d..b4c0c41856 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/repository/model/UpdateItemRequest.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/data/authenticator/repository/model/UpdateItemRequest.kt @@ -16,12 +16,12 @@ import com.bitwarden.authenticator.data.authenticator.datasource.disk.entity.Aut */ data class UpdateItemRequest( val key: String, - val accountName: String, + val accountName: String?, val type: AuthenticatorItemType, val algorithm: AuthenticatorItemAlgorithm, val period: Int, val digits: Int, - val issuer: String?, + val issuer: String, ) { /** * The composite label of the authenticator item. Derived from combining [issuer] and [accountName] @@ -29,9 +29,9 @@ data class UpdateItemRequest( * label = accountName /issuer (“:” / “%3A”) *”%20” accountName * ``` */ - val label = if (issuer != null) { - "$issuer:$accountName" + val label = if (accountName.isNullOrBlank()) { + issuer } else { - accountName + "$issuer:$accountName" } } diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/EditItemScreen.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/EditItemScreen.kt index 9a5e5090a8..890cd53441 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/EditItemScreen.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/EditItemScreen.kt @@ -139,17 +139,17 @@ fun EditItemScreen( .imePadding() .padding(innerPadding), viewState = viewState, - onAccountNameTextChange = remember(viewModel) { + onIssuerNameTextChange = remember(viewModel) { { viewModel.trySendAction( - EditItemAction.AccountNameTextChange(it) + EditItemAction.IssuerNameTextChange(it) ) } }, - onIssuerTextChange = remember(viewModel) { + onUsernameTextChange = remember(viewModel) { { viewModel.trySendAction( - EditItemAction.IssuerTextChange(it) + EditItemAction.UsernameTextChange(it) ) } }, @@ -211,8 +211,8 @@ fun EditItemScreen( fun EditItemContent( modifier: Modifier = Modifier, viewState: EditItemState.ViewState.Content, - onAccountNameTextChange: (String) -> Unit = {}, - onIssuerTextChange: (String) -> Unit = {}, + onIssuerNameTextChange: (String) -> Unit = {}, + onUsernameTextChange: (String) -> Unit = {}, onTypeOptionClicked: (AuthenticatorItemType) -> Unit = {}, onTotpCodeTextChange: (String) -> Unit = {}, onAlgorithmOptionClicked: (AuthenticatorItemAlgorithm) -> Unit = {}, @@ -237,8 +237,8 @@ fun EditItemContent( .fillMaxSize() .padding(horizontal = 16.dp), label = stringResource(id = R.string.name), - value = viewState.itemData.accountName, - onValueChange = onAccountNameTextChange, + value = viewState.itemData.issuer, + onValueChange = onIssuerNameTextChange, singleLine = true, ) } @@ -256,20 +256,18 @@ fun EditItemContent( ) } - viewState.itemData.issuer?.let { issuer -> item { Spacer(modifier = Modifier.height(8.dp)) BitwardenTextField( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp), - label = stringResource(id = R.string.account_info), - value = issuer, - onValueChange = onIssuerTextChange, + label = stringResource(id = R.string.username), + value = viewState.itemData.username.orEmpty(), + onValueChange = onUsernameTextChange, singleLine = true, ) } - } } Spacer(modifier = Modifier.height(8.dp)) @@ -483,7 +481,7 @@ private fun EditItemContentExpandedOptionsPreview() { refreshPeriod = AuthenticatorRefreshPeriodOption.THIRTY, totpCode = "123456", type = AuthenticatorItemType.TOTP, - accountName = "account name", + username = "account name", issuer = "issuer", algorithm = AuthenticatorItemAlgorithm.SHA1, digits = VerificationCodeDigitsOption.SIX @@ -502,7 +500,7 @@ private fun EditItemContentCollapsedOptionsPreview() { refreshPeriod = AuthenticatorRefreshPeriodOption.THIRTY, totpCode = "123456", type = AuthenticatorItemType.TOTP, - accountName = "account name", + username = "account name", issuer = "issuer", algorithm = AuthenticatorItemAlgorithm.SHA1, digits = VerificationCodeDigitsOption.SIX diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/EditItemViewModel.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/EditItemViewModel.kt index c33513439e..9db68f1377 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/EditItemViewModel.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/EditItemViewModel.kt @@ -57,8 +57,8 @@ class EditItemViewModel @Inject constructor( is EditItemAction.AlgorithmOptionClick -> handleAlgorithmOptionClick(action) is EditItemAction.CancelClick -> handleCancelClick() is EditItemAction.TypeOptionClick -> handleTypeOptionClick(action) - is EditItemAction.AccountNameTextChange -> handleAccountNameTextChange(action) - is EditItemAction.IssuerTextChange -> handleIssuerTextChange(action) + is EditItemAction.IssuerNameTextChange -> handleIssuerNameTextChange(action) + is EditItemAction.UsernameTextChange -> handleIssuerTextChange(action) is EditItemAction.RefreshPeriodOptionClick -> handlePeriodTextChange(action) is EditItemAction.TotpCodeTextChange -> handleTotpCodeTextChange(action) is EditItemAction.NumberOfDigitsOptionClick -> handleNumberOfDigitsOptionChange(action) @@ -76,7 +76,7 @@ class EditItemViewModel @Inject constructor( } private fun handleSaveClick() = onContent { content -> - if (content.itemData.accountName.isBlank()) { + if (content.itemData.issuer.isBlank()) { mutableStateFlow.update { it.copy( dialog = EditItemState.DialogState.Generic( @@ -110,12 +110,12 @@ class EditItemViewModel @Inject constructor( AuthenticatorItemEntity( id = state.itemId, key = content.itemData.totpCode.trim(), - accountName = content.itemData.accountName.trim(), + accountName = content.itemData.username?.trim(), type = content.itemData.type, algorithm = content.itemData.algorithm, period = content.itemData.refreshPeriod.seconds, digits = content.itemData.digits.length, - issuer = content.itemData.issuer?.trim(), + issuer = content.itemData.issuer.trim(), ) ) trySendAction(EditItemAction.Internal.UpdateItemResult(result)) @@ -130,18 +130,18 @@ class EditItemViewModel @Inject constructor( } } - private fun handleAccountNameTextChange(action: EditItemAction.AccountNameTextChange) { + private fun handleIssuerNameTextChange(action: EditItemAction.IssuerNameTextChange) { updateItemData { currentItemData -> currentItemData.copy( - accountName = action.accountName + issuer = action.issuerName ) } } - private fun handleIssuerTextChange(action: EditItemAction.IssuerTextChange) { + private fun handleIssuerTextChange(action: EditItemAction.UsernameTextChange) { updateItemData { currentItemData -> currentItemData.copy( - issuer = action.issue + username = action.username ) } } @@ -318,7 +318,7 @@ class EditItemViewModel @Inject constructor( ?: AuthenticatorRefreshPeriodOption.THIRTY, totpCode = key, type = type, - accountName = accountName, + username = accountName, issuer = issuer, algorithm = algorithm, digits = VerificationCodeDigitsOption.fromIntOrNull(digits) @@ -435,12 +435,12 @@ sealed class EditItemAction { /** * The user has changed the account name text. */ - data class AccountNameTextChange(val accountName: String) : EditItemAction() + data class IssuerNameTextChange(val issuerName: String) : EditItemAction() /** * The user has changed the issue text. */ - data class IssuerTextChange(val issue: String) : EditItemAction() + data class UsernameTextChange(val username: String) : EditItemAction() /** * The user has selected an Item Type option. diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/model/EditItemData.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/model/EditItemData.kt index d47911b4a7..16c7928c5d 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/model/EditItemData.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/edititem/model/EditItemData.kt @@ -12,7 +12,7 @@ import kotlinx.parcelize.Parcelize * * @property refreshPeriod The period for the verification code. * @property totpCode The totp code for the item. - * @property accountName Account or username for this item. + * @property username Account or username for this item. * @property issuer Name of the item provider. * @property algorithm Hashing algorithm used with the item. * @property digits Number of digits in the verification code. @@ -22,8 +22,8 @@ data class EditItemData( val refreshPeriod: AuthenticatorRefreshPeriodOption, val totpCode: String, val type: AuthenticatorItemType, - val accountName: String, - val issuer: String?, + val username: String?, + val issuer: String, val algorithm: AuthenticatorItemAlgorithm, val digits: VerificationCodeDigitsOption, ) : Parcelable diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt index 0662b63c1d..aec2ad06e1 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt @@ -31,6 +31,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext @@ -228,7 +229,8 @@ fun ItemListingScreen( items(currentState.itemList) { VaultVerificationCodeItem( authCode = it.authCode, - issuer = it.issuer, + name = it.issuer, + username = it.username, periodSeconds = it.periodSeconds, timeLeftSeconds = it.timeLeftSeconds, alertThresholdSeconds = it.alertThresholdSeconds, @@ -257,7 +259,6 @@ fun ItemListingScreen( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp), - supportingLabel = it.supportingLabel, ) } } diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt index d4340df7db..6738a737e0 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt @@ -391,6 +391,13 @@ class ItemListingViewModel @Inject constructor( ?: return null val label = uri.pathSegments.firstOrNull() ?: return null + val accountName = if (label.contains(":")) { + label + .split(":") + .last() + } else { + label + } val key = uri.getQueryParameter(SECRET) ?: return null @@ -401,14 +408,14 @@ class ItemListingViewModel @Inject constructor( val digits = uri.getQueryParameter(DIGITS)?.toInt() ?: 6 - val issuer = uri.getQueryParameter(ISSUER) + val issuer = uri.getQueryParameter(ISSUER) ?: label val period = uri.getQueryParameter(PERIOD)?.toInt() ?: 30 return AuthenticatorItemEntity( id = UUID.randomUUID().toString(), key = key, - accountName = label, + accountName = accountName, type = type, algorithm = algorithm, period = period, diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt index b8fc7e3aa6..43e4b69d37 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt @@ -39,20 +39,21 @@ import com.bitwarden.authenticator.ui.platform.theme.AuthenticatorTheme * The verification code item displayed to the user. * * @param authCode The code for the item. - * @param issuer The label for the item. + * @param name The label for the item. Represents the OTP issuer. + * @param username The supporting label for the item. Represents the OTP account name. * @param periodSeconds The times span where the code is valid. * @param timeLeftSeconds The seconds remaining until a new code is needed. * @param startIcon The leading icon for the item. * @param onItemClick The lambda function to be invoked when the item is clicked. * @param modifier The modifier for the item. - * @param supportingLabel The supporting label for the item. */ @OptIn(ExperimentalFoundationApi::class) @Suppress("LongMethod", "MagicNumber") @Composable fun VaultVerificationCodeItem( authCode: String, - issuer: String?, + name: String?, + username: String?, periodSeconds: Int, timeLeftSeconds: Int, alertThresholdSeconds: Int, @@ -61,7 +62,6 @@ fun VaultVerificationCodeItem( onEditItemClick: () -> Unit, onDeleteItemClick: () -> Unit, modifier: Modifier = Modifier, - supportingLabel: String? = null, ) { var shouldShowDropdownMenu by remember { mutableStateOf(value = false) } Box(modifier = modifier) { @@ -93,9 +93,9 @@ fun VaultVerificationCodeItem( verticalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.weight(1f), ) { - issuer?.let { + if (!name.isNullOrEmpty()) { Text( - text = it, + text = name, style = MaterialTheme.typography.bodyLarge, color = MaterialTheme.colorScheme.onSurface, maxLines = 1, @@ -103,9 +103,9 @@ fun VaultVerificationCodeItem( ) } - supportingLabel?.let { + if (!username.isNullOrEmpty()) { Text( - text = it, + text = username, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, maxLines = 1, @@ -173,7 +173,8 @@ private fun VerificationCodeItem_preview() { AuthenticatorTheme { VaultVerificationCodeItem( authCode = "1234567890".chunked(3).joinToString(" "), - issuer = "Sample Label", + name = "Issuer, AKA Name", + username = "username@bitwarden.com", periodSeconds = 30, timeLeftSeconds = 15, alertThresholdSeconds = 7, @@ -182,7 +183,6 @@ private fun VerificationCodeItem_preview() { onEditItemClick = {}, onDeleteItemClick = {}, modifier = Modifier.padding(horizontal = 16.dp), - supportingLabel = "Supporting Label", ) } } diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/model/VerificationCodeDisplayItem.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/model/VerificationCodeDisplayItem.kt index 66dfd34e52..f0eda13770 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/model/VerificationCodeDisplayItem.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/model/VerificationCodeDisplayItem.kt @@ -11,9 +11,8 @@ import kotlinx.parcelize.Parcelize @Parcelize data class VerificationCodeDisplayItem( val id: String, - val label: String, val issuer: String?, - val supportingLabel: String?, + val username: String?, val timeLeftSeconds: Int, val periodSeconds: Int, val alertThresholdSeconds: Int, diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/util/VerificationCodeItemExtensions.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/util/VerificationCodeItemExtensions.kt index 00ccd47f4d..aa6c89c170 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/util/VerificationCodeItemExtensions.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/itemlisting/util/VerificationCodeItemExtensions.kt @@ -18,9 +18,8 @@ fun List.toViewState( fun VerificationCodeItem.toDisplayItem(alertThresholdSeconds: Int) = VerificationCodeDisplayItem( id = id, - label = label, issuer = issuer, - supportingLabel = username, + username = username, timeLeftSeconds = timeLeftSeconds, periodSeconds = periodSeconds, alertThresholdSeconds = alertThresholdSeconds, diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryScreen.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryScreen.kt index d45afc742a..855266701d 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryScreen.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryScreen.kt @@ -133,7 +133,7 @@ fun ManualCodeEntryScreen( Spacer(modifier = Modifier.height(8.dp)) BitwardenTextField( label = stringResource(id = R.string.name), - value = state.accountName, + value = state.issuer, onValueChange = remember(viewModel) { { viewModel.trySendAction( diff --git a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryViewModel.kt b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryViewModel.kt index ff870a88e1..ee9844f267 100644 --- a/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryViewModel.kt +++ b/app/src/main/kotlin/com/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import com.bitwarden.authenticator.R import com.bitwarden.authenticator.data.authenticator.datasource.disk.entity.AuthenticatorItemEntity +import com.bitwarden.authenticator.data.authenticator.datasource.disk.entity.AuthenticatorItemType import com.bitwarden.authenticator.data.authenticator.repository.AuthenticatorRepository import com.bitwarden.authenticator.data.authenticator.repository.model.CreateItemResult import com.bitwarden.authenticator.ui.platform.base.BaseViewModel @@ -29,7 +30,7 @@ class ManualCodeEntryViewModel @Inject constructor( private val authenticatorRepository: AuthenticatorRepository, ) : BaseViewModel( initialState = savedStateHandle[KEY_STATE] - ?: ManualCodeEntryState(code = "", accountName = "", dialog = null), + ?: ManualCodeEntryState(code = "", issuer = "", dialog = null), ) { override fun handleAction(action: ManualCodeEntryAction) { when (action) { @@ -47,7 +48,7 @@ class ManualCodeEntryViewModel @Inject constructor( private fun handleIssuerTextChange(action: ManualCodeEntryAction.IssuerTextChange) { mutableStateFlow.update { - it.copy(accountName = action.accountName) + it.copy(issuer = action.issuer) } } @@ -67,8 +68,14 @@ class ManualCodeEntryViewModel @Inject constructor( AuthenticatorItemEntity( id = UUID.randomUUID().toString(), key = state.code, - accountName = state.accountName, + issuer = state.issuer, + accountName = "", userId = null, + type = if (state.code.startsWith("steam://")) { + AuthenticatorItemType.STEAM + } else { + AuthenticatorItemType.TOTP + } ) ) sendAction(ManualCodeEntryAction.Internal.CreateItemResultReceive(result)) @@ -118,7 +125,7 @@ class ManualCodeEntryViewModel @Inject constructor( @Parcelize data class ManualCodeEntryState( val code: String, - val accountName: String, + val issuer: String, val dialog: DialogState?, ) : Parcelable { @@ -187,7 +194,7 @@ sealed class ManualCodeEntryAction { /** * The use has changed the issuer text. */ - data class IssuerTextChange(val accountName: String) : ManualCodeEntryAction() + data class IssuerTextChange(val issuer: String) : ManualCodeEntryAction() /** * Models actions that the [ManualCodeEntryViewModel] itself might send. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d6ea562591..3164daa0f0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -34,7 +34,7 @@ Add code Cannot read authenticator key. Verification code added - Account info + Username Refresh period Algorithm Hide