From 2b46e32197dd6cdedfc42d8f5c4c8ce44b735d99 Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Tue, 25 Jun 2024 12:30:10 +0300 Subject: [PATCH] Render global ids with correct bold ranges --- .../status/address/AddressDetailsDialog.kt | 22 +-- .../address/AddressDetailsDialogViewModel.kt | 81 +++++++-- .../ActionableAddressView.kt | 8 - .../AddressDetailsDialogViewModelTest.kt | 163 +++++++++++++++++- 4 files changed, 225 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialog.kt index aed7c84501..9efc9bbeb3 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialog.kt @@ -61,12 +61,10 @@ import com.babylon.wallet.android.utils.openUrl import com.babylon.wallet.android.utils.shareText import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.Address -import com.radixdlt.sargon.AddressFormat import com.radixdlt.sargon.ComponentAddress import com.radixdlt.sargon.NonFungibleGlobalId import com.radixdlt.sargon.ResourceAddress import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.extensions.formatted import com.radixdlt.sargon.samples.sample import com.radixdlt.sargon.samples.sampleMainnet import kotlinx.collections.immutable.ImmutableList @@ -459,10 +457,7 @@ fun AddressDetailsDialogContentAccountAddressPreview() { title = "My Main Account", sections = listOf( Section.AccountAddressQRCode(accountAddress = address), - Section.FullAddress( - rawAddress = address.formatted(format = AddressFormat.RAW), - truncatedPart = address.formatted(format = AddressFormat.MIDDLE) - ), + Section.FullAddress.from(actionableAddress = actionableAddress), Section.VisitDashboard(url = actionableAddress.dashboardUrl().orEmpty()), Section.VerifyAddressOnLedger(accountAddress = address) ) @@ -494,10 +489,7 @@ fun AddressDetailsDialogContentResourceAddressPreview() { actionableAddress = actionableAddress, title = "Radix (XRD)", sections = listOf( - Section.FullAddress( - rawAddress = address.formatted(format = AddressFormat.RAW), - truncatedPart = address.formatted(format = AddressFormat.MIDDLE) - ), + Section.FullAddress.from(actionableAddress = actionableAddress), Section.VisitDashboard(url = actionableAddress.dashboardUrl().orEmpty()), ) ), @@ -528,10 +520,7 @@ fun AddressDetailsDialogContentGlobalIdPreview() { actionableAddress = actionableAddress, title = "NFT Collection", sections = listOf( - Section.FullAddress( - rawAddress = address.formatted(format = AddressFormat.RAW), - truncatedPart = address.formatted(format = AddressFormat.MIDDLE) - ), + Section.FullAddress.from(actionableAddress = actionableAddress), Section.VisitDashboard(url = actionableAddress.dashboardUrl()), ) ), @@ -562,10 +551,7 @@ fun AddressDetailsDialogContentRandomComponentAddressPreview() { actionableAddress = actionableAddress, title = null, sections = listOf( - Section.FullAddress( - rawAddress = address.formatted(format = AddressFormat.RAW), - truncatedPart = address.formatted(format = AddressFormat.MIDDLE) - ), + Section.FullAddress.from(actionableAddress = actionableAddress), Section.VisitDashboard(url = actionableAddress.dashboardUrl().orEmpty()), ) ), diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialogViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialogViewModel.kt index 0b5a25103c..2091ca41bb 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialogViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialogViewModel.kt @@ -14,9 +14,11 @@ import com.babylon.wallet.android.presentation.common.UiState import com.babylon.wallet.android.presentation.ui.composables.actionableaddress.ActionableAddress import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.Address +import com.radixdlt.sargon.AddressFormat +import com.radixdlt.sargon.extensions.formatted import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import rdx.works.core.domain.resources.Resource @@ -57,12 +59,7 @@ class AddressDetailsDialogViewModel @Inject constructor( sections.add(State.Section.AccountAddressQRCode(accountAddress = actionableAddress.address.v1)) } - sections.add( - State.Section.FullAddress( - rawAddress = actionableAddress.rawAddress(), - truncatedPart = actionableAddress.truncatedPart() - ) - ) + sections.add(State.Section.FullAddress.from(actionableAddress = actionableAddress)) if (actionableAddress.isVisitableInDashboard) { actionableAddress.dashboardUrl()?.let { @@ -302,21 +299,67 @@ class AddressDetailsDialogViewModel @Inject constructor( data class FullAddress( override val order: Short = 1, val rawAddress: String, - val truncatedPart: String + val boldRanges: ImmutableList> ) : Section { - val boldRanges: ImmutableList> = run { - val visibleCharsWhenTruncated = rawAddress.split(truncatedPart) - - if (visibleCharsWhenTruncated.size != 2) return@run persistentListOf() - - val startRange = 0 until visibleCharsWhenTruncated[0].length - val endRange = rawAddress.length - visibleCharsWhenTruncated[1].length until rawAddress.length + companion object { + fun from(actionableAddress: ActionableAddress): FullAddress { + val pairs = when (actionableAddress) { + is ActionableAddress.Address -> + listOf( + actionableAddress.address.formatted( + format = AddressFormat.RAW + ) to actionableAddress.address.formatted( + format = AddressFormat.DEFAULT + ) + ) + + is ActionableAddress.GlobalId -> listOf( + actionableAddress.address.resourceAddress.formatted( + format = AddressFormat.RAW + ) to actionableAddress.address.resourceAddress.formatted( + format = AddressFormat.DEFAULT + ), + actionableAddress.address.nonFungibleLocalId.formatted( + format = AddressFormat.RAW + ) to actionableAddress.address.nonFungibleLocalId.formatted( + format = AddressFormat.DEFAULT + ) + ) + + is ActionableAddress.TransactionId -> listOf( + actionableAddress.hash.formatted( + format = AddressFormat.RAW + ) to actionableAddress.hash.formatted( + format = AddressFormat.DEFAULT + ) + ) + } + + val raw = actionableAddress.rawAddress() + + val boldRanges = mutableListOf>() + pairs.forEach { pair -> + val rawPart = pair.first + val startIndex = raw.indexOf(rawPart) + val boldChars = pair.second.split("...") + + val boldStart = boldChars[0] + val firstPartStartIndex = rawPart.indexOf(boldStart) + startIndex + boldRanges.add(firstPartStartIndex until firstPartStartIndex + boldStart.length) + + val boldEnd = boldChars.getOrNull(1) + if (boldEnd != null) { + val secondPartStartIndex = rawPart.lastIndexOf(boldEnd) + startIndex + boldRanges.add(secondPartStartIndex until secondPartStartIndex + boldEnd.length) + } + } - persistentListOf( - startRange, - endRange - ) + return FullAddress( + rawAddress = raw, + boldRanges = boldRanges.toPersistentList() + ) + } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/actionableaddress/ActionableAddressView.kt b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/actionableaddress/ActionableAddressView.kt index 911c970eda..6f986ec893 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/actionableaddress/ActionableAddressView.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/actionableaddress/ActionableAddressView.kt @@ -241,8 +241,6 @@ sealed interface ActionableAddress { fun rawAddress(): String - fun truncatedPart(): String - fun dashboardUrl(): String? @Composable @@ -271,8 +269,6 @@ sealed interface ActionableAddress { override fun rawAddress(): String = address.formatted(format = AddressFormat.RAW) - override fun truncatedPart(): String = address.formatted(format = AddressFormat.MIDDLE) - override fun dashboardUrl(): String? = when (address) { is com.radixdlt.sargon.Address.AccessController -> null is com.radixdlt.sargon.Address.Account -> "account" @@ -318,8 +314,6 @@ sealed interface ActionableAddress { override fun rawAddress(): String = address.formatted(format = AddressFormat.RAW) - override fun truncatedPart(): String = address.formatted(format = AddressFormat.MIDDLE) - override fun dashboardUrl(): String = "${address.resourceAddress.networkId.dashboardUrl()}/nft/${address.string.encodeUtf8()}" @Composable @@ -362,8 +356,6 @@ sealed interface ActionableAddress { override fun rawAddress(): String = hash.formatted(format = AddressFormat.RAW) - override fun truncatedPart(): String = hash.formatted(format = AddressFormat.MIDDLE) - override fun dashboardUrl(): String = "${hash.networkId.dashboardUrl()}/transaction/${hash.bech32EncodedTxId.encodeUtf8()}" @Composable diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialogViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialogViewModelTest.kt index bfd1e666c3..98608e5c48 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialogViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/status/address/AddressDetailsDialogViewModelTest.kt @@ -20,17 +20,25 @@ import com.radixdlt.sargon.DisplayName import com.radixdlt.sargon.FactorSource import com.radixdlt.sargon.HierarchicalDeterministicPublicKey import com.radixdlt.sargon.IdentityAddress +import com.radixdlt.sargon.IntentHash import com.radixdlt.sargon.NetworkId +import com.radixdlt.sargon.NonEmptyMax64Bytes +import com.radixdlt.sargon.NonFungibleGlobalId +import com.radixdlt.sargon.NonFungibleLocalId +import com.radixdlt.sargon.NonFungibleLocalIdString import com.radixdlt.sargon.Profile import com.radixdlt.sargon.extensions.asGeneral import com.radixdlt.sargon.extensions.formatted import com.radixdlt.sargon.extensions.init +import com.radixdlt.sargon.extensions.string +import com.radixdlt.sargon.extensions.toBagOfBytes import com.radixdlt.sargon.samples.sample import com.radixdlt.sargon.samples.sampleMainnet import com.radixdlt.sargon.samples.sampleRandom import io.mockk.coEvery import io.mockk.every import io.mockk.mockk +import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest @@ -51,6 +59,7 @@ import rdx.works.core.sargon.initBabylon import rdx.works.core.sargon.isLedgerAccount import rdx.works.core.sargon.sample import rdx.works.profile.domain.GetProfileUseCase +import kotlin.random.Random class AddressDetailsDialogViewModelTest : StateViewModelTest() { @@ -82,10 +91,15 @@ class AddressDetailsDialogViewModelTest : StateViewModelTest