diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/ItemScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/ItemScreen.kt index c50fce3c1..0967f61b6 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/ItemScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/ItemScreen.kt @@ -128,7 +128,7 @@ fun ItemContent( BitwardenTextField( modifier = Modifier.padding(horizontal = 16.dp), label = stringResource(id = R.string.name), - value = viewState.itemData.name, + value = viewState.itemData.issuer, onValueChange = {}, readOnly = true, singleLine = true, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/ItemViewModel.kt b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/ItemViewModel.kt index 1ce9f9a83..cb9bf9755 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/ItemViewModel.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/ItemViewModel.kt @@ -62,7 +62,7 @@ class ItemViewModel @Inject constructor( } ItemData( - name = item?.username.orEmpty(), + issuer = item?.issuer.orEmpty(), alertThresholdSeconds = alertThresholdSeconds, totpCodeItemData = totpData ) @@ -133,7 +133,7 @@ class ItemViewModel @Inject constructor( itemId = action.item?.id.orEmpty(), viewState = ItemState.ViewState.Content( itemData = ItemData( - name = action.item?.username.orEmpty(), + issuer = action.item?.issuer.orEmpty(), alertThresholdSeconds = alertThreshold, totpCodeItemData = totpItemData, ) diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/model/ItemData.kt b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/model/ItemData.kt index 3cf37be68..22ddf1416 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/model/ItemData.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/item/model/ItemData.kt @@ -6,14 +6,14 @@ import kotlinx.parcelize.Parcelize /** * Represents the item data displayed to users. * - * @property name Name of the account associated to the item. + * @property issuer Name of the item provider. * @property alertThresholdSeconds Threshold, in seconds, at which an Item is considered near * expiration. * @property totpCodeItemData TOTP data for the account. */ @Parcelize data class ItemData( - val name: String, + val issuer: String, val alertThresholdSeconds: Int, val totpCodeItemData: TotpCodeItemData?, ) : Parcelable diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt index f4bbb58b3..c645c1ff4 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingScreen.kt @@ -159,7 +159,7 @@ fun ItemListingScreen( .fillMaxWidth() .padding(horizontal = 16.dp), startIcon = it.startIcon, - label = it.label, + issuer = it.issuer, supportingLabel = it.supportingLabel, timeLeftSeconds = it.timeLeftSeconds, periodSeconds = it.periodSeconds, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt index 48cdcad48..735c6a616 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/ItemListingViewModel.kt @@ -375,6 +375,7 @@ sealed class ItemListingAction { data class VerificationCodeDisplayItem( val id: String, val label: String, + val issuer: String?, val supportingLabel: String?, val timeLeftSeconds: Int, val periodSeconds: Int, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt index d23890e59..eccf1b4d2 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/VaultVerificationCodeItem.kt @@ -32,7 +32,7 @@ import com.x8bit.bitwarden.authenticator.ui.platform.theme.AuthenticatorTheme * The verification code item displayed to the user. * * @param authCode The code for the item. - * @param label The label for the item. + * @param issuer The label for the item. * @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. @@ -45,7 +45,7 @@ import com.x8bit.bitwarden.authenticator.ui.platform.theme.AuthenticatorTheme @Composable fun VaultVerificationCodeItem( authCode: String, - label: String, + issuer: String?, periodSeconds: Int, timeLeftSeconds: Int, alertThresholdSeconds: Int, @@ -80,13 +80,15 @@ fun VaultVerificationCodeItem( verticalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.weight(1f), ) { - Text( - text = label, - style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.onSurface, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) + issuer?.let { + Text( + text = it, + style = MaterialTheme.typography.bodyLarge, + color = MaterialTheme.colorScheme.onSurface, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } supportingLabel?.let { Text( @@ -131,7 +133,7 @@ private fun VerificationCodeItem_preview() { AuthenticatorTheme { VaultVerificationCodeItem( startIcon = IconData.Local(R.drawable.ic_login_item), - label = "Sample Label", + issuer = "Sample Label", supportingLabel = "Supporting Label", authCode = "1234567890".chunked(3).joinToString(" "), timeLeftSeconds = 15, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/util/VerificationCodeItemExtensions.kt b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/util/VerificationCodeItemExtensions.kt index 02e63abd2..a8d5c2733 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/util/VerificationCodeItemExtensions.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/itemlisting/util/VerificationCodeItemExtensions.kt @@ -19,6 +19,7 @@ fun VerificationCodeItem.toDisplayItem(alertThresholdSeconds: Int) = VerificationCodeDisplayItem( id = id, label = label, + issuer = issuer, supportingLabel = username, timeLeftSeconds = timeLeftSeconds, periodSeconds = periodSeconds, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryScreen.kt index 18e64e65c..b4feeda5a 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryScreen.kt @@ -147,6 +147,22 @@ fun ManualCodeEntryScreen( .padding(horizontal = 16.dp), ) + Spacer(modifier = Modifier.height(8.dp)) + BitwardenTextField( + label = stringResource(id = R.string.issuer), + value = state.issuer, + onValueChange = remember(viewModel) { + { + viewModel.trySendAction( + ManualCodeEntryAction.IssuerTextChange(it), + ) + } + }, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + ) + Spacer(modifier = Modifier.height(16.dp)) BitwardenFilledTonalButton( label = stringResource(id = R.string.add_totp), diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryViewModel.kt b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryViewModel.kt index 8c937e4d6..897c9b5e4 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryViewModel.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/authenticator/ui/authenticator/feature/manualcodeentry/ManualCodeEntryViewModel.kt @@ -2,12 +2,13 @@ package com.x8bit.bitwarden.authenticator.ui.authenticator.feature.manualcodeent import android.os.Parcelable import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.viewModelScope import com.x8bit.bitwarden.authenticator.data.authenticator.repository.AuthenticatorRepository -import com.x8bit.bitwarden.authenticator.data.authenticator.repository.model.TotpCodeResult import com.x8bit.bitwarden.authenticator.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.authenticator.ui.platform.base.util.Text import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize import javax.inject.Inject @@ -23,18 +24,25 @@ class ManualCodeEntryViewModel @Inject constructor( private val authenticatorRepository: AuthenticatorRepository, ) : BaseViewModel( initialState = savedStateHandle[KEY_STATE] - ?: ManualCodeEntryState(code = ""), + ?: ManualCodeEntryState(code = "", issuer = ""), ) { override fun handleAction(action: ManualCodeEntryAction) { when (action) { is ManualCodeEntryAction.CloseClick -> handleCloseClick() is ManualCodeEntryAction.CodeTextChange -> handleCodeTextChange(action) + is ManualCodeEntryAction.IssuerTextChange -> handleIssuerTextChange(action) is ManualCodeEntryAction.CodeSubmit -> handleCodeSubmit() is ManualCodeEntryAction.ScanQrCodeTextClick -> handleScanQrCodeTextClick() is ManualCodeEntryAction.SettingsClick -> handleSettingsClick() } } + private fun handleIssuerTextChange(action: ManualCodeEntryAction.IssuerTextChange) { + mutableStateFlow.update { + it.copy(issuer = action.issuer) + } + } + private fun handleCloseClick() { sendEvent(ManualCodeEntryEvent.NavigateBack) } @@ -46,7 +54,9 @@ class ManualCodeEntryViewModel @Inject constructor( } private fun handleCodeSubmit() { - authenticatorRepository.emitTotpCodeResult(TotpCodeResult.Success(state.code)) + viewModelScope.launch { + authenticatorRepository.createItem(state.code, state.issuer) + } sendEvent(ManualCodeEntryEvent.NavigateBack) } @@ -65,6 +75,7 @@ class ManualCodeEntryViewModel @Inject constructor( @Parcelize data class ManualCodeEntryState( val code: String, + val issuer: String, ) : Parcelable /** @@ -113,6 +124,11 @@ sealed class ManualCodeEntryAction { */ data class CodeTextChange(val code: String) : ManualCodeEntryAction() + /** + * The use has changed the issuer text. + */ + data class IssuerTextChange(val issuer: String) : ManualCodeEntryAction() + /** * The text to switch to QR code scanning is clicked. */ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 945a6581d..95c544427 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -38,4 +38,5 @@ Add code Sync items from Bitwarden Import items + Issuer