Move item listing models to common location for reuse with search (#5438)

This commit is contained in:
David Perez
2025-06-27 14:06:31 -05:00
committed by GitHub
parent d279f6acae
commit ed2d6ca585
13 changed files with 60 additions and 79 deletions

View File

@@ -55,9 +55,9 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.bitwarden.authenticator.R
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.ItemListingExpandableFabAction
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VaultDropdownMenuAction
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.platform.components.appbar.AuthenticatorMediumTopAppBar
import com.bitwarden.authenticator.ui.platform.components.appbar.AuthenticatorTopAppBar
import com.bitwarden.authenticator.ui.platform.components.appbar.action.AuthenticatorSearchActionItem

View File

@@ -19,11 +19,11 @@ import com.bitwarden.authenticator.data.platform.manager.BitwardenEncodingManage
import com.bitwarden.authenticator.data.platform.manager.clipboard.BitwardenClipboardManager
import com.bitwarden.authenticator.data.platform.manager.imports.model.GoogleAuthenticatorProtos
import com.bitwarden.authenticator.data.platform.repository.SettingsRepository
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VaultDropdownMenuAction
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util.toDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util.toSharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.util.toDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.util.toSharedCodesDisplayState
import com.bitwarden.authenticatorbridge.manager.AuthenticatorBridgeManager
import com.bitwarden.core.data.repository.model.DataState
import com.bitwarden.ui.platform.base.BaseViewModel

View File

@@ -1,4 +1,4 @@
package com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model
package com.bitwarden.authenticator.ui.authenticator.feature.model
import android.os.Parcelable
import com.bitwarden.ui.util.Text

View File

@@ -1,4 +1,4 @@
package com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model
package com.bitwarden.authenticator.ui.authenticator.feature.model
import android.os.Parcelable
import com.bitwarden.authenticator.R

View File

@@ -21,7 +21,7 @@ fun ItemSearchContent(
modifier: Modifier = Modifier,
) {
LazyColumn(modifier = modifier) {
items(viewState.displayItems) {
items(viewState.itemList) {
VaultVerificationCodeItem(
modifier = Modifier
.fillMaxWidth()

View File

@@ -9,11 +9,12 @@ import com.bitwarden.authenticator.data.authenticator.repository.AuthenticatorRe
import com.bitwarden.authenticator.data.authenticator.repository.model.SharedVerificationCodesState
import com.bitwarden.authenticator.data.authenticator.repository.util.itemsOrEmpty
import com.bitwarden.authenticator.data.platform.manager.clipboard.BitwardenClipboardManager
import com.bitwarden.authenticator.ui.authenticator.feature.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.util.toDisplayItem
import com.bitwarden.core.data.repository.model.DataState
import com.bitwarden.core.data.repository.util.SpecialCharWithPrecedenceComparator
import com.bitwarden.ui.platform.base.BaseViewModel
import com.bitwarden.ui.platform.base.util.removeDiacritics
import com.bitwarden.ui.platform.components.icon.model.IconData
import com.bitwarden.ui.util.Text
import com.bitwarden.ui.util.asText
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -155,7 +156,15 @@ class ItemSearchViewModel @Inject constructor(
isNotEmpty() -> {
ItemSearchState.ViewState.Content(
displayItems = toDisplayItemList()
itemList = this
.map {
it.toDisplayItem(
alertThresholdSeconds = 7,
sharedVerificationCodesState = authenticatorRepository
.sharedCodesStateFlow
.value,
)
}
.sortAlphabetically(),
)
}
@@ -167,39 +176,13 @@ class ItemSearchViewModel @Inject constructor(
}
}
private fun List<VerificationCodeItem>.toDisplayItemList(): List<ItemSearchState.DisplayItem> =
this.map {
it.toDisplayItem()
}
private fun VerificationCodeItem.toDisplayItem(): ItemSearchState.DisplayItem =
ItemSearchState.DisplayItem(
id = id,
authCode = code,
title = issuer ?: label ?: "--",
subtitle = if (issuer != null) {
// Only show label if it is not being used as the primary title:
label
} else {
null
},
periodSeconds = periodSeconds,
timeLeftSeconds = timeLeftSeconds,
alertThresholdSeconds = 7,
startIcon = IconData.Local(iconRes = R.drawable.ic_login_item),
)
/**
* Sort a list of [ItemSearchState.DisplayItem] by their titles alphabetically giving digits and
* Sort a list of [VerificationCodeDisplayItem] by their titles alphabetically giving digits and
* special characters higher precedence.
*/
@Suppress("MaxLineLength")
private fun List<ItemSearchState.DisplayItem>.sortAlphabetically() =
private fun List<VerificationCodeDisplayItem>.sortAlphabetically() =
this.sortedWith { item1, item2 ->
SpecialCharWithPrecedenceComparator.compare(
item1.title.orEmpty(),
item2.title.orEmpty(),
)
SpecialCharWithPrecedenceComparator.compare(item1.title, item2.title)
}
//endregion Utility Functions
}
@@ -222,7 +205,7 @@ data class ItemSearchState(
*/
@Parcelize
data class Content(
val displayItems: List<DisplayItem>,
val itemList: List<VerificationCodeDisplayItem>,
) : ViewState()
/**
@@ -231,21 +214,6 @@ data class ItemSearchState(
@Parcelize
data class Empty(val message: Text?) : ViewState()
}
/**
* An item to be displayed.
*/
@Parcelize
data class DisplayItem(
val id: String,
val authCode: String,
val title: String,
val subtitle: String? = null,
val periodSeconds: Int,
val timeLeftSeconds: Int,
val alertThresholdSeconds: Int,
val startIcon: IconData,
) : Parcelable
}
/**

View File

@@ -1,10 +1,10 @@
package com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util
package com.bitwarden.authenticator.ui.authenticator.feature.util
import com.bitwarden.authenticator.R
import com.bitwarden.authenticator.data.authenticator.repository.model.AuthenticatorItem
import com.bitwarden.authenticator.data.authenticator.repository.model.SharedVerificationCodesState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.model.VerificationCodeDisplayItem
import com.bitwarden.ui.util.asText
/**

View File

@@ -1,9 +1,9 @@
package com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util
package com.bitwarden.authenticator.ui.authenticator.feature.util
import com.bitwarden.authenticator.data.authenticator.manager.model.VerificationCodeItem
import com.bitwarden.authenticator.data.authenticator.repository.model.AuthenticatorItem
import com.bitwarden.authenticator.data.authenticator.repository.model.SharedVerificationCodesState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.model.VerificationCodeDisplayItem
/**
* Converts [VerificationCodeItem] to a [VerificationCodeDisplayItem].

View File

@@ -9,9 +9,9 @@ import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import androidx.compose.ui.test.performTouchInput
import androidx.core.net.toUri
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VaultDropdownMenuAction
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.platform.base.AuthenticatorComposeTest
import com.bitwarden.authenticator.ui.platform.manager.intent.IntentManager
import com.bitwarden.authenticator.ui.platform.manager.permissions.FakePermissionManager

View File

@@ -10,11 +10,11 @@ import com.bitwarden.authenticator.data.authenticator.repository.model.SharedVer
import com.bitwarden.authenticator.data.platform.manager.BitwardenEncodingManager
import com.bitwarden.authenticator.data.platform.manager.clipboard.BitwardenClipboardManager
import com.bitwarden.authenticator.data.platform.repository.SettingsRepository
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VaultDropdownMenuAction
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util.toDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util.toSharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.util.toDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.util.toSharedCodesDisplayState
import com.bitwarden.authenticatorbridge.manager.AuthenticatorBridgeManager
import com.bitwarden.core.data.repository.model.DataState
import com.bitwarden.ui.platform.base.BaseViewModelTest

View File

@@ -9,6 +9,7 @@ import com.bitwarden.authenticator.data.authenticator.repository.model.Authentic
import com.bitwarden.authenticator.data.authenticator.repository.model.SharedVerificationCodesState
import com.bitwarden.authenticator.data.authenticator.repository.util.itemsOrEmpty
import com.bitwarden.authenticator.data.platform.manager.clipboard.BitwardenClipboardManager
import com.bitwarden.authenticator.ui.authenticator.feature.model.VerificationCodeDisplayItem
import com.bitwarden.core.data.repository.model.DataState
import com.bitwarden.ui.platform.base.BaseViewModelTest
import com.bitwarden.ui.platform.components.icon.model.IconData
@@ -66,7 +67,7 @@ class ItemSearchViewModelTest : BaseViewModelTest() {
assertEquals(
ItemSearchState.ViewState.Content(
displayItems = SHARED_AND_LOCAL_DISPLAY_ITEMS,
itemList = SHARED_AND_LOCAL_DISPLAY_ITEMS,
),
viewModel.stateFlow.value.viewState,
)
@@ -84,7 +85,7 @@ class ItemSearchViewModelTest : BaseViewModelTest() {
assertEquals(
ItemSearchState.ViewState.Content(
displayItems = listOf(SHARED_AND_LOCAL_DISPLAY_ITEMS[1]),
itemList = listOf(SHARED_AND_LOCAL_DISPLAY_ITEMS[1]),
),
viewModel.stateFlow.value.viewState,
)
@@ -116,7 +117,7 @@ private val LOCAL_ITEMS = listOf(
private val SHARED_ITEMS = listOf(
VerificationCodeItem(
"123456",
code = "123456",
periodSeconds = 60,
timeLeftSeconds = 30,
issueTime = 1,
@@ -133,24 +134,36 @@ private val SHARED_ITEMS = listOf(
)
private val SHARED_AND_LOCAL_DISPLAY_ITEMS = listOf(
ItemSearchState.DisplayItem(
VerificationCodeDisplayItem(
id = SHARED_ITEMS[0].id,
authCode = SHARED_ITEMS[0].code,
title = SHARED_ITEMS[0].issuer!!,
periodSeconds = SHARED_ITEMS[0].periodSeconds,
timeLeftSeconds = SHARED_ITEMS[0].timeLeftSeconds,
alertThresholdSeconds = 7,
startIcon = IconData.Local(iconRes = R.drawable.ic_login_item),
startIcon = IconData.Local(
iconRes = R.drawable.ic_login_item,
testTag = "BitwardenIcon",
),
subtitle = SHARED_ITEMS[0].label,
favorite = false,
allowLongPressActions = false,
showMoveToBitwarden = false,
),
ItemSearchState.DisplayItem(
VerificationCodeDisplayItem(
id = LOCAL_ITEMS[0].id,
authCode = LOCAL_ITEMS[0].code,
title = LOCAL_ITEMS[0].issuer!!,
periodSeconds = LOCAL_ITEMS[0].periodSeconds,
timeLeftSeconds = LOCAL_ITEMS[0].timeLeftSeconds,
alertThresholdSeconds = 7,
startIcon = IconData.Local(iconRes = R.drawable.ic_login_item),
startIcon = IconData.Local(
iconRes = R.drawable.ic_login_item,
testTag = "BitwardenIcon",
),
subtitle = LOCAL_ITEMS[0].label,
favorite = false,
allowLongPressActions = true,
showMoveToBitwarden = true,
),
)

View File

@@ -1,11 +1,11 @@
package com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util
package com.bitwarden.authenticator.ui.authenticator.feature.util
import com.bitwarden.authenticator.R
import com.bitwarden.authenticator.data.authenticator.manager.model.VerificationCodeItem
import com.bitwarden.authenticator.data.authenticator.repository.model.AuthenticatorItem
import com.bitwarden.authenticator.data.authenticator.repository.model.SharedVerificationCodesState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.model.SharedCodesDisplayState
import com.bitwarden.authenticator.ui.authenticator.feature.model.VerificationCodeDisplayItem
import com.bitwarden.ui.util.asText
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

View File

@@ -1,9 +1,9 @@
package com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.util
package com.bitwarden.authenticator.ui.authenticator.feature.util
import com.bitwarden.authenticator.data.authenticator.manager.util.createMockVerificationCodeItem
import com.bitwarden.authenticator.data.authenticator.repository.model.AuthenticatorItem
import com.bitwarden.authenticator.data.authenticator.repository.model.SharedVerificationCodesState
import com.bitwarden.authenticator.ui.authenticator.feature.itemlisting.model.VerificationCodeDisplayItem
import com.bitwarden.authenticator.ui.authenticator.feature.model.VerificationCodeDisplayItem
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test