Updated on 2026-08-14

This commit is contained in:
Tangem 2026-06-11 11:33:19 +01:00
parent c903c938fc
commit 900031ff25
5 changed files with 36 additions and 34 deletions

View file

@ -1,6 +1,7 @@
package com.tangem.features.addressbook.addaddress.contract
import androidx.annotation.DrawableRes
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.ds.button.TangemButtonUM
import com.tangem.domain.models.network.Network
import kotlinx.collections.immutable.ImmutableList
@ -9,19 +10,20 @@ internal data class AddAddressUM(
val addressField: AddressFieldUM,
val availableNetworks: ImmutableList<Network>,
val buttonUM: TangemButtonUM,
val chosenNetworkState: ChosenNetworkState,
val chosenNetworkStateUM: ChosenNetworkStateUM,
val onAddressChange: (String) -> Unit,
val onAddressClear: () -> Unit,
val onPasteClick: () -> Unit,
val onQrClick: () -> Unit,
val onBackClick: () -> Unit,
) {
sealed class ChosenNetworkState {
data object Loading : ChosenNetworkState()
data object Empty : ChosenNetworkState()
@Immutable
sealed class ChosenNetworkStateUM {
data object Loading : ChosenNetworkStateUM()
data object Empty : ChosenNetworkStateUM()
data class Result(
val networkUMList: ImmutableList<NetworkUM>,
) : ChosenNetworkState() {
) : ChosenNetworkStateUM() {
data class NetworkUM(
val networkName: String,

View file

@ -70,7 +70,7 @@ internal class AddAddressModel @Inject constructor(
isError = false,
error = null,
),
chosenNetworkState = AddAddressUM.ChosenNetworkState.Loading,
chosenNetworkStateUM = AddAddressUM.ChosenNetworkStateUM.Loading,
)
}
}
@ -83,21 +83,21 @@ internal class AddAddressModel @Inject constructor(
state.update { oldState ->
oldState.copy(
availableNetworks = availableNetworks,
chosenNetworkState = createChosenNetworkState(availableNetworks),
chosenNetworkStateUM = createChosenNetworkState(availableNetworks),
)
}
}
.launchIn(modelScope)
}
private fun createChosenNetworkState(availableNetworks: ImmutableList<Network>): AddAddressUM.ChosenNetworkState {
private fun createChosenNetworkState(availableNetworks: ImmutableList<Network>): AddAddressUM.ChosenNetworkStateUM {
return if (availableNetworks.isEmpty()) {
AddAddressUM.ChosenNetworkState.Empty
AddAddressUM.ChosenNetworkStateUM.Empty
} else {
AddAddressUM.ChosenNetworkState.Result(
AddAddressUM.ChosenNetworkStateUM.Result(
networkUMList = availableNetworks
.map { network ->
AddAddressUM.ChosenNetworkState.Result.NetworkUM(
AddAddressUM.ChosenNetworkStateUM.Result.NetworkUM(
networkName = network.name,
iconResId = network.iconResId,
)
@ -138,7 +138,7 @@ internal class AddAddressModel @Inject constructor(
isEnabled = false,
onClick = ::validateAndConfirm,
),
chosenNetworkState = AddAddressUM.ChosenNetworkState.Empty,
chosenNetworkStateUM = AddAddressUM.ChosenNetworkStateUM.Empty,
onAddressChange = { onAddressChange(value = it) },
onAddressClear = { onAddressChange("") },
onPasteClick = ::onPaste,

View file

@ -54,7 +54,7 @@ internal fun AddAddressContent(state: AddAddressUM, modifier: Modifier = Modifie
onPasteClick = state.onPasteClick,
)
SpacerH12()
NetworkBlock(state.chosenNetworkState)
NetworkBlock(state.chosenNetworkStateUM)
PrimaryButton(state.buttonUM)
}
}
@ -91,7 +91,7 @@ private fun Preview_AddAddressContent() {
isEnabled = false,
onClick = { },
),
chosenNetworkState = AddAddressUM.ChosenNetworkState.Empty,
chosenNetworkStateUM = AddAddressUM.ChosenNetworkStateUM.Empty,
onAddressChange = {},
onAddressClear = {},
onPasteClick = {},

View file

@ -31,7 +31,7 @@ import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreviewRedesign
import com.tangem.features.addressbook.addaddress.contract.AddAddressUM
import com.tangem.features.addressbook.addaddress.contract.AddAddressUM.ChosenNetworkState.Result.NetworkUM
import com.tangem.features.addressbook.addaddress.contract.AddAddressUM.ChosenNetworkStateUM.Result.NetworkUM
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
@ -44,7 +44,7 @@ private val NetworkIconSize = 24.dp
private val NetworkIconStep = 18.dp
@Composable
internal fun NetworkBlock(chosenNetworkState: AddAddressUM.ChosenNetworkState) {
internal fun NetworkBlock(chosenNetworkStateUM: AddAddressUM.ChosenNetworkStateUM) {
TangemRow(
verticalAlignment = TangemRowVerticalAlignment.Center,
modifier = Modifier
@ -61,20 +61,20 @@ internal fun NetworkBlock(chosenNetworkState: AddAddressUM.ChosenNetworkState) {
)
},
endSlot = {
SelectNetworkButton(chosenNetworkState)
SelectNetworkButton(chosenNetworkStateUM)
},
)
}
@Composable
private fun SelectNetworkButton(chosenNetworkState: AddAddressUM.ChosenNetworkState) {
private fun SelectNetworkButton(chosenNetworkStateUM: AddAddressUM.ChosenNetworkStateUM) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
when (chosenNetworkState) {
is AddAddressUM.ChosenNetworkState.Result -> NetworkIconsResolver(chosenNetworkState.networkUMList)
AddAddressUM.ChosenNetworkState.Loading -> TangemLoader()
AddAddressUM.ChosenNetworkState.Empty -> {
when (chosenNetworkStateUM) {
is AddAddressUM.ChosenNetworkStateUM.Result -> NetworkIconsResolver(chosenNetworkStateUM.networkUMList)
AddAddressUM.ChosenNetworkStateUM.Loading -> TangemLoader()
AddAddressUM.ChosenNetworkStateUM.Empty -> {
Text(
modifier = Modifier.padding(start = 8.dp),
text = stringResourceSafe(R.string.address_book_select_network),
@ -174,7 +174,7 @@ private fun Preview_NetworkBlock() {
TangemThemePreviewRedesign {
Column {
NetworkBlock(
chosenNetworkState = AddAddressUM.ChosenNetworkState.Result(
chosenNetworkStateUM = AddAddressUM.ChosenNetworkStateUM.Result(
networkUMList = persistentListOf(
NetworkUM(networkName = "Ethereum", iconResId = R.drawable.img_eth_22),
),
@ -182,7 +182,7 @@ private fun Preview_NetworkBlock() {
)
SpacerH12()
NetworkBlock(
chosenNetworkState = AddAddressUM.ChosenNetworkState.Result(
chosenNetworkStateUM = AddAddressUM.ChosenNetworkStateUM.Result(
networkUMList = persistentListOf(
NetworkUM(networkName = "Ethereum", iconResId = R.drawable.img_eth_22),
NetworkUM(networkName = "BSC", iconResId = R.drawable.img_bsc_22),
@ -192,16 +192,16 @@ private fun Preview_NetworkBlock() {
)
SpacerH12()
NetworkBlock(
chosenNetworkState = AddAddressUM.ChosenNetworkState.Result(
chosenNetworkStateUM = AddAddressUM.ChosenNetworkStateUM.Result(
networkUMList = List(15) {
NetworkUM(networkName = "Network", iconResId = R.drawable.img_eth_22)
}.toImmutableList(),
),
)
SpacerH12()
NetworkBlock(chosenNetworkState = AddAddressUM.ChosenNetworkState.Loading)
NetworkBlock(chosenNetworkStateUM = AddAddressUM.ChosenNetworkStateUM.Loading)
SpacerH12()
NetworkBlock(chosenNetworkState = AddAddressUM.ChosenNetworkState.Empty)
NetworkBlock(chosenNetworkStateUM = AddAddressUM.ChosenNetworkStateUM.Empty)
}
}
}

View file

@ -144,7 +144,7 @@ internal class AddAddressModelTest {
// Assert
val state = model.state.value
assertThat(state.availableNetworks).containsExactly(ethereum.network)
assertThat(state.chosenNetworkState)
assertThat(state.chosenNetworkStateUM)
.isEqualTo(resultOf(ethereum.network))
}
@ -163,7 +163,7 @@ internal class AddAddressModelTest {
// Assert
val state = model.state.value
assertThat(state.availableNetworks).isEmpty()
assertThat(state.chosenNetworkState).isEqualTo(AddAddressUM.ChosenNetworkState.Empty)
assertThat(state.chosenNetworkStateUM).isEqualTo(AddAddressUM.ChosenNetworkStateUM.Empty)
}
@Test
@ -180,7 +180,7 @@ internal class AddAddressModelTest {
// Assert
val state = model.state.value
assertThat(state.availableNetworks).isEmpty()
assertThat(state.chosenNetworkState).isEqualTo(AddAddressUM.ChosenNetworkState.Empty)
assertThat(state.chosenNetworkStateUM).isEqualTo(AddAddressUM.ChosenNetworkStateUM.Empty)
}
// Covers the "not initialized yet" case: the address is typed before coins load, and the
@ -197,22 +197,22 @@ internal class AddAddressModelTest {
model.state.value.onAddressChange(VALID_ETH_ADDRESS)
advanceUntilIdle()
// Assert intermediate: nothing to match yet
assertThat(model.state.value.chosenNetworkState).isEqualTo(AddAddressUM.ChosenNetworkState.Empty)
assertThat(model.state.value.chosenNetworkStateUM).isEqualTo(AddAddressUM.ChosenNetworkStateUM.Empty)
// Act — coins arrive later
accountsFlow.value = listOf(accountListWith(ethereum, bitcoin))
advanceUntilIdle()
// Assert
assertThat(model.state.value.chosenNetworkState)
assertThat(model.state.value.chosenNetworkStateUM)
.isEqualTo(resultOf(ethereum.network))
}
}
private fun resultOf(vararg networks: Network) = AddAddressUM.ChosenNetworkState.Result(
private fun resultOf(vararg networks: Network) = AddAddressUM.ChosenNetworkStateUM.Result(
networkUMList = networks
.map { network ->
AddAddressUM.ChosenNetworkState.Result.NetworkUM(
AddAddressUM.ChosenNetworkStateUM.Result.NetworkUM(
networkName = network.name,
iconResId = network.iconResId,
)