From d35af95bc70a07de69b4d29587708756d5df3717 Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Mon, 24 Jun 2024 15:59:52 +0300 Subject: [PATCH 01/18] Add next cursor information on metadata column --- .../repository/cache/database/DAppEntity.kt | 6 +- .../repository/cache/database/NFTEntity.kt | 4 +- .../repository/cache/database/PoolEntity.kt | 10 ++- .../cache/database/ProvidedConverters.kt | 79 +++++++++++++++++-- .../cache/database/ResourceEntity.kt | 16 ++-- .../cache/database/StateDatabase.kt | 7 +- .../cache/database/ValidatorEntity.kt | 31 +++----- .../repository/state/AccountsStateCache.kt | 16 ++-- .../data/repository/state/StateRepository.kt | 17 ++-- .../usecases/assets/GetLSUDetailsUseCase.kt | 38 --------- .../usecases/assets/ObserveResourceUseCase.kt | 42 ---------- .../data/cache/ProvidedConvertersTest.kt | 9 ++- 12 files changed, 131 insertions(+), 144 deletions(-) delete mode 100644 app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetLSUDetailsUseCase.kt delete mode 100644 app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ObserveResourceUseCase.kt diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/DAppEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/DAppEntity.kt index b7b18fa74e..b6ded0778b 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/DAppEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/DAppEntity.kt @@ -3,7 +3,6 @@ package com.babylon.wallet.android.data.repository.cache.database import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey -import com.babylon.wallet.android.data.gateway.extensions.toMetadata import com.babylon.wallet.android.data.gateway.generated.models.StateEntityDetailsResponseItem import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.extensions.init @@ -27,7 +26,10 @@ data class DAppEntity( companion object { fun from(item: StateEntityDetailsResponseItem, syncedAt: Instant) = DAppEntity( definitionAddress = AccountAddress.init(item.address), - metadata = item.explicitMetadata?.toMetadata()?.let { MetadataColumn(it) }, + metadata = MetadataColumn.from( + explicitMetadata = item.explicitMetadata, + implicitMetadata = item.metadata + ), synced = syncedAt ) } diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/NFTEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/NFTEntity.kt index ac89cc3324..e1692d3cab 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/NFTEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/NFTEntity.kt @@ -37,7 +37,7 @@ data class NFTEntity( metadata = toMetadata().takeIf { it.isNotEmpty() }?.let { - MetadataColumn(it) + MetadataColumn(metadata = it, implicitState = MetadataColumn.ImplicitMetadataState.Complete) }, synced = synced ) @@ -49,7 +49,7 @@ data class NFTEntity( metadata = metadata.takeIf { it.isNotEmpty() }?.let { - MetadataColumn(it) + MetadataColumn(metadata = it, implicitState = MetadataColumn.ImplicitMetadataState.Complete) }, synced = synced ) diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt index e69bdde5ce..972e4de6f1 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/PoolEntity.kt @@ -6,7 +6,6 @@ import androidx.room.ForeignKey import androidx.room.Index import androidx.room.PrimaryKey import com.babylon.wallet.android.data.gateway.extensions.PoolsResponse -import com.babylon.wallet.android.data.gateway.extensions.toMetadata import com.babylon.wallet.android.data.gateway.generated.models.StateEntityDetailsResponseItem import com.babylon.wallet.android.data.repository.cache.database.PoolResourceJoin.Companion.asPoolResourceJoin import com.babylon.wallet.android.data.repository.cache.database.ResourceEntity.Companion.asEntity @@ -60,11 +59,14 @@ data class PoolEntity( } fun StateEntityDetailsResponseItem.asPoolEntity(): PoolEntity? { - val metadata = this.metadata.toMetadata() - val poolUnitResourceAddress = metadata.poolUnit() ?: return null + val metadataColumn = MetadataColumn.from( + explicitMetadata = explicitMetadata, + implicitMetadata = metadata + ) + val poolUnitResourceAddress = metadataColumn.metadata.poolUnit() ?: return null return PoolEntity( address = PoolAddress.init(address), - metadata = MetadataColumn(metadata), + metadata = metadataColumn, resourceAddress = poolUnitResourceAddress ) } diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt index 9981253788..a987550545 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt @@ -2,6 +2,9 @@ package com.babylon.wallet.android.data.repository.cache.database import androidx.room.ProvidedTypeConverter import androidx.room.TypeConverter +import com.babylon.wallet.android.data.gateway.extensions.toMetadata +import com.babylon.wallet.android.data.gateway.generated.models.EntityMetadataCollection +import com.babylon.wallet.android.data.repository.cache.database.MetadataColumn.ImplicitMetadataState import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.Decimal192 import com.radixdlt.sargon.NonFungibleLocalId @@ -12,6 +15,7 @@ import com.radixdlt.sargon.VaultAddress import com.radixdlt.sargon.extensions.init import com.radixdlt.sargon.extensions.string import com.radixdlt.sargon.extensions.toDecimal192OrNull +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json @@ -24,7 +28,72 @@ import java.time.Instant data class BehavioursColumn(val behaviours: Set) @Serializable -data class MetadataColumn(val metadata: List) +data class MetadataColumn( + /** + * A union of explicit and **currently known** implicit metadata + * As a client we don't need to expose the difference between explicit + * and implicit metadata. + */ + val metadata: List, + + /** + * The state of the next page of the implicit metadata. See [ImplicitMetadataState] + */ + @SerialName("implicit_state") + val implicitState: ImplicitMetadataState +) { + + @Serializable + sealed interface ImplicitMetadataState { + /** + * When we have no information yet regarding the existence of implicit metadata + * An example is when we query account information. In this request we receive + * resource data but with no information about implicit metadata. In order to make + * sure we received all metadata available we need to fetch details of this specific + * resource + */ + @Serializable + @SerialName("unknown") + data object Unknown: ImplicitMetadataState + + /** + * We have received an answer from a details request and we know that the [MetadataColumn.metadata] + * are complete. + */ + @Serializable + @SerialName("complete") + data object Complete: ImplicitMetadataState + + /** + * We have received an answer from a details request and we know that the [MetadataColumn.metadata] + * are incomplete. We need to query [nextCursor] to receive more. + */ + @Serializable + @SerialName("incomplete") + data class Incomplete( + @SerialName("next_cursor") + val nextCursor: String? + ): ImplicitMetadataState + } + + companion object { + fun from( + explicitMetadata: EntityMetadataCollection?, + implicitMetadata: EntityMetadataCollection + ): MetadataColumn { + val explicit = explicitMetadata?.toMetadata().orEmpty().toSet() + val implicit = implicitMetadata.toMetadata().toSet() + + val all = explicit union implicit + return MetadataColumn( + metadata = all.toList(), + implicitState = implicitMetadata.nextCursor?.let { + ImplicitMetadataState.Incomplete(nextCursor = it) + } ?: ImplicitMetadataState.Complete + ) + } + } +} @Suppress("TooManyFunctions") @ProvidedTypeConverter @@ -37,23 +106,23 @@ class StateDatabaseConverters { // Behaviours @TypeConverter fun stringToBehaviours(string: String?): BehavioursColumn? { - return string?.let { BehavioursColumn(behaviours = json.decodeFromString(string)) } + return string?.let { json.decodeFromString(string) } } @TypeConverter fun behavioursToString(column: BehavioursColumn?): String? { - return column?.let { json.encodeToString(it.behaviours) } + return column?.let { json.encodeToString(it) } } // Metadata @TypeConverter fun stringToMetadata(string: String?): MetadataColumn? { - return string?.let { MetadataColumn(metadata = json.decodeFromString(string)) } + return string?.let { json.decodeFromString(string) } } @TypeConverter fun metadataToString(column: MetadataColumn?): String? { - return column?.let { json.encodeToString(it.metadata) } + return column?.let { json.encodeToString(it) } } // Decimal192 diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt index cf7f2625a8..ed91321247 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt @@ -99,7 +99,7 @@ data class ResourceEntity( metadata = metadata .filterNot { it.key in setOf(ExplicitMetadataKey.POOL.key, ExplicitMetadataKey.VALIDATOR.key) } .takeIf { it.isNotEmpty() } - ?.let { MetadataColumn(it) }, + ?.let { MetadataColumn(it, MetadataColumn.ImplicitMetadataState.Unknown) }, synced = synced ) @@ -114,7 +114,7 @@ data class ResourceEntity( metadata = metadata .filterNot { it.key in setOf(ExplicitMetadataKey.POOL.key, ExplicitMetadataKey.VALIDATOR.key) } .takeIf { it.isNotEmpty() } - ?.let { MetadataColumn(it) }, + ?.let { MetadataColumn(it, MetadataColumn.ImplicitMetadataState.Unknown) }, synced = synced ) } @@ -126,7 +126,7 @@ data class ResourceEntity( details: StateEntityDetailsResponseItemDetails? = null ): ResourceEntity = from( address = ResourceAddress.init(resourceAddress), - metadataCollection = explicitMetadata, + explicitMetadata = explicitMetadata, details = details, type = ResourceEntityType.FUNGIBLE, synced = synced @@ -139,7 +139,7 @@ data class ResourceEntity( details: StateEntityDetailsResponseItemDetails? = null ): ResourceEntity = from( address = ResourceAddress.init(resourceAddress), - metadataCollection = explicitMetadata, + explicitMetadata = explicitMetadata, details = details, type = ResourceEntityType.NON_FUNGIBLE, synced = synced @@ -156,7 +156,7 @@ data class ResourceEntity( } return from( address = ResourceAddress.init(address), - metadataCollection = metadata, + explicitMetadata = metadata, details = details, type = type, synced = synced @@ -165,12 +165,12 @@ data class ResourceEntity( private fun from( address: ResourceAddress, - metadataCollection: EntityMetadataCollection?, + explicitMetadata: EntityMetadataCollection?, details: StateEntityDetailsResponseItemDetails?, type: ResourceEntityType, synced: Instant ): ResourceEntity { - val metadata = metadataCollection?.toMetadata().orEmpty() + val metadata = explicitMetadata?.toMetadata().orEmpty() return ResourceEntity( address = address, type = type, @@ -182,7 +182,7 @@ data class ResourceEntity( metadata = metadata .filterNot { it.key in setOf(ExplicitMetadataKey.VALIDATOR.key, ExplicitMetadataKey.POOL.key) } .takeIf { it.isNotEmpty() } - ?.let { MetadataColumn(it) }, + ?.let { MetadataColumn(it, MetadataColumn.ImplicitMetadataState.Unknown) }, synced = synced ) } diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt index 90ef12b87d..35d0e18c5c 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt @@ -20,7 +20,7 @@ import androidx.room.TypeConverters PoolDAppJoin::class, TokenPriceEntity::class ], - version = StateDatabase.VERSION_8 + version = StateDatabase.VERSION_9 ) @TypeConverters(StateDatabaseConverters::class) abstract class StateDatabase : RoomDatabase() { @@ -51,9 +51,12 @@ abstract class StateDatabase : RoomDatabase() { @Deprecated("Add TokenPriceEntity to schema") const val VERSION_7 = 7 - // Replace BigDecimal with Decimal192 + @Deprecated("Replace BigDecimal with Decimal192") const val VERSION_8 = 8 + // Added next cursor to metadata column + const val VERSION_9 = 9 + private const val NAME = "STATE_DATABASE" fun factory(applicationContext: Context): StateDatabase = Room diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ValidatorEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ValidatorEntity.kt index d48548e363..8c67d5d5c5 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ValidatorEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ValidatorEntity.kt @@ -5,7 +5,6 @@ import androidx.room.Entity import androidx.room.PrimaryKey import com.babylon.wallet.android.data.gateway.extensions.claimTokenResourceAddress import com.babylon.wallet.android.data.gateway.extensions.stakeUnitResourceAddress -import com.babylon.wallet.android.data.gateway.extensions.toMetadata import com.babylon.wallet.android.data.gateway.extensions.totalXRDStake import com.babylon.wallet.android.data.gateway.generated.models.StateEntityDetailsResponseItem import com.radixdlt.sargon.Decimal192 @@ -38,28 +37,16 @@ data class ValidatorEntity( ) companion object { - fun Validator.asValidatorEntity(syncInfo: SyncInfo) = ValidatorEntity( - address = address, - stakeUnitResourceAddress = stakeUnitResourceAddress, - claimTokenResourceAddress = claimTokenResourceAddress, - totalStake = totalXrdStake, - metadata = metadata.takeIf { it.isNotEmpty() }?.let { MetadataColumn(it) }, + fun StateEntityDetailsResponseItem.asValidatorEntity(syncInfo: SyncInfo) = ValidatorEntity( + address = ValidatorAddress.init(address), + stakeUnitResourceAddress = details?.stakeUnitResourceAddress?.let { ResourceAddress.init(it) }, + claimTokenResourceAddress = details?.claimTokenResourceAddress?.let { ResourceAddress.init(it) }, + totalStake = totalXRDStake, + metadata = MetadataColumn.from( + explicitMetadata = explicitMetadata, + implicitMetadata = metadata + ), stateVersion = syncInfo.accountStateVersion ) - - fun List.asValidators() = map { item -> - val metadata = item.explicitMetadata?.toMetadata().orEmpty() - Validator( - address = ValidatorAddress.init(item.address), - totalXrdStake = item.totalXRDStake, - stakeUnitResourceAddress = item.details?.stakeUnitResourceAddress?.let { ResourceAddress.init(it) }, - claimTokenResourceAddress = item.details?.claimTokenResourceAddress?.let { ResourceAddress.init(it) }, - metadata = metadata - ) - } - - fun List.asValidatorEntities(syncInfo: SyncInfo) = map { item -> - item.asValidatorEntity(syncInfo) - } } } diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt index f07d9ac0ce..270664d2ed 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt @@ -11,8 +11,7 @@ import com.babylon.wallet.android.data.repository.cache.database.StateDao import com.babylon.wallet.android.data.repository.cache.database.StateDao.Companion.accountCacheValidity import com.babylon.wallet.android.data.repository.cache.database.StateDatabase import com.babylon.wallet.android.data.repository.cache.database.SyncInfo -import com.babylon.wallet.android.data.repository.cache.database.ValidatorEntity.Companion.asValidatorEntities -import com.babylon.wallet.android.data.repository.cache.database.ValidatorEntity.Companion.asValidators +import com.babylon.wallet.android.data.repository.cache.database.ValidatorEntity.Companion.asValidatorEntity import com.babylon.wallet.android.data.repository.cache.database.getCachedPools import com.babylon.wallet.android.data.repository.cache.database.getCachedValidators import com.babylon.wallet.android.di.coroutines.ApplicationScope @@ -244,11 +243,16 @@ class AccountsStateCache @Inject constructor( val allValidatorAddresses = cached.map { it.value.validatorAddresses() }.flatten().toSet() val cachedValidators = dao.getCachedValidators(allValidatorAddresses, stateVersion).toMutableMap() val newValidators = runCatching { - api.fetchValidators( + val validatorItems = api.fetchValidators( allValidatorAddresses - cachedValidators.keys, stateVersion - ).validators.asValidators().onEach { - cachedValidators[it.address] = it + ).validators + + val syncInfo = SyncInfo(InstantGenerator(), stateVersion) + validatorItems.map { + it.asValidatorEntity(syncInfo) + }.onEach { entity -> + cachedValidators[entity.address] = entity.asValidatorDetail() } }.onFailure { error -> cacheErrors.value = error @@ -256,7 +260,7 @@ class AccountsStateCache @Inject constructor( if (newValidators.isNotEmpty()) { logger.d("\uD83D\uDCBD Inserting validators") - dao.insertValidators(newValidators.asValidatorEntities(SyncInfo(InstantGenerator(), stateVersion))) + dao.insertValidators(newValidators) } val allPoolAddresses = cached.map { it.value.poolAddresses() }.flatten().toSet() diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt index 4b0c225141..e67b9d1b93 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt @@ -17,7 +17,6 @@ import com.babylon.wallet.android.data.repository.cache.database.StateDao.Compan import com.babylon.wallet.android.data.repository.cache.database.StateDao.Companion.resourcesCacheValidity import com.babylon.wallet.android.data.repository.cache.database.SyncInfo import com.babylon.wallet.android.data.repository.cache.database.ValidatorEntity.Companion.asValidatorEntity -import com.babylon.wallet.android.data.repository.cache.database.ValidatorEntity.Companion.asValidators import com.babylon.wallet.android.data.repository.cache.database.getCachedPools import com.babylon.wallet.android.data.repository.cache.database.storeAccountNFTsPortfolio import com.babylon.wallet.android.data.repository.cache.database.updateResourceDetails @@ -395,9 +394,7 @@ class StateRepositoryImpl @Inject constructor( runCatching { val stateVersion = getLatestCachedStateVersionInNetwork() val cachedValidators = if (stateVersion != null) { - stateDao.getValidators(addresses = validatorAddresses.toSet(), atStateVersion = stateVersion).map { - it.asValidatorDetail() - } + stateDao.getValidators(addresses = validatorAddresses.toSet(), atStateVersion = stateVersion) } else { emptyList() } @@ -408,15 +405,17 @@ class StateRepositoryImpl @Inject constructor( validatorsAddresses = unknownAddresses, stateVersion = stateVersion ) - val details = response.validators.asValidators() - if (details.isNotEmpty()) { - val syncInfo = SyncInfo(InstantGenerator(), requireNotNull(response.stateVersion)) - stateDao.insertValidators(details.map { it.asValidatorEntity(syncInfo) }) + + val syncInfo = SyncInfo(InstantGenerator(), requireNotNull(response.stateVersion)) + val newValidatorEntities = response.validators.map { it.asValidatorEntity(syncInfo) }.also { entities -> + stateDao.insertValidators(entities) } - details + cachedValidators + newValidatorEntities + cachedValidators } else { cachedValidators } + }.mapCatching { entities -> + entities.map { it.asValidatorDetail() } } } diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetLSUDetailsUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetLSUDetailsUseCase.kt deleted file mode 100644 index 47d8be8193..0000000000 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/GetLSUDetailsUseCase.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.babylon.wallet.android.domain.usecases.assets - -import com.babylon.wallet.android.data.repository.state.StateRepository -import com.radixdlt.sargon.AccountAddress -import com.radixdlt.sargon.ResourceAddress -import rdx.works.core.domain.assets.LiquidStakeUnit -import rdx.works.core.domain.assets.ValidatorWithStakes -import rdx.works.core.domain.resources.Resource -import rdx.works.core.then -import java.lang.RuntimeException -import javax.inject.Inject - -/** - * Returns the LSU with validator details. Currently this use case does not return the associated claims. - */ -class GetLSUDetailsUseCase @Inject constructor( - private val stateRepository: StateRepository -) { - - suspend operator fun invoke(resourceAddress: ResourceAddress, accountAddress: AccountAddress): Result = - stateRepository.getResources( - addresses = setOf(resourceAddress), - underAccountAddress = accountAddress, - withDetails = true - ).mapCatching { - it.first() as Resource.FungibleResource - }.then { stake -> - val validatorAddress = stake.validatorAddress - ?: return@then Result.failure(RuntimeException("Resource $resourceAddress has no associated validator")) - stateRepository.getValidators(validatorAddresses = setOf(validatorAddress)).mapCatching { validators -> - val validator = validators.first() - ValidatorWithStakes( - validator = validator, - liquidStakeUnit = LiquidStakeUnit(stake, validator) - ) - } - } -} diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ObserveResourceUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ObserveResourceUseCase.kt deleted file mode 100644 index a2bcdc9b7f..0000000000 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ObserveResourceUseCase.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.babylon.wallet.android.domain.usecases.assets - -import com.babylon.wallet.android.data.repository.state.StateRepository -import com.radixdlt.sargon.AccountAddress -import com.radixdlt.sargon.ResourceAddress -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import rdx.works.core.domain.resources.Resource -import javax.inject.Inject - -/** - * Fetches details regarding this fungible/non-fungible by looking it up through its address. - * If an account address is provided, the repository will try to also fetch amount information. - */ -class ObserveResourceUseCase @Inject constructor( - private val stateRepository: StateRepository -) { - - operator fun invoke( - resourceAddress: ResourceAddress, - accountAddress: AccountAddress? = null, - withDetails: Boolean = true - ): Flow = flow { - val resource = stateRepository.getResources( - addresses = setOf(resourceAddress), - underAccountAddress = accountAddress, - withDetails = false - ).getOrThrow().first() - - emit(resource) - - if (!resource.isDetailsAvailable && withDetails) { - val resourceWithDetails = stateRepository.getResources( - addresses = setOf(resourceAddress), - underAccountAddress = accountAddress, - withDetails = true - ).getOrThrow().first() - - emit(resourceWithDetails) - } - } -} diff --git a/app/src/test/java/com/babylon/wallet/android/data/cache/ProvidedConvertersTest.kt b/app/src/test/java/com/babylon/wallet/android/data/cache/ProvidedConvertersTest.kt index a5f10bb2ae..46a5a3e520 100644 --- a/app/src/test/java/com/babylon/wallet/android/data/cache/ProvidedConvertersTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/data/cache/ProvidedConvertersTest.kt @@ -3,12 +3,12 @@ package com.babylon.wallet.android.data.cache import com.babylon.wallet.android.data.repository.cache.database.BehavioursColumn import com.babylon.wallet.android.data.repository.cache.database.MetadataColumn import com.babylon.wallet.android.data.repository.cache.database.StateDatabaseConverters -import rdx.works.core.domain.assets.AssetBehaviour -import rdx.works.core.domain.resources.metadata.Metadata -import rdx.works.core.domain.resources.metadata.MetadataType import org.junit.Assert.assertEquals import org.junit.Assert.assertNull import org.junit.Test +import rdx.works.core.domain.assets.AssetBehaviour +import rdx.works.core.domain.resources.metadata.Metadata +import rdx.works.core.domain.resources.metadata.MetadataType class ProvidedConvertersTest { @@ -100,7 +100,8 @@ class ProvidedConvertersTest { ) to Metadata.Primitive("value", "Value", MetadataType.String) ) ) - ) + ), + implicitState = MetadataColumn.ImplicitMetadataState.Unknown ) val converter = StateDatabaseConverters() From 301a188acdc3ab5e5b2aa271d671af98c573111d Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Tue, 25 Jun 2024 16:48:54 +0300 Subject: [PATCH 02/18] Request all pages of metadata for asset details dialog --- .../extensions/StateEntityDetailsApiHelper.kt | 27 ++++++++ .../MetadataTypedValueSerializer.kt | 3 +- .../cache/database/ProvidedConverters.kt | 5 +- .../cache/database/ResourceEntity.kt | 41 +++++++++--- .../repository/cache/database/StateDao.kt | 10 +++ .../data/repository/state/StateRepository.kt | 64 +++++++++++++------ .../usecases/GetDAppWithResourcesUseCase.kt | 3 +- .../domain/usecases/GetResourcesUseCase.kt | 11 +++- .../assets/ResolveAssetsFromAddressUseCase.kt | 6 +- .../GetTransactionBadgesUseCase.kt | 3 +- .../status/assets/AssetDialogViewModel.kt | 3 +- 11 files changed, 139 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt index fe138a4042..9aeb9cb261 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/StateEntityDetailsApiHelper.kt @@ -1,6 +1,7 @@ package com.babylon.wallet.android.data.gateway.extensions import com.babylon.wallet.android.data.gateway.apis.StateApi +import com.babylon.wallet.android.data.gateway.generated.models.EntityMetadataItem import com.babylon.wallet.android.data.gateway.generated.models.FungibleResourcesCollection import com.babylon.wallet.android.data.gateway.generated.models.FungibleResourcesCollectionItem import com.babylon.wallet.android.data.gateway.generated.models.LedgerState @@ -15,6 +16,7 @@ import com.babylon.wallet.android.data.gateway.generated.models.StateEntityDetai import com.babylon.wallet.android.data.gateway.generated.models.StateEntityDetailsResponseItem import com.babylon.wallet.android.data.gateway.generated.models.StateEntityFungiblesPageRequest import com.babylon.wallet.android.data.gateway.generated.models.StateEntityFungiblesPageRequestOptIns +import com.babylon.wallet.android.data.gateway.generated.models.StateEntityMetadataPageRequest import com.babylon.wallet.android.data.gateway.generated.models.StateEntityNonFungibleIdsPageRequest import com.babylon.wallet.android.data.gateway.generated.models.StateEntityNonFungiblesPageRequest import com.babylon.wallet.android.data.gateway.generated.models.StateEntityNonFungiblesPageRequestOptIns @@ -386,3 +388,28 @@ suspend fun StateApi.paginateNonFungibles( onPage(response) } } + +suspend fun StateApi.getAllMetadata( + resourceAddress: ResourceAddress, + stateVersion: Long, + initialCursor: String +): List { + val items = mutableListOf() + + var cursor: String? = initialCursor + while (cursor != null) { + val page = entityMetadataPage( + stateEntityMetadataPageRequest = StateEntityMetadataPageRequest( + address = resourceAddress.string, + cursor = initialCursor, + atLedgerState = LedgerStateSelector( + stateVersion = stateVersion + ) + ) + ).toResult().getOrThrow() + cursor = page.nextCursor + items.addAll(page.items) + } + + return items +} diff --git a/app/src/main/java/com/babylon/wallet/android/data/gateway/serialisers/MetadataTypedValueSerializer.kt b/app/src/main/java/com/babylon/wallet/android/data/gateway/serialisers/MetadataTypedValueSerializer.kt index 366ef32224..ec339650af 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/gateway/serialisers/MetadataTypedValueSerializer.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/gateway/serialisers/MetadataTypedValueSerializer.kt @@ -25,6 +25,7 @@ import com.babylon.wallet.android.data.gateway.generated.models.MetadataPublicKe import com.babylon.wallet.android.data.gateway.generated.models.MetadataStringArrayValue import com.babylon.wallet.android.data.gateway.generated.models.MetadataStringValue import com.babylon.wallet.android.data.gateway.generated.models.MetadataTypedValue +import com.babylon.wallet.android.data.gateway.generated.models.MetadataU32ArrayValue import com.babylon.wallet.android.data.gateway.generated.models.MetadataU32Value import com.babylon.wallet.android.data.gateway.generated.models.MetadataU64ArrayValue import com.babylon.wallet.android.data.gateway.generated.models.MetadataU64Value @@ -62,7 +63,7 @@ object MetadataTypedValueSerializer : JsonContentPolymorphicSerializer MetadataStringArrayValue.serializer() MetadataValueType.BoolArray -> MetadataBoolArrayValue.serializer() MetadataValueType.U8Array -> MetadataU8ArrayValue.serializer() - MetadataValueType.U32Array -> MetadataU32Value.serializer() + MetadataValueType.U32Array -> MetadataU32ArrayValue.serializer() MetadataValueType.U64Array -> MetadataU64ArrayValue.serializer() MetadataValueType.I32Array -> MetadataI32ArrayValue.serializer() MetadataValueType.I64Array -> MetadataI64ArrayValue.serializer() diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt index a987550545..bbb42eacae 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt @@ -43,6 +43,9 @@ data class MetadataColumn( val implicitState: ImplicitMetadataState ) { + val nextCursor: String? + get() = (implicitState as? ImplicitMetadataState.Incomplete)?.nextCursor + @Serializable sealed interface ImplicitMetadataState { /** @@ -72,7 +75,7 @@ data class MetadataColumn( @SerialName("incomplete") data class Incomplete( @SerialName("next_cursor") - val nextCursor: String? + val nextCursor: String ): ImplicitMetadataState } diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt index ed91321247..eb1f9ef78d 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt @@ -50,6 +50,12 @@ data class ResourceEntity( val synced: Instant ) { + val isDetailsAvailable: Boolean + get() = when (type) { + ResourceEntityType.FUNGIBLE -> supply != null && divisibility != null && behaviours != null + ResourceEntityType.NON_FUNGIBLE -> supply != null && behaviours != null + } + @Suppress("CyclomaticComplexMethod") fun toResource(amount: Decimal192?): Resource { val validatorAndPoolMetadata = listOf( @@ -127,6 +133,7 @@ data class ResourceEntity( ): ResourceEntity = from( address = ResourceAddress.init(resourceAddress), explicitMetadata = explicitMetadata, + implicitMetadata = null, details = details, type = ResourceEntityType.FUNGIBLE, synced = synced @@ -140,6 +147,7 @@ data class ResourceEntity( ): ResourceEntity = from( address = ResourceAddress.init(resourceAddress), explicitMetadata = explicitMetadata, + implicitMetadata = null, details = details, type = ResourceEntityType.NON_FUNGIBLE, synced = synced @@ -156,7 +164,8 @@ data class ResourceEntity( } return from( address = ResourceAddress.init(address), - explicitMetadata = metadata, + explicitMetadata = explicitMetadata, + implicitMetadata = metadata, details = details, type = type, synced = synced @@ -166,23 +175,39 @@ data class ResourceEntity( private fun from( address: ResourceAddress, explicitMetadata: EntityMetadataCollection?, + implicitMetadata: EntityMetadataCollection?, details: StateEntityDetailsResponseItemDetails?, type: ResourceEntityType, synced: Instant ): ResourceEntity { - val metadata = explicitMetadata?.toMetadata().orEmpty() + val metadataColumn = if (implicitMetadata != null) { + MetadataColumn.from( + explicitMetadata = explicitMetadata, + implicitMetadata = implicitMetadata + ) + } else { + MetadataColumn( + metadata = explicitMetadata?.toMetadata().orEmpty(), + implicitState = MetadataColumn.ImplicitMetadataState.Unknown + ) + } + return ResourceEntity( address = address, type = type, divisibility = details?.divisibility(), behaviours = details?.let { BehavioursColumn(it.extractBehaviours()) }, supply = details?.totalSupply(), - validatorAddress = metadata.validatorAddress(), - poolAddress = metadata.poolAddress(), - metadata = metadata - .filterNot { it.key in setOf(ExplicitMetadataKey.VALIDATOR.key, ExplicitMetadataKey.POOL.key) } - .takeIf { it.isNotEmpty() } - ?.let { MetadataColumn(it, MetadataColumn.ImplicitMetadataState.Unknown) }, + validatorAddress = metadataColumn.metadata.validatorAddress(), + poolAddress = metadataColumn.metadata.poolAddress(), + metadata = metadataColumn.copy( + metadata = metadataColumn.metadata.filterNot { + it.key in setOf( + ExplicitMetadataKey.VALIDATOR.key, + ExplicitMetadataKey.POOL.key + ) + } + ).takeIf { it.metadata.isNotEmpty() }, synced = synced ) } diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt index 2156845bdc..a92453e6c1 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt @@ -324,6 +324,16 @@ interface StateDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertDApps(dApps: List) + + @Query( + """ + UPDATE ResourceEntity SET + metadata = :metadataColumn + WHERE address = :resourceAddress + """ + ) + fun updateMetadata(resourceAddress: ResourceAddress, metadataColumn: MetadataColumn) + companion object { val deleteDuration = 1.toDuration(DurationUnit.SECONDS) private val accountsCacheDuration = 2.toDuration(DurationUnit.HOURS) diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt index e67b9d1b93..d7c5e2dd7a 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt @@ -3,11 +3,13 @@ package com.babylon.wallet.android.data.repository.state import com.babylon.wallet.android.data.gateway.apis.StateApi import com.babylon.wallet.android.data.gateway.extensions.fetchPools import com.babylon.wallet.android.data.gateway.extensions.fetchValidators +import com.babylon.wallet.android.data.gateway.extensions.getAllMetadata import com.babylon.wallet.android.data.gateway.extensions.getNextNftItems import com.babylon.wallet.android.data.gateway.extensions.paginateDetails import com.babylon.wallet.android.data.gateway.extensions.paginateNonFungibles import com.babylon.wallet.android.data.gateway.extensions.toMetadata import com.babylon.wallet.android.data.repository.cache.database.DAppEntity +import com.babylon.wallet.android.data.repository.cache.database.MetadataColumn import com.babylon.wallet.android.data.repository.cache.database.NFTEntity.Companion.asEntity import com.babylon.wallet.android.data.repository.cache.database.PoolEntity.Companion.asPoolsResourcesJoin import com.babylon.wallet.android.data.repository.cache.database.ResourceEntity @@ -69,7 +71,8 @@ interface StateRepository { suspend fun getResources( addresses: Set, underAccountAddress: AccountAddress?, - withDetails: Boolean + withDetails: Boolean, + withAllMetadata: Boolean ): Result> suspend fun getPools(poolAddresses: Set): Result> @@ -317,23 +320,18 @@ class StateRepositoryImpl @Inject constructor( override suspend fun getResources( addresses: Set, underAccountAddress: AccountAddress?, - withDetails: Boolean + withDetails: Boolean, + withAllMetadata: Boolean ): Result> = withContext(dispatcher) { runCatching { - val addressesWithResources = addresses.associateWith { address -> - val cachedEntity = stateDao.getResourceDetails( + val addressesWithResourceEntities = addresses.associateWith { address -> + stateDao.getResourceDetails( resourceAddress = address, minValidity = resourcesCacheValidity() ) - - val amount = underAccountAddress?.let { accountAddress -> - stateDao.getAccountResourceJoin(resourceAddress = address, accountAddress = accountAddress)?.amount - } - - cachedEntity?.toResource(amount) }.toMutableMap() - val resourcesToFetch = addressesWithResources.mapNotNull { entry -> + val resourcesToFetch = addressesWithResourceEntities.mapNotNull { entry -> val cachedResource = entry.value if (cachedResource == null || !cachedResource.isDetailsAvailable && withDetails) entry.key else null } @@ -343,22 +341,48 @@ class StateRepositoryImpl @Inject constructor( metadataKeys = ExplicitMetadataKey.forAssets, onPage = { page -> page.items.forEach { item -> - val amount = underAccountAddress?.let { accountAddress -> - stateDao.getAccountResourceJoin( - resourceAddress = ResourceAddress.init(item.address), - accountAddress = accountAddress - )?.amount - } val updatedEntity = stateDao.updateResourceDetails(item) - val resource = updatedEntity.toResource(amount) - addressesWithResources[resource.address] = resource + addressesWithResourceEntities[updatedEntity.address] = updatedEntity } } ) } - addressesWithResources.values.filterNotNull() + addressesWithResourceEntities.values.filterNotNull().map { resourceEntity -> + val amount = underAccountAddress?.let { accountAddress -> + stateDao.getAccountResourceJoin(resourceAddress = resourceEntity.address, accountAddress = accountAddress)?.amount + } + + val nextMetadataCursor = resourceEntity.metadata?.nextCursor + if (withAllMetadata && nextMetadataCursor != null) { + val remainingMetadata = runCatching { + val stateVersion = requireNotNull(getLatestCachedStateVersionInNetwork()) + + stateApi.getAllMetadata( + resourceAddress = resourceEntity.address, + stateVersion = stateVersion, + initialCursor = nextMetadataCursor + ) + }.getOrNull()?.mapNotNull { it.toMetadata() }?.takeIf { it.isNotEmpty() }?.toSet() + + if (remainingMetadata != null) { + resourceEntity.copy( + metadata = resourceEntity.metadata.metadata.toMutableSet().apply { + this union remainingMetadata + }.let { + MetadataColumn(metadata = it.toList(), implicitState = MetadataColumn.ImplicitMetadataState.Complete) + }.also { + stateDao.updateMetadata(resourceAddress = resourceEntity.address, metadataColumn = it) + } + ) + } else { + resourceEntity + } + } else { + resourceEntity + }.toResource(amount) + } } } diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetDAppWithResourcesUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetDAppWithResourcesUseCase.kt index de6170a35f..e0cd36d334 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetDAppWithResourcesUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetDAppWithResourcesUseCase.kt @@ -26,7 +26,8 @@ class GetDAppWithResourcesUseCase @Inject constructor( val resources = stateRepository.getResources( addresses = claimedResources.toSet(), underAccountAddress = null, - withDetails = false + withDetails = false, + withAllMetadata = false ).getOrNull().orEmpty() DAppWithResources( diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetResourcesUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetResourcesUseCase.kt index 748614c112..21d4231adf 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetResourcesUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/GetResourcesUseCase.kt @@ -8,6 +8,13 @@ class GetResourcesUseCase @Inject constructor( private val stateRepository: StateRepository ) { - suspend operator fun invoke(addresses: Set, withDetails: Boolean = false) = - stateRepository.getResources(addresses = addresses, underAccountAddress = null, withDetails = withDetails) + suspend operator fun invoke( + addresses: Set, + withDetails: Boolean = false + ) = stateRepository.getResources( + addresses = addresses, + underAccountAddress = null, + withDetails = withDetails, + withAllMetadata = false + ) } diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ResolveAssetsFromAddressUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ResolveAssetsFromAddressUseCase.kt index 75ecff1798..fe61486e2e 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ResolveAssetsFromAddressUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/assets/ResolveAssetsFromAddressUseCase.kt @@ -21,12 +21,14 @@ class ResolveAssetsFromAddressUseCase @Inject constructor( ) { suspend operator fun invoke( fungibleAddresses: Set, - nonFungibleIds: Map> + nonFungibleIds: Map>, + withAllMetadata: Boolean = false ): Result> = stateRepository .getResources( addresses = fungibleAddresses + nonFungibleIds.keys, underAccountAddress = null, - withDetails = true + withDetails = true, + withAllMetadata = withAllMetadata ).mapCatching { resources -> val nfts = nonFungibleIds.mapValues { entry -> stateRepository.getNFTDetails(entry.key, entry.value.toSet()).getOrThrow() diff --git a/app/src/main/java/com/babylon/wallet/android/domain/usecases/transaction/GetTransactionBadgesUseCase.kt b/app/src/main/java/com/babylon/wallet/android/domain/usecases/transaction/GetTransactionBadgesUseCase.kt index 020f794add..70de3905cb 100644 --- a/app/src/main/java/com/babylon/wallet/android/domain/usecases/transaction/GetTransactionBadgesUseCase.kt +++ b/app/src/main/java/com/babylon/wallet/android/domain/usecases/transaction/GetTransactionBadgesUseCase.kt @@ -14,7 +14,8 @@ class GetTransactionBadgesUseCase @Inject constructor( ): Result> = stateRepository.getResources( addresses = addresses, underAccountAddress = null, - withDetails = false + withDetails = false, + withAllMetadata = false ).mapCatching { resources -> resources.map { Badge( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialogViewModel.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialogViewModel.kt index a16bf9ffde..0cc0ab10c8 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialogViewModel.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialogViewModel.kt @@ -52,7 +52,8 @@ class AssetDialogViewModel @Inject constructor( is AssetDialogArgs.NFT -> mapOf( args.resourceAddress to args.localId?.let { setOf(it) }.orEmpty() ) - } + }, + withAllMetadata = true ).mapCatching { assets -> when (val asset = assets.first()) { // In case we receive a fungible asset, let's copy the custom amount From 9e5148142cb89ee848b1bf7ab46c8522070779e0 Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Tue, 25 Jun 2024 17:38:03 +0300 Subject: [PATCH 03/18] Show non standard metadata in asset details dialog sheet --- .../EntityMetadataCollectionExtensions.kt | 2 +- .../account/composable/AssetMetadataRow.kt | 17 ++++++++++--- .../presentation/status/assets/AssetDialog.kt | 25 +++++++++++++++++++ .../assets/fungible/FungibleDialogContent.kt | 8 ++++++ .../status/assets/lsu/LSUDialogContent.kt | 9 ++++++- .../NonFungibleAssetDialogContent.kt | 8 ++++++ .../assets/pool/PoolUnitDialogContent.kt | 8 ++++++ .../domain/resources/ExplicitMetadataKey.kt | 2 -- .../works/core/domain/resources/Resource.kt | 6 +++++ .../resources/metadata/StandardMetadata.kt | 5 ---- 10 files changed, 77 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt index c5fe1aa473..8dd5f12445 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt @@ -181,7 +181,7 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) is MetadataInstantValue -> Metadata.Primitive( key = key, - value = typed.value, + value = typed.unixTimestampSeconds, valueType = MetadataType.Instant ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/AssetMetadataRow.kt b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/AssetMetadataRow.kt index bb64f10e4e..9aa9fe3b36 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/AssetMetadataRow.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/AssetMetadataRow.kt @@ -76,7 +76,7 @@ fun Metadata.View(modifier: Modifier) { Row( modifier = modifier, horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.Top ) { KeyView() Spacer(modifier = Modifier.width(RadixTheme.dimensions.paddingMedium)) @@ -167,21 +167,30 @@ fun Metadata.ValueView( modifier = modifier, address = remember(value) { Address.init(value) - } + }, + textStyle = RadixTheme.typography.body1HighImportance, + textColor = RadixTheme.colors.gray1, + iconColor = RadixTheme.colors.gray1 ) MetadataType.NonFungibleGlobalId -> ActionableAddressView( modifier = modifier, globalId = remember(value) { NonFungibleGlobalId.init(value) - } + }.copy(), + textStyle = RadixTheme.typography.body1HighImportance, + textColor = RadixTheme.colors.gray1, + iconColor = RadixTheme.colors.gray1 ) MetadataType.NonFungibleLocalId -> ActionableAddressView( modifier = modifier, localId = remember(value) { NonFungibleLocalId.init(value) - } + }, + textStyle = RadixTheme.typography.body1HighImportance, + textColor = RadixTheme.colors.gray1, + iconColor = RadixTheme.colors.gray1 ) MetadataType.Decimal -> Text( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt index cd556a9e92..32d6a150ca 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt @@ -10,16 +10,19 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme +import com.babylon.wallet.android.presentation.account.composable.View import com.babylon.wallet.android.presentation.status.assets.fungible.FungibleDialogContent import com.babylon.wallet.android.presentation.status.assets.lsu.LSUDialogContent import com.babylon.wallet.android.presentation.status.assets.nonfungible.NonFungibleAssetDialogContent @@ -38,6 +41,7 @@ import rdx.works.core.domain.assets.AssetPrice import rdx.works.core.domain.assets.LiquidStakeUnit import rdx.works.core.domain.assets.PoolUnit import rdx.works.core.domain.assets.Token +import rdx.works.core.domain.resources.Resource import rdx.works.core.domain.resources.Tag @Composable @@ -139,6 +143,27 @@ fun Asset.displayTitle() = when (this) { } } +@Composable +fun NonStandardMetadataSection( + modifier: Modifier = Modifier, + resource: Resource +) { + val metadata = remember(resource.metadata) { + resource.nonStandardMetadata + } + + if (metadata.isNotEmpty()) { + Column( + modifier = modifier + ) { + metadata.forEach { metadata -> + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) + metadata.View(modifier = Modifier.fillMaxWidth()) + } + } + } +} + @Composable fun BehavioursSection( modifier: Modifier = Modifier, diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt index 732ac8c51b..14e601e21e 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt @@ -26,6 +26,7 @@ import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.account.composable.AssetMetadataRow import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection +import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.ShimmeringView import com.babylon.wallet.android.presentation.ui.composables.Thumbnail @@ -151,6 +152,13 @@ fun FungibleDialogContent( ) } + token?.resource?.let { resource -> + NonStandardMetadataSection( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), + resource = resource + ) + } + BehavioursSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), isXRD = token?.resource?.isXrd ?: false, diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt index bfc6f2acea..1af3a38552 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt @@ -29,6 +29,7 @@ import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.account.composable.AssetMetadataRow import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection +import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.ShimmeringView import com.babylon.wallet.android.presentation.ui.composables.Thumbnail @@ -219,7 +220,13 @@ fun LSUDialogContent( textAlign = TextAlign.End ) } - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) + + lsu?.resource?.let { resource -> + NonStandardMetadataSection( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), + resource = resource + ) + } BehavioursSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt index fb2ce098be..82b6234620 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt @@ -33,6 +33,7 @@ import com.babylon.wallet.android.presentation.account.composable.AssetMetadataR import com.babylon.wallet.android.presentation.account.composable.View import com.babylon.wallet.android.presentation.status.assets.AssetDialogViewModel import com.babylon.wallet.android.presentation.status.assets.BehavioursSection +import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.GrayBackgroundWrapper import com.babylon.wallet.android.presentation.ui.composables.Thumbnail @@ -266,6 +267,13 @@ fun NonFungibleAssetDialogContent( ) } + asset?.resource?.let { resource -> + NonStandardMetadataSection( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingXXLarge), + resource = resource + ) + } + BehavioursSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingXXLarge), behaviours = asset?.resource?.behaviours diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt index 90ff3ffbf0..941a450ed8 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt @@ -28,6 +28,7 @@ import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.account.composable.AssetMetadataRow import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection +import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.Thumbnail import com.babylon.wallet.android.presentation.ui.composables.assets.PoolResourcesValues @@ -194,6 +195,13 @@ fun PoolUnitDialogContent( ) } + poolUnit?.resource?.let { resource -> + NonStandardMetadataSection( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), + resource = resource + ) + } + BehavioursSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), behaviours = poolUnit?.resource?.behaviours diff --git a/core/src/main/java/rdx/works/core/domain/resources/ExplicitMetadataKey.kt b/core/src/main/java/rdx/works/core/domain/resources/ExplicitMetadataKey.kt index 207678d1e5..c197103521 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/ExplicitMetadataKey.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/ExplicitMetadataKey.kt @@ -19,7 +19,6 @@ enum class ExplicitMetadataKey(val key: String) { TAGS("tags"), KEY_IMAGE_URL("key_image_url"), ICON_URL("icon_url"), - INFO_URL("info_url"), VALIDATOR("validator"), CLAIM_AMOUNT("claim_amount"), CLAIM_EPOCH("claim_epoch"), @@ -36,7 +35,6 @@ enum class ExplicitMetadataKey(val key: String) { DESCRIPTION, RELATED_WEBSITES, ICON_URL, - INFO_URL, VALIDATOR, POOL, TAGS, diff --git a/core/src/main/java/rdx/works/core/domain/resources/Resource.kt b/core/src/main/java/rdx/works/core/domain/resources/Resource.kt index 504ffbd1b5..be5f35aae0 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/Resource.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/Resource.kt @@ -47,6 +47,12 @@ sealed class Resource { is NonFungibleResource -> currentSupply != null && behaviours != null } + val nonStandardMetadata: List by lazy { + metadata.filterNot { item -> + item.key in ExplicitMetadataKey.entries.map { it.key }.toSet() + } + } + data class FungibleResource( override val address: ResourceAddress, val ownedAmount: Decimal192?, diff --git a/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt b/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt index be8d72dc71..2e78d1a657 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt @@ -40,11 +40,6 @@ fun List.name(): String? = findPrimitive( type = MetadataType.String )?.value -fun List.infoUrl(): Uri? = findPrimitive( - key = ExplicitMetadataKey.INFO_URL, - type = MetadataType.Url -)?.value?.toUri() - fun List.iconUrl(): Uri? = findPrimitive( key = ExplicitMetadataKey.ICON_URL, type = MetadataType.Url From d50a0e901dba4a226583505f842a0e0e9ada3481 Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Tue, 25 Jun 2024 17:46:48 +0300 Subject: [PATCH 04/18] Improve how global id is constructed from string metadata --- .../extensions/EntityMetadataCollectionExtensions.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt index 8dd5f12445..9fe59a185b 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt @@ -38,6 +38,11 @@ import com.babylon.wallet.android.data.gateway.generated.models.PublicKeyEcdsaSe import com.babylon.wallet.android.data.gateway.generated.models.PublicKeyEddsaEd25519 import com.babylon.wallet.android.data.gateway.generated.models.PublicKeyHashEcdsaSecp256k1 import com.babylon.wallet.android.data.gateway.generated.models.PublicKeyHashEddsaEd25519 +import com.radixdlt.sargon.NonFungibleGlobalId +import com.radixdlt.sargon.NonFungibleLocalId +import com.radixdlt.sargon.ResourceAddress +import com.radixdlt.sargon.extensions.init +import com.radixdlt.sargon.extensions.string import rdx.works.core.domain.resources.metadata.Metadata import rdx.works.core.domain.resources.metadata.MetadataType import rdx.works.core.domain.resources.metadata.MetadataType.Integer.Size @@ -198,7 +203,10 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) is MetadataNonFungibleGlobalIdValue -> Metadata.Primitive( key = key, - value = "${typed.resourceAddress}:${typed.nonFungibleId}", + value = NonFungibleGlobalId( + resourceAddress = ResourceAddress.init(typed.resourceAddress), + nonFungibleLocalId = NonFungibleLocalId.init(typed.nonFungibleId) + ).string, valueType = MetadataType.NonFungibleGlobalId ) From 514a25775ab4a7020092912d11b57afe5086bf54 Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Wed, 26 Jun 2024 12:20:15 +0300 Subject: [PATCH 05/18] Replace AssetMetadataRow with modular MetadataView --- .../EntityMetadataCollectionExtensions.kt | 143 ++++++++----- .../cache/database/ResourceEntity.kt | 33 +-- .../cache/database/StateDatabase.kt | 2 +- .../{AssetMetadataRow.kt => MetadataView.kt} | 192 +++++++++++------- .../presentation/status/assets/AssetDialog.kt | 5 +- .../assets/fungible/FungibleDialogContent.kt | 4 +- .../status/assets/lsu/LSUDialogContent.kt | 6 +- .../NonFungibleAssetDialogContent.kt | 14 +- .../assets/pool/PoolUnitDialogContent.kt | 4 +- .../domain/resources/metadata/Metadata.kt | 6 +- .../src/main/res/drawable/ic_lock.xml | 15 +- 11 files changed, 249 insertions(+), 175 deletions(-) rename app/src/main/java/com/babylon/wallet/android/presentation/account/composable/{AssetMetadataRow.kt => MetadataView.kt} (59%) diff --git a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt index 9fe59a185b..a6dea364bd 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt @@ -56,7 +56,8 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) is MetadataBoolValue -> Metadata.Primitive( key = key, value = typed.value.toString(), - valueType = MetadataType.Bool + valueType = MetadataType.Bool, + isLocked = isLocked ) is MetadataBoolArrayValue -> Metadata.Collection( @@ -65,15 +66,18 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it.toString(), - valueType = MetadataType.Bool + valueType = MetadataType.Bool, + isLocked = isLocked ) - } + }, + isLocked = isLocked ) is MetadataDecimalValue -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Decimal + valueType = MetadataType.Decimal, + isLocked = isLocked ) is MetadataDecimalArrayValue -> Metadata.Collection( @@ -84,13 +88,15 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) value = it, valueType = MetadataType.Decimal ) - } + }, + isLocked = isLocked ) is MetadataGlobalAddressValue -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Address + valueType = MetadataType.Address, + isLocked = isLocked ) is MetadataGlobalAddressArrayValue -> Metadata.Collection( @@ -99,15 +105,18 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Address + valueType = MetadataType.Address, + isLocked = isLocked ) }, + isLocked = isLocked ) is MetadataI32Value -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Integer(signed = true, size = Size.INT) + valueType = MetadataType.Integer(signed = true, size = Size.INT), + isLocked = isLocked ) is MetadataI32ArrayValue -> Metadata.Collection( @@ -116,15 +125,18 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Integer(signed = true, size = Size.INT) + valueType = MetadataType.Integer(signed = true, size = Size.INT), + isLocked = isLocked ) - } + }, + isLocked = isLocked ) is MetadataI64Value -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Integer(signed = true, size = Size.LONG) + valueType = MetadataType.Integer(signed = true, size = Size.LONG), + isLocked = isLocked ) is MetadataI64ArrayValue -> Metadata.Collection( @@ -133,27 +145,32 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Integer(signed = true, size = Size.LONG) + valueType = MetadataType.Integer(signed = true, size = Size.LONG), + isLocked = isLocked ) - } + }, + isLocked = isLocked ) is MetadataU8Value -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Integer(signed = false, size = Size.INT) + valueType = MetadataType.Integer(signed = false, size = Size.INT), + isLocked = isLocked ) is MetadataU8ArrayValue -> Metadata.Primitive( key = key, value = typed.valueHex, - valueType = MetadataType.Bytes + valueType = MetadataType.Bytes, + isLocked = isLocked ) is MetadataU32Value -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Integer(signed = false, size = Size.INT) + valueType = MetadataType.Integer(signed = false, size = Size.INT), + isLocked = isLocked ) is MetadataU32ArrayValue -> Metadata.Collection( @@ -162,15 +179,18 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Integer(signed = false, size = Size.INT) + valueType = MetadataType.Integer(signed = false, size = Size.INT), + isLocked = isLocked ) - } + }, + isLocked = isLocked ) is MetadataU64Value -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Integer(signed = false, size = Size.LONG) + valueType = MetadataType.Integer(signed = false, size = Size.LONG), + isLocked = isLocked ) is MetadataU64ArrayValue -> Metadata.Collection( @@ -179,15 +199,18 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Integer(signed = false, size = Size.LONG) + valueType = MetadataType.Integer(signed = false, size = Size.LONG), + isLocked = isLocked ) }, + isLocked = isLocked ) is MetadataInstantValue -> Metadata.Primitive( key = key, value = typed.unixTimestampSeconds, - valueType = MetadataType.Instant + valueType = MetadataType.Instant, + isLocked = isLocked ) is MetadataInstantArrayValue -> Metadata.Collection( @@ -196,9 +219,11 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Instant + valueType = MetadataType.Instant, + isLocked = isLocked ) - } + }, + isLocked = isLocked ) is MetadataNonFungibleGlobalIdValue -> Metadata.Primitive( @@ -207,7 +232,8 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) resourceAddress = ResourceAddress.init(typed.resourceAddress), nonFungibleLocalId = NonFungibleLocalId.init(typed.nonFungibleId) ).string, - valueType = MetadataType.NonFungibleGlobalId + valueType = MetadataType.NonFungibleGlobalId, + isLocked = isLocked ) is MetadataNonFungibleGlobalIdArrayValue -> Metadata.Collection( @@ -216,16 +242,19 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = "${it.resourceAddress}:${it.nonFungibleId}", - valueType = MetadataType.NonFungibleGlobalId + valueType = MetadataType.NonFungibleGlobalId, + isLocked = isLocked ) - } + }, + isLocked = isLocked ) is MetadataNonFungibleLocalIdValue -> Metadata.Primitive( key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = typed.value, - valueType = MetadataType.NonFungibleLocalId + valueType = MetadataType.NonFungibleLocalId, + isLocked = isLocked ) is MetadataNonFungibleLocalIdArrayValue -> Metadata.Collection( @@ -234,15 +263,18 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.NonFungibleLocalId + valueType = MetadataType.NonFungibleLocalId, + isLocked = isLocked ) - } + }, + isLocked = isLocked ) is MetadataOriginValue -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Url + valueType = MetadataType.Url, + isLocked = isLocked ) is MetadataOriginArrayValue -> Metadata.Collection( @@ -251,15 +283,18 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Url + valueType = MetadataType.Url, + isLocked = isLocked ) - } + }, + isLocked = isLocked ) is MetadataStringValue -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.String + valueType = MetadataType.String, + isLocked = isLocked ) is MetadataStringArrayValue -> Metadata.Collection( @@ -268,9 +303,11 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.String + valueType = MetadataType.String, + isLocked = isLocked ) - } + }, + isLocked = isLocked ) is MetadataUrlValue -> Metadata.Primitive( @@ -285,9 +322,11 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) Metadata.Primitive( key = key, value = it, - valueType = MetadataType.Url + valueType = MetadataType.Url, + isLocked = isLocked ) - } + }, + isLocked = isLocked ) is MetadataPublicKeyValue -> when (typed.value) { @@ -295,14 +334,16 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = typed.value.keyHex, - valueType = MetadataType.PublicKeyEcdsaSecp256k1 + valueType = MetadataType.PublicKeyEcdsaSecp256k1, + isLocked = isLocked ) is PublicKeyEddsaEd25519 -> Metadata.Primitive( key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = typed.value.keyHex, - valueType = MetadataType.PublicKeyEddsaEd25519 + valueType = MetadataType.PublicKeyEddsaEd25519, + isLocked = isLocked ) else -> error("Not supported MetadataPublicKeyValue type for $value") @@ -316,18 +357,21 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) is PublicKeyEcdsaSecp256k1 -> Metadata.Primitive( key = key, value = value.keyHex, - valueType = MetadataType.PublicKeyEcdsaSecp256k1 + valueType = MetadataType.PublicKeyEcdsaSecp256k1, + isLocked = isLocked ) is PublicKeyEddsaEd25519 -> Metadata.Primitive( key = key, value = value.keyHex, - valueType = MetadataType.PublicKeyEddsaEd25519 + valueType = MetadataType.PublicKeyEddsaEd25519, + isLocked = isLocked ) else -> error("Not supported MetadataPublicKeyValue type for $value") } - } + }, + isLocked = isLocked ) is MetadataPublicKeyHashValue -> when (typed.value) { @@ -335,14 +379,16 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = typed.value.hashHex, - valueType = MetadataType.PublicKeyHashEcdsaSecp256k1 + valueType = MetadataType.PublicKeyHashEcdsaSecp256k1, + isLocked = isLocked ) is PublicKeyHashEddsaEd25519 -> Metadata.Primitive( key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = typed.value.hashHex, - valueType = MetadataType.PublicKeyHashEddsaEd25519 + valueType = MetadataType.PublicKeyHashEddsaEd25519, + isLocked = isLocked ) } @@ -355,17 +401,20 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = value.hashHex, - valueType = MetadataType.PublicKeyHashEcdsaSecp256k1 + valueType = MetadataType.PublicKeyHashEcdsaSecp256k1, + isLocked = isLocked ) is PublicKeyHashEddsaEd25519 -> Metadata.Primitive( key = key, lastUpdatedAtStateVersion = lastUpdatedAtStateVersion, value = value.hashHex, - valueType = MetadataType.PublicKeyHashEddsaEd25519 + valueType = MetadataType.PublicKeyHashEddsaEd25519, + isLocked = isLocked ) } - } + }, + isLocked = isLocked ) else -> null diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt index eb1f9ef78d..02d52ab3e3 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt @@ -22,10 +22,7 @@ import com.radixdlt.sargon.extensions.init import com.radixdlt.sargon.extensions.string import com.radixdlt.sargon.extensions.toDecimal192 import rdx.works.core.domain.resources.Divisibility -import rdx.works.core.domain.resources.ExplicitMetadataKey import rdx.works.core.domain.resources.Resource -import rdx.works.core.domain.resources.metadata.Metadata -import rdx.works.core.domain.resources.metadata.MetadataType import rdx.works.core.domain.resources.metadata.poolAddress import rdx.works.core.domain.resources.metadata.validatorAddress import java.time.Instant @@ -58,15 +55,6 @@ data class ResourceEntity( @Suppress("CyclomaticComplexMethod") fun toResource(amount: Decimal192?): Resource { - val validatorAndPoolMetadata = listOf( - validatorAddress?.let { - Metadata.Primitive(ExplicitMetadataKey.VALIDATOR.key, it.string, MetadataType.Address) - }, - poolAddress?.let { - Metadata.Primitive(ExplicitMetadataKey.POOL.key, it.string, MetadataType.Address) - } - ).mapNotNull { it } - return when (type) { ResourceEntityType.FUNGIBLE -> { Resource.FungibleResource( @@ -75,7 +63,7 @@ data class ResourceEntity( assetBehaviours = behaviours?.behaviours?.toSet(), currentSupply = supply, divisibility = divisibility, - metadata = metadata?.metadata.orEmpty() + validatorAndPoolMetadata + metadata = metadata?.metadata.orEmpty() ) } @@ -86,7 +74,7 @@ data class ResourceEntity( assetBehaviours = behaviours?.behaviours?.toSet(), items = emptyList(), currentSupply = supply?.string?.toIntOrNull(), - metadata = metadata?.metadata.orEmpty() + validatorAndPoolMetadata + metadata = metadata?.metadata.orEmpty() ) } } @@ -103,7 +91,6 @@ data class ResourceEntity( validatorAddress = metadata.validatorAddress(), poolAddress = metadata.poolAddress(), metadata = metadata - .filterNot { it.key in setOf(ExplicitMetadataKey.POOL.key, ExplicitMetadataKey.VALIDATOR.key) } .takeIf { it.isNotEmpty() } ?.let { MetadataColumn(it, MetadataColumn.ImplicitMetadataState.Unknown) }, synced = synced @@ -118,7 +105,6 @@ data class ResourceEntity( validatorAddress = metadata.validatorAddress(), poolAddress = metadata.poolAddress(), metadata = metadata - .filterNot { it.key in setOf(ExplicitMetadataKey.POOL.key, ExplicitMetadataKey.VALIDATOR.key) } .takeIf { it.isNotEmpty() } ?.let { MetadataColumn(it, MetadataColumn.ImplicitMetadataState.Unknown) }, synced = synced @@ -190,7 +176,7 @@ data class ResourceEntity( metadata = explicitMetadata?.toMetadata().orEmpty(), implicitState = MetadataColumn.ImplicitMetadataState.Unknown ) - } + }.takeIf { it.metadata.isNotEmpty() } return ResourceEntity( address = address, @@ -198,16 +184,9 @@ data class ResourceEntity( divisibility = details?.divisibility(), behaviours = details?.let { BehavioursColumn(it.extractBehaviours()) }, supply = details?.totalSupply(), - validatorAddress = metadataColumn.metadata.validatorAddress(), - poolAddress = metadataColumn.metadata.poolAddress(), - metadata = metadataColumn.copy( - metadata = metadataColumn.metadata.filterNot { - it.key in setOf( - ExplicitMetadataKey.VALIDATOR.key, - ExplicitMetadataKey.POOL.key - ) - } - ).takeIf { it.metadata.isNotEmpty() }, + validatorAddress = metadataColumn?.metadata?.validatorAddress(), + poolAddress = metadataColumn?.metadata?.poolAddress(), + metadata = metadataColumn, synced = synced ) } diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt index 35d0e18c5c..98acbfa299 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDatabase.kt @@ -54,7 +54,7 @@ abstract class StateDatabase : RoomDatabase() { @Deprecated("Replace BigDecimal with Decimal192") const val VERSION_8 = 8 - // Added next cursor to metadata column + // Added next cursor to metadata column and locked flag const val VERSION_9 = 9 private const val NAME = "STATE_DATABASE" diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/AssetMetadataRow.kt b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt similarity index 59% rename from app/src/main/java/com/babylon/wallet/android/presentation/account/composable/AssetMetadataRow.kt rename to app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt index 9aa9fe3b36..fc3a62e991 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/AssetMetadataRow.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt @@ -4,21 +4,27 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width +import androidx.compose.foundation.text.InlineTextContent +import androidx.compose.foundation.text.appendInlineContent import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.Placeholder +import androidx.compose.ui.text.PlaceholderVerticalAlign +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.sp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.ui.composables.ExpandableText @@ -36,41 +42,22 @@ import java.time.Instant import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.format.FormatStyle -import java.util.Locale @Composable -fun AssetMetadataRow( - modifier: Modifier, +fun MetadataView( + modifier: Modifier = Modifier, key: String, - valueView: @Composable RowScope.() -> Unit + isLocked: Boolean = false, + isRenderedInNewLine: Boolean = false, + valueView: @Composable () -> Unit ) { - Row( - modifier = modifier, - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - modifier = Modifier.padding(end = RadixTheme.dimensions.paddingMedium), - text = key.replaceFirstChar { - if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() - }, - style = RadixTheme.typography.body1Regular, - color = RadixTheme.colors.gray2 - ) - - valueView() - } -} - -@Composable -fun Metadata.View(modifier: Modifier) { if (isRenderedInNewLine) { Column( modifier = modifier, verticalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingSmall) ) { - KeyView() - ValueView(isRenderedInNewLine = true) + MetadataKeyView(key = key, isLocked = isLocked) + valueView() } } else { Row( @@ -78,44 +65,101 @@ fun Metadata.View(modifier: Modifier) { horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.Top ) { - KeyView() + MetadataKeyView(key = key, isLocked = isLocked) Spacer(modifier = Modifier.width(RadixTheme.dimensions.paddingMedium)) - ValueView(isRenderedInNewLine = false) + valueView() } } } @Composable -fun Metadata.KeyView( - modifier: Modifier = Modifier +fun MetadataView( + modifier: Modifier = Modifier, + metadata: Metadata +) { + MetadataView( + modifier = modifier, + key = metadata.key, + isLocked = metadata.isLocked, + isRenderedInNewLine = metadata.isRenderedInNewLine, + ) { + MetadataValueView( + metadata = metadata, + isRenderedInNewLine = metadata.isRenderedInNewLine + ) + } +} + +@Composable +fun MetadataKeyView( + modifier: Modifier = Modifier, + metadata: Metadata, + style: TextStyle = RadixTheme.typography.body1Regular, + color: Color = RadixTheme.colors.gray2, +) { + MetadataKeyView( + modifier = modifier, + key = metadata.key, + isLocked = metadata.isLocked, + style = style, + color = color + ) +} + +@Composable +fun MetadataKeyView( + modifier: Modifier = Modifier, + key: String, + isLocked: Boolean, + style: TextStyle = RadixTheme.typography.body1Regular, + color: Color = RadixTheme.colors.gray2, ) { Text( - modifier = modifier.padding(end = RadixTheme.dimensions.paddingMedium), - text = key, - style = RadixTheme.typography.body1Regular, - color = RadixTheme.colors.gray2, - textAlign = TextAlign.Start + modifier = modifier, + text = buildAnnotatedString { + append(key) + append(" ") + if (isLocked) { + appendInlineContent(id = "lock_icon") + } + }, + style = style, + color = color, + textAlign = TextAlign.Start, + inlineContent = mapOf( + "lock_icon" to InlineTextContent( + Placeholder(16.sp, 16.sp, PlaceholderVerticalAlign.TextCenter) + ) { + Icon( + painter = painterResource(id = com.babylon.wallet.android.designsystem.R.drawable.ic_lock), + contentDescription = null + ) + } + ) ) } @Suppress("CyclomaticComplexMethod") @Composable -fun Metadata.ValueView( +fun MetadataValueView( modifier: Modifier = Modifier, - isRenderedInNewLine: Boolean + metadata: Metadata, + isRenderedInNewLine: Boolean, + style: TextStyle = RadixTheme.typography.body1HighImportance, + color: Color = RadixTheme.colors.gray1 ) { val context = LocalContext.current - when (this) { + when (metadata) { is Metadata.Collection, is Metadata.Map -> Text( modifier = modifier, text = stringResource(id = R.string.assetDetails_NFTDetails_complexData), - style = RadixTheme.typography.body1HighImportance, - color = RadixTheme.colors.gray1, + style = style, + color = color, textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, maxLines = 2 ) - is Metadata.Primitive -> when (valueType) { + is Metadata.Primitive -> when (metadata.valueType) { MetadataType.Bool, is MetadataType.Integer, MetadataType.Bytes, @@ -125,28 +169,28 @@ fun Metadata.ValueView( MetadataType.PublicKeyHashEcdsaSecp256k1, MetadataType.PublicKeyHashEddsaEd25519 -> Text( modifier = modifier, - text = value, - style = RadixTheme.typography.body1HighImportance, - color = RadixTheme.colors.gray1, + text = metadata.value, + style = style, + color = color, textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, maxLines = 2 ) MetadataType.String -> ExpandableText( modifier = modifier, - text = value, - style = RadixTheme.typography.body1HighImportance.copy( - color = RadixTheme.colors.gray1, + text = metadata.value, + style = style.copy( + color = color, textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, ), - toggleStyle = RadixTheme.typography.body1HighImportance.copy( + toggleStyle = style.copy( color = RadixTheme.colors.gray2 ), ) MetadataType.Instant -> { - val displayable = remember(value) { - val epochSeconds = value.toLongOrNull() ?: return@remember value + val displayable = remember(metadata.value) { + val epochSeconds = metadata.value.toLongOrNull() ?: return@remember metadata.value val dateTime = Instant.ofEpochSecond(epochSeconds) .atZone(ZoneId.systemDefault()) .toLocalDateTime() @@ -156,8 +200,8 @@ fun Metadata.ValueView( Text( modifier = modifier, text = displayable, - style = RadixTheme.typography.body1HighImportance, - color = RadixTheme.colors.gray1, + style = style, + color = color, textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, maxLines = 2 ) @@ -165,40 +209,40 @@ fun Metadata.ValueView( MetadataType.Address -> ActionableAddressView( modifier = modifier, - address = remember(value) { - Address.init(value) + address = remember(metadata.value) { + Address.init(metadata.value) }, - textStyle = RadixTheme.typography.body1HighImportance, - textColor = RadixTheme.colors.gray1, - iconColor = RadixTheme.colors.gray1 + textStyle = style, + textColor = color, + iconColor = color ) MetadataType.NonFungibleGlobalId -> ActionableAddressView( modifier = modifier, - globalId = remember(value) { - NonFungibleGlobalId.init(value) + globalId = remember(metadata.value) { + NonFungibleGlobalId.init(metadata.value) }.copy(), - textStyle = RadixTheme.typography.body1HighImportance, - textColor = RadixTheme.colors.gray1, - iconColor = RadixTheme.colors.gray1 + textStyle = style, + textColor = color, + iconColor = color ) MetadataType.NonFungibleLocalId -> ActionableAddressView( modifier = modifier, - localId = remember(value) { - NonFungibleLocalId.init(value) + localId = remember(metadata.value) { + NonFungibleLocalId.init(metadata.value) }, - textStyle = RadixTheme.typography.body1HighImportance, - textColor = RadixTheme.colors.gray1, - iconColor = RadixTheme.colors.gray1 + textStyle = style, + textColor = color, + iconColor = color ) MetadataType.Decimal -> Text( modifier = modifier, // If value is unable to transform to big decimal we just display raw value - text = value.toDecimal192OrNull()?.formatted() ?: value, - style = RadixTheme.typography.body1HighImportance, - color = RadixTheme.colors.gray1, + text = metadata.value.toDecimal192OrNull()?.formatted() ?: metadata.value, + style = style, + color = color, textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, maxLines = 2 ) @@ -206,12 +250,12 @@ fun Metadata.ValueView( MetadataType.Url -> Row( modifier = modifier .fillMaxWidth() - .clickable { context.openUrl(value) }, + .clickable { context.openUrl(metadata.value) }, horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingDefault), verticalAlignment = Alignment.CenterVertically ) { Text( - text = value, + text = metadata.value, style = RadixTheme.typography.body1StandaloneLink, color = RadixTheme.colors.blue1 ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt index 32d6a150ca..881b40b41c 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -22,7 +21,7 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.account.composable.View +import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.fungible.FungibleDialogContent import com.babylon.wallet.android.presentation.status.assets.lsu.LSUDialogContent import com.babylon.wallet.android.presentation.status.assets.nonfungible.NonFungibleAssetDialogContent @@ -158,7 +157,7 @@ fun NonStandardMetadataSection( ) { metadata.forEach { metadata -> Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - metadata.View(modifier = Modifier.fillMaxWidth()) + MetadataView(modifier = Modifier.fillMaxWidth(), metadata = metadata) } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt index 14e601e21e..e9ae7bd64e 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt @@ -23,7 +23,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.account.composable.AssetMetadataRow +import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection @@ -130,7 +130,7 @@ fun FungibleDialogContent( Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) if (!isNewlyCreated) { - AssetMetadataRow( + MetadataView( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingSmall), diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt index 1af3a38552..9058f4fab3 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt @@ -26,7 +26,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.account.composable.AssetMetadataRow +import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection @@ -179,7 +179,7 @@ fun LSUDialogContent( } Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - AssetMetadataRow( + MetadataView( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingSmall), @@ -197,7 +197,7 @@ fun LSUDialogContent( ) } Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - AssetMetadataRow( + MetadataView( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingSmall), diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt index 82b6234620..b444b58adf 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt @@ -29,8 +29,7 @@ import androidx.compose.ui.unit.dp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.composable.RadixTextButton import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.account.composable.AssetMetadataRow -import com.babylon.wallet.android.presentation.account.composable.View +import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.AssetDialogViewModel import com.babylon.wallet.android.presentation.status.assets.BehavioursSection import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection @@ -115,7 +114,7 @@ fun NonFungibleAssetDialogContent( } if (item != null) { - AssetMetadataRow( + MetadataView( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXLarge), @@ -155,10 +154,11 @@ fun NonFungibleAssetDialogContent( item?.nonStandardMetadata?.forEach { metadata -> Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - metadata.View( + MetadataView( modifier = Modifier .fillMaxWidth() - .padding(horizontal = RadixTheme.dimensions.paddingXXLarge) + .padding(horizontal = RadixTheme.dimensions.paddingXXLarge), + metadata = metadata ) } @@ -226,7 +226,7 @@ fun NonFungibleAssetDialogContent( ) if (!asset?.resource?.name.isNullOrBlank() && localId != null) { Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - AssetMetadataRow( + MetadataView( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXLarge), @@ -242,7 +242,7 @@ fun NonFungibleAssetDialogContent( Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) if (!isNewlyCreated) { - AssetMetadataRow( + MetadataView( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXLarge), diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt index 941a450ed8..d2759d21e8 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt @@ -25,7 +25,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme -import com.babylon.wallet.android.presentation.account.composable.AssetMetadataRow +import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection @@ -173,7 +173,7 @@ fun PoolUnitDialogContent( ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - AssetMetadataRow( + MetadataView( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingSmall), diff --git a/core/src/main/java/rdx/works/core/domain/resources/metadata/Metadata.kt b/core/src/main/java/rdx/works/core/domain/resources/metadata/Metadata.kt index b7f44b0131..c700c9b7a9 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/metadata/Metadata.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/metadata/Metadata.kt @@ -7,6 +7,7 @@ import kotlinx.serialization.Serializable sealed interface Metadata { val key: String val lastUpdatedAtStateVersion: Long + val isLocked: Boolean @Serializable @SerialName("primitive") @@ -16,6 +17,7 @@ sealed interface Metadata { @SerialName("value_type") val valueType: MetadataType, override val lastUpdatedAtStateVersion: Long = 0, + override val isLocked: Boolean = false ) : Metadata @Serializable @@ -24,6 +26,7 @@ sealed interface Metadata { override val key: String, val values: List, override val lastUpdatedAtStateVersion: Long = 0, + override val isLocked: Boolean = false ) : Metadata @Serializable @@ -31,7 +34,8 @@ sealed interface Metadata { data class Map( override val key: String, val values: kotlin.collections.Map, - override val lastUpdatedAtStateVersion: Long = 0L + override val lastUpdatedAtStateVersion: Long = 0L, + override val isLocked: Boolean = false ) : Metadata } diff --git a/designsystem/src/main/res/drawable/ic_lock.xml b/designsystem/src/main/res/drawable/ic_lock.xml index 9d29f7c790..73f80fc366 100644 --- a/designsystem/src/main/res/drawable/ic_lock.xml +++ b/designsystem/src/main/res/drawable/ic_lock.xml @@ -1,14 +1,13 @@ + android:width="24dp" + android:height="25dp" + android:viewportWidth="24" + android:viewportHeight="25"> + android:pathData="M0,0.72h24v24h-24z"/> + android:pathData="M18,8.72H17V6.72C17,3.96 14.76,1.72 12,1.72C9.24,1.72 7,3.96 7,6.72V8.72H6C4.9,8.72 4,9.62 4,10.72V20.72C4,21.82 4.9,22.72 6,22.72H18C19.1,22.72 20,21.82 20,20.72V10.72C20,9.62 19.1,8.72 18,8.72ZM9,6.72C9,5.06 10.34,3.72 12,3.72C13.66,3.72 15,5.06 15,6.72V8.72H9V6.72ZM18,20.72H6V10.72H18V20.72ZM12,17.72C13.1,17.72 14,16.82 14,15.72C14,14.62 13.1,13.72 12,13.72C10.9,13.72 10,14.62 10,15.72C10,16.82 10.9,17.72 12,17.72Z" + android:fillColor="#003057"/> - From 3cc5e0e2a75bcc9e29d1cab507c323c9e7c7703f Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Wed, 26 Jun 2024 13:29:30 +0300 Subject: [PATCH 06/18] Add lock information in tags section --- .../EntityMetadataCollectionExtensions.kt | 3 +- .../account/composable/MetadataView.kt | 5 ++- .../presentation/status/assets/AssetDialog.kt | 11 +++--- .../assets/fungible/FungibleDialogContent.kt | 1 + .../status/assets/lsu/LSUDialogContent.kt | 6 ++- .../NonFungibleAssetDialogContent.kt | 6 ++- .../assets/pool/PoolUnitDialogContent.kt | 1 + .../works/core/domain/resources/Resource.kt | 38 +++++++++++++++++++ .../resources/metadata/StandardMetadata.kt | 2 + 9 files changed, 61 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt index a6dea364bd..a84e4c8a4b 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt @@ -313,7 +313,8 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) is MetadataUrlValue -> Metadata.Primitive( key = key, value = typed.value, - valueType = MetadataType.Url + valueType = MetadataType.Url, + isLocked = isLocked ) is MetadataUrlArrayValue -> Metadata.Collection( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt index fc3a62e991..271b402d92 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt @@ -128,11 +128,12 @@ fun MetadataKeyView( textAlign = TextAlign.Start, inlineContent = mapOf( "lock_icon" to InlineTextContent( - Placeholder(16.sp, 16.sp, PlaceholderVerticalAlign.TextCenter) + Placeholder(style.fontSize, style.fontSize, PlaceholderVerticalAlign.TextCenter) ) { Icon( painter = painterResource(id = com.babylon.wallet.android.designsystem.R.drawable.ic_lock), - contentDescription = null + contentDescription = null, + tint = color ) } ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt index 881b40b41c..891b7d239b 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt @@ -21,6 +21,7 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme +import com.babylon.wallet.android.presentation.account.composable.MetadataKeyView import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.fungible.FungibleDialogContent import com.babylon.wallet.android.presentation.status.assets.lsu.LSUDialogContent @@ -213,16 +214,16 @@ fun BehavioursSection( @Composable fun TagsSection( modifier: Modifier = Modifier, - tags: ImmutableList? + tags: ImmutableList?, + isLocked: Boolean ) { if (!tags.isNullOrEmpty()) { Column(modifier = modifier) { Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - Text( + MetadataKeyView( modifier = Modifier.fillMaxWidth(), - text = stringResource(id = R.string.assetDetails_tags), - style = RadixTheme.typography.body1Regular, - color = RadixTheme.colors.gray2 + key = stringResource(id = R.string.assetDetails_tags), + isLocked = isLocked ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) FlowRow( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt index e9ae7bd64e..e675ac9b8c 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt @@ -168,6 +168,7 @@ fun FungibleDialogContent( TagsSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), tags = token?.resource?.tags, + isLocked = token?.resource?.isTagsLocked ?: false ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt index 9058f4fab3..1d58e8de97 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt @@ -183,7 +183,8 @@ fun LSUDialogContent( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingSmall), - key = stringResource(id = R.string.assetDetails_name) + key = stringResource(id = R.string.assetDetails_name), + isLocked = lsu?.resource?.isNameLocked ?: false ) { Text( modifier = Modifier @@ -235,7 +236,8 @@ fun LSUDialogContent( TagsSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - tags = lsu?.fungibleResource?.tags + tags = lsu?.fungibleResource?.tags, + isLocked = lsu?.resource?.isTagsLocked ?: false ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt index b444b58adf..db110f4c4a 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt @@ -230,7 +230,8 @@ fun NonFungibleAssetDialogContent( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXLarge), - key = stringResource(id = R.string.assetDetails_name) + key = stringResource(id = R.string.assetDetails_name), + isLocked = asset?.resource?.isNameLocked ?: false ) { Text( text = asset?.resource?.name.orEmpty(), @@ -281,7 +282,8 @@ fun NonFungibleAssetDialogContent( TagsSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingXXLarge), - tags = asset?.resource?.tags + tags = asset?.resource?.tags, + isLocked = asset?.resource?.isTagsLocked ?: false ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt index d2759d21e8..8b6bbd2395 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt @@ -210,6 +210,7 @@ fun PoolUnitDialogContent( TagsSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), tags = poolUnit?.resource?.tags, + isLocked = poolUnit?.resource?.isTagsLocked ?: false ) } } diff --git a/core/src/main/java/rdx/works/core/domain/resources/Resource.kt b/core/src/main/java/rdx/works/core/domain/resources/Resource.kt index be5f35aae0..84dab7ed1e 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/Resource.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/Resource.kt @@ -26,6 +26,7 @@ import rdx.works.core.domain.resources.metadata.claimAmount import rdx.works.core.domain.resources.metadata.claimEpoch import rdx.works.core.domain.resources.metadata.description import rdx.works.core.domain.resources.metadata.iconUrl +import rdx.works.core.domain.resources.metadata.isLocked import rdx.works.core.domain.resources.metadata.keyImageUrl import rdx.works.core.domain.resources.metadata.name import rdx.works.core.domain.resources.metadata.poolAddress @@ -61,22 +62,39 @@ sealed class Resource { val divisibility: Divisibility? = null, override val metadata: List = emptyList() ) : Resource(), Comparable { + override val name: String by lazy { metadata.name().orEmpty().truncate(maxNumberOfCharacters = NAME_MAX_CHARS) } + val isNameLocked: Boolean by lazy { + metadata.isLocked(key = ExplicitMetadataKey.NAME) + } + val symbol: String by lazy { metadata.symbol().orEmpty() } + val isSymbolLocked: Boolean by lazy { + metadata.isLocked(key = ExplicitMetadataKey.SYMBOL) + } + val description: String by lazy { metadata.description().orEmpty().truncate(maxNumberOfCharacters = DESCRIPTION_MAX_CHARS) } + val isDescriptionLocked: Boolean by lazy { + metadata.isLocked(key = ExplicitMetadataKey.DESCRIPTION) + } + override val iconUrl: Uri? by lazy { metadata.iconUrl() } + val isIconUrlLocked: Boolean by lazy { + metadata.isLocked(key = ExplicitMetadataKey.ICON_URL) + } + override val validatorAddress: ValidatorAddress? by lazy { metadata.validatorAddress() } @@ -101,6 +119,10 @@ sealed class Resource { }.take(TAGS_MAX).toImmutableList() } + val isTagsLocked: Boolean by lazy { + metadata.isLocked(key = ExplicitMetadataKey.TAGS) + } + val behaviours: AssetBehaviours? = if (assetBehaviours != null && isXrd) { assetBehaviours.filterNot { it == AssetBehaviour.INFORMATION_CHANGEABLE }.toSet() } else { @@ -167,20 +189,36 @@ sealed class Resource { metadata.name().orEmpty().truncate(maxNumberOfCharacters = NAME_MAX_CHARS) } + val isNameLocked: Boolean by lazy { + metadata.isLocked(key = ExplicitMetadataKey.NAME) + } + val description: String by lazy { metadata.description().orEmpty().truncate(maxNumberOfCharacters = DESCRIPTION_MAX_CHARS) } + val isDescriptionLocked: Boolean by lazy { + metadata.isLocked(key = ExplicitMetadataKey.DESCRIPTION) + } + override val iconUrl: Uri? by lazy { metadata.iconUrl() } + val isIconUrlLocked: Boolean by lazy { + metadata.isLocked(key = ExplicitMetadataKey.ICON_URL) + } + val tags: ImmutableList by lazy { metadata.tags().orEmpty().map { Tag.Dynamic(name = it.truncate(maxNumberOfCharacters = TAG_MAX_CHARS)) }.take(TAGS_MAX).toImmutableList() } + val isTagsLocked: Boolean by lazy { + metadata.isLocked(key = ExplicitMetadataKey.TAGS) + } + override val validatorAddress: ValidatorAddress? by lazy { metadata.validatorAddress() } diff --git a/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt b/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt index 2e78d1a657..c094131cfc 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt @@ -25,6 +25,8 @@ private fun List.findCollection(key: ExplicitMetadataKey, type: Metada ?.takeIf { values -> values.all { it.valueType == type } } } +fun List.isLocked(key: ExplicitMetadataKey) = find { it.key == key.key }?.isLocked ?: false + fun List.description(): String? = findPrimitive( key = ExplicitMetadataKey.DESCRIPTION, type = MetadataType.String From ab62f3e2f585810eec6d6ecef2e9332209867b54 Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Wed, 26 Jun 2024 13:41:55 +0300 Subject: [PATCH 07/18] Create a specific section for description --- .../presentation/status/assets/AssetDialog.kt | 22 +++++++++++++++++++ .../assets/fungible/FungibleDialogContent.kt | 12 ++++------ .../status/assets/lsu/LSUDialogContent.kt | 12 ++++------ .../NonFungibleAssetDialogContent.kt | 13 +++-------- .../assets/pool/PoolUnitDialogContent.kt | 14 ++++-------- 5 files changed, 37 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt index 891b7d239b..2e6b58a7fb 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -143,6 +144,27 @@ fun Asset.displayTitle() = when (this) { } } +@Composable +fun DescriptionSection( + modifier: Modifier = Modifier, + description: String +) { + Column( + modifier = modifier + ) { + Text( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), + text = description, + style = RadixTheme.typography.body1Regular, + color = RadixTheme.colors.gray1 + ) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) + HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) + } + +} + @Composable fun NonStandardMetadataSection( modifier: Modifier = Modifier, diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt index e675ac9b8c..373f9ff346 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt @@ -26,6 +26,7 @@ import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection +import com.babylon.wallet.android.presentation.status.assets.DescriptionSection import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.ShimmeringView @@ -110,15 +111,10 @@ fun FungibleDialogContent( Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) if (!token?.resource?.description.isNullOrBlank()) { - Text( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - text = token?.resource?.description.orEmpty(), - style = RadixTheme.typography.body2Regular, - color = RadixTheme.colors.gray1 + DescriptionSection( + modifier = Modifier.fillMaxWidth(), + description = token?.resource?.description.orEmpty() ) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) } AddressRow( modifier = Modifier diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt index 1d58e8de97..1f8e140518 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt @@ -29,6 +29,7 @@ import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection +import com.babylon.wallet.android.presentation.status.assets.DescriptionSection import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.ShimmeringView @@ -148,15 +149,10 @@ fun LSUDialogContent( Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) if (!lsu?.fungibleResource?.description.isNullOrBlank()) { - Text( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - text = lsu?.fungibleResource?.description.orEmpty(), - style = RadixTheme.typography.body2Regular, - color = RadixTheme.colors.gray1 + DescriptionSection( + modifier = Modifier.fillMaxWidth(), + description = lsu?.fungibleResource?.description.orEmpty() ) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) } AddressRow( diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt index db110f4c4a..c37bb8b74e 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt @@ -32,6 +32,7 @@ import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.AssetDialogViewModel import com.babylon.wallet.android.presentation.status.assets.BehavioursSection +import com.babylon.wallet.android.presentation.status.assets.DescriptionSection import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.GrayBackgroundWrapper @@ -202,20 +203,12 @@ fun NonFungibleAssetDialogContent( Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) if (!asset?.resource?.description.isNullOrBlank()) { - Text( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingXXLarge), - text = asset?.resource?.description.orEmpty(), - style = RadixTheme.typography.body2Regular, - color = RadixTheme.colors.gray1 - ) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - HorizontalDivider( + DescriptionSection( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingLarge), - color = RadixTheme.colors.gray4 + description = asset?.resource?.description.orEmpty() ) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) } AddressRow( modifier = Modifier diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt index 8b6bbd2395..476a7ab967 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt @@ -28,6 +28,7 @@ import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.AssetDialogArgs import com.babylon.wallet.android.presentation.status.assets.BehavioursSection +import com.babylon.wallet.android.presentation.status.assets.DescriptionSection import com.babylon.wallet.android.presentation.status.assets.NonStandardMetadataSection import com.babylon.wallet.android.presentation.status.assets.TagsSection import com.babylon.wallet.android.presentation.ui.composables.Thumbnail @@ -152,19 +153,12 @@ fun PoolUnitDialogContent( Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) if (!poolUnit?.stake?.description.isNullOrBlank()) { - Text( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingDefault), - text = poolUnit?.stake?.description.orEmpty(), - style = RadixTheme.typography.body2Regular, - color = RadixTheme.colors.gray1 - ) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - HorizontalDivider( + DescriptionSection( modifier = Modifier.fillMaxWidth(), - color = RadixTheme.colors.gray4 + description = poolUnit?.stake?.description.orEmpty() ) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) } + AddressRow( modifier = Modifier .fillMaxWidth() From d932cc2ff2cb533fb0dd202d3a94f3c406f928d4 Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Wed, 26 Jun 2024 13:57:03 +0300 Subject: [PATCH 08/18] Public keys and hashes are show single line with copy action and ellipsis at the end --- .../account/composable/MetadataView.kt | 28 +++++++++++++++---- .../debug/profile/InspectProfileScreen.kt | 14 ++++------ .../ActionableAddressView.kt | 20 ++++--------- .../wallet/android/utils/ContextExtensions.kt | 25 +++++++++++++++++ 4 files changed, 59 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt index 271b402d92..600c147c93 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt @@ -24,11 +24,14 @@ import androidx.compose.ui.text.PlaceholderVerticalAlign import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.sp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.ui.composables.ExpandableText import com.babylon.wallet.android.presentation.ui.composables.actionableaddress.ActionableAddressView +import com.babylon.wallet.android.presentation.ui.modifier.throttleClickable +import com.babylon.wallet.android.utils.copyToClipboard import com.babylon.wallet.android.utils.openUrl import com.radixdlt.sargon.Address import com.radixdlt.sargon.NonFungibleGlobalId @@ -164,17 +167,32 @@ fun MetadataValueView( MetadataType.Bool, is MetadataType.Integer, MetadataType.Bytes, - MetadataType.Enum, + MetadataType.Enum -> Text( + modifier = modifier, + text = metadata.value, + style = style, + color = color, + textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, + maxLines = 2 + ) + MetadataType.PublicKeyEcdsaSecp256k1, MetadataType.PublicKeyEddsaEd25519, MetadataType.PublicKeyHashEcdsaSecp256k1, MetadataType.PublicKeyHashEddsaEd25519 -> Text( - modifier = modifier, + modifier = modifier.throttleClickable { + context.copyToClipboard( + label = metadata.key, + value = metadata.value, + successMessage = context.getString(R.string.addressAction_copiedToClipboard) + ) + }, text = metadata.value, style = style, color = color, - textAlign = if (isRenderedInNewLine) TextAlign.Start else TextAlign.End, - maxLines = 2 + textAlign = TextAlign.End, + maxLines = 1, + overflow = TextOverflow.Ellipsis ) MetadataType.String -> ExpandableText( @@ -186,7 +204,7 @@ fun MetadataValueView( ), toggleStyle = style.copy( color = RadixTheme.colors.gray2 - ), + ) ) MetadataType.Instant -> { diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/settings/debug/profile/InspectProfileScreen.kt b/app/src/main/java/com/babylon/wallet/android/presentation/settings/debug/profile/InspectProfileScreen.kt index 48d348b791..330b6dee45 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/settings/debug/profile/InspectProfileScreen.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/settings/debug/profile/InspectProfileScreen.kt @@ -1,6 +1,5 @@ package com.babylon.wallet.android.presentation.settings.debug.profile -import android.content.ClipData import androidx.compose.foundation.background import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.WindowInsets @@ -31,11 +30,11 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.Typeface import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.sp -import androidx.core.content.getSystemService import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.common.FullscreenCircularProgressContent import com.babylon.wallet.android.presentation.ui.composables.RadixCenteredTopAppBar +import com.babylon.wallet.android.utils.copyToClipboard @Composable fun InspectProfileScreen( @@ -82,13 +81,10 @@ fun InspectProfileScreen( containerColor = RadixTheme.colors.gray4, contentColor = RadixTheme.colors.gray1, onClick = { - context.getSystemService()?.let { clipboardManager -> - val clipData = ClipData.newPlainText( - "Radix Address", - state.rawSnapshot - ) - clipboardManager.setPrimaryClip(clipData) - } + context.copyToClipboard( + label = "Radix Profile", + value = state.rawSnapshot.orEmpty() + ) } ) { Icon(painter = painterResource(id = R.drawable.ic_copy), contentDescription = null) 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 7ce9189383..9c251634eb 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 @@ -53,6 +53,7 @@ import com.babylon.wallet.android.domain.usecases.VerifyAddressOnLedgerUseCase import com.babylon.wallet.android.presentation.ui.RadixWalletPreviewTheme import com.babylon.wallet.android.presentation.ui.composables.AccountQRCodeView import com.babylon.wallet.android.presentation.ui.composables.BottomSheetWrapper +import com.babylon.wallet.android.utils.copyToClipboard import com.babylon.wallet.android.utils.encodeUtf8 import com.babylon.wallet.android.utils.openUrl import com.radixdlt.sargon.AccountAddress @@ -469,20 +470,11 @@ private sealed interface OnAction { ) : CallbackBasedAction { override fun onAction(context: Context) { - context.getSystemService()?.let { clipboardManager -> - - val clipData = ClipData.newPlainText( - "Radix Address", - actionableAddress.copyable - ) - - clipboardManager.setPrimaryClip(clipData) - - // From Android 13, the system handles the copy confirmation - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { - Toast.makeText(context, R.string.addressAction_copiedToClipboard, Toast.LENGTH_SHORT).show() - } - } + context.copyToClipboard( + label = "Radix Address", + value = actionableAddress.copyable.orEmpty(), + successMessage = context.getString(R.string.addressAction_copiedToClipboard) + ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt b/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt index 92676dbc0d..b5888f71a3 100644 --- a/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/utils/ContextExtensions.kt @@ -1,13 +1,16 @@ package com.babylon.wallet.android.utils import android.content.ActivityNotFoundException +import android.content.ClipData import android.content.ComponentName import android.content.Context import android.content.ContextWrapper import android.content.Intent import android.content.pm.PackageManager import android.net.Uri +import android.os.Build import android.widget.Toast +import androidx.core.content.getSystemService import androidx.core.net.toUri import androidx.fragment.app.FragmentActivity import androidx.navigation.NavController @@ -44,6 +47,28 @@ suspend fun Context.biometricAuthenticateSuspend(allowIfDeviceIsNotSecure: Boole fun Context.openUrl(url: HttpUrl, browser: Browser? = null) = openUrl(url.toString(), browser) fun Context.openUrl(url: String, browser: Browser? = null) = openUrl(url.toUri(), browser) +fun Context.copyToClipboard( + label: String, + value: String, + // Used only for Android versions < Android 13 + successMessage: String? = null +) { + getSystemService()?.let { clipboardManager -> + + val clipData = ClipData.newPlainText( + label, + value + ) + + clipboardManager.setPrimaryClip(clipData) + + // From Android 13, the system handles the copy confirmation + if (successMessage != null && Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { + Toast.makeText(this, successMessage, Toast.LENGTH_SHORT).show() + } + } +} + @Suppress("SwallowedException") fun Context.openUrl(uri: Uri, browser: Browser? = null) { val intent = Intent(Intent.ACTION_VIEW).apply { From 13d1a6fc05fe783dd24fd5bb3e9eb9742b7852e9 Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Wed, 26 Jun 2024 14:13:00 +0300 Subject: [PATCH 09/18] Inline url metadata icon --- .../account/composable/MetadataView.kt | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt index 600c147c93..8c14039ae2 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt @@ -25,7 +25,6 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.sp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.ui.composables.ExpandableText @@ -266,24 +265,31 @@ fun MetadataValueView( maxLines = 2 ) - MetadataType.Url -> Row( + MetadataType.Url -> Text( modifier = modifier .fillMaxWidth() .clickable { context.openUrl(metadata.value) }, - horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingDefault), - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = metadata.value, - style = RadixTheme.typography.body1StandaloneLink, - color = RadixTheme.colors.blue1 - ) - Icon( - painter = painterResource(id = R.drawable.ic_external_link), - contentDescription = null, - tint = RadixTheme.colors.gray3 - ) - } + text = buildAnnotatedString { + append(metadata.value) + append(" ") + appendInlineContent(id = "link_icon") + }, + style = RadixTheme.typography.body1StandaloneLink, + color = RadixTheme.colors.blue1, + inlineContent = mapOf("link_icon" to InlineTextContent( + Placeholder( + RadixTheme.typography.body1StandaloneLink.fontSize, + RadixTheme.typography.body1StandaloneLink.fontSize, + PlaceholderVerticalAlign.TextCenter + ) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_external_link), + contentDescription = null, + tint = color + ) + }) + ) } } } @@ -291,6 +297,6 @@ fun MetadataValueView( private const val ASSET_METADATA_SHORT_STRING_THRESHOLD = 40 private val Metadata.isRenderedInNewLine: Boolean get() = this is Metadata.Primitive && ( - valueType is MetadataType.Url || - (valueType is MetadataType.String && value.length > ASSET_METADATA_SHORT_STRING_THRESHOLD) - ) + valueType is MetadataType.Url || + (valueType is MetadataType.String && value.length > ASSET_METADATA_SHORT_STRING_THRESHOLD) + ) From 480ebd4a88d22974781f12a846398c3f02587370 Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Wed, 26 Jun 2024 14:23:46 +0300 Subject: [PATCH 10/18] Fix test issues --- .../cache/database/ProvidedConverters.kt | 6 +- .../cache/database/ResourceEntity.kt | 1 + .../repository/cache/database/StateDao.kt | 1 - .../repository/state/AccountsStateCache.kt | 96 +++++++++---------- .../data/repository/state/StateRepository.kt | 2 +- .../account/composable/MetadataView.kt | 34 +++---- .../presentation/status/assets/AssetDialog.kt | 1 - .../assets/fungible/FungibleDialogContent.kt | 39 +++++--- .../status/assets/lsu/LSUDialogContent.kt | 39 +++++--- .../ActionableAddressView.kt | 3 - .../usecases/SearchFeePayersUseCaseTest.kt | 3 +- .../android/fakes/StateRepositoryFake.kt | 12 ++- .../login/DAppAuthorizedLoginViewModelTest.kt | 3 +- 13 files changed, 131 insertions(+), 109 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt index bbb42eacae..bffd706390 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ProvidedConverters.kt @@ -57,7 +57,7 @@ data class MetadataColumn( */ @Serializable @SerialName("unknown") - data object Unknown: ImplicitMetadataState + data object Unknown : ImplicitMetadataState /** * We have received an answer from a details request and we know that the [MetadataColumn.metadata] @@ -65,7 +65,7 @@ data class MetadataColumn( */ @Serializable @SerialName("complete") - data object Complete: ImplicitMetadataState + data object Complete : ImplicitMetadataState /** * We have received an answer from a details request and we know that the [MetadataColumn.metadata] @@ -76,7 +76,7 @@ data class MetadataColumn( data class Incomplete( @SerialName("next_cursor") val nextCursor: String - ): ImplicitMetadataState + ) : ImplicitMetadataState } companion object { diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt index 02d52ab3e3..214ce47aae 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/ResourceEntity.kt @@ -158,6 +158,7 @@ data class ResourceEntity( ) } + @Suppress("LongParameterList") private fun from( address: ResourceAddress, explicitMetadata: EntityMetadataCollection?, diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt index a92453e6c1..04f596388d 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/cache/database/StateDao.kt @@ -324,7 +324,6 @@ interface StateDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertDApps(dApps: List) - @Query( """ UPDATE ResourceEntity SET diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt index 270664d2ed..ff628ce264 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/state/AccountsStateCache.kt @@ -233,62 +233,47 @@ class AccountsStateCache @Inject constructor( result } - private fun Flow>.compileAccountAddressAssets(): Flow> = - transform { cached -> - val stateVersion = cached.values.mapNotNull { it.stateVersion }.maxOrNull() ?: run { - emit(emptyList()) - return@transform + private fun Flow>.compileAccountAddressAssets() = transform { cached -> + val stateVersion = cached.values.mapNotNull { it.stateVersion }.maxOrNull() ?: run { + emit(emptyList()) + return@transform + } + + val allValidatorAddresses = cached.map { it.value.validatorAddresses() }.flatten().toSet() + val cachedValidators = dao.getCachedValidators(allValidatorAddresses, stateVersion).toMutableMap() + val newValidators = runCatching { + val validatorItems = api.fetchValidators( + allValidatorAddresses - cachedValidators.keys, + stateVersion + ).validators + + val syncInfo = SyncInfo(InstantGenerator(), stateVersion) + validatorItems.map { + it.asValidatorEntity(syncInfo) + }.onEach { entity -> + cachedValidators[entity.address] = entity.asValidatorDetail() } + }.onFailure { cacheErrors.value = it }.getOrNull() ?: return@transform - val allValidatorAddresses = cached.map { it.value.validatorAddresses() }.flatten().toSet() - val cachedValidators = dao.getCachedValidators(allValidatorAddresses, stateVersion).toMutableMap() - val newValidators = runCatching { - val validatorItems = api.fetchValidators( - allValidatorAddresses - cachedValidators.keys, - stateVersion - ).validators - - val syncInfo = SyncInfo(InstantGenerator(), stateVersion) - validatorItems.map { - it.asValidatorEntity(syncInfo) - }.onEach { entity -> - cachedValidators[entity.address] = entity.asValidatorDetail() - } + if (newValidators.isNotEmpty()) { + logger.d("\uD83D\uDCBD Inserting validators") + dao.insertValidators(newValidators) + } + + val allPoolAddresses = cached.map { it.value.poolAddresses() }.flatten().toSet() + val cachedPools = dao.getCachedPools(allPoolAddresses, stateVersion).toMutableMap() + val unknownPools = allPoolAddresses - cachedPools.keys + if (unknownPools.isNotEmpty()) { + logger.d("\uD83D\uDCBD Inserting pools") + val newPools = runCatching { + api.fetchPools(unknownPools.toSet(), stateVersion) }.onFailure { error -> cacheErrors.value = error }.getOrNull() ?: return@transform - if (newValidators.isNotEmpty()) { - logger.d("\uD83D\uDCBD Inserting validators") - dao.insertValidators(newValidators) - } - - val allPoolAddresses = cached.map { it.value.poolAddresses() }.flatten().toSet() - val cachedPools = dao.getCachedPools(allPoolAddresses, stateVersion).toMutableMap() - val unknownPools = allPoolAddresses - cachedPools.keys - if (unknownPools.isNotEmpty()) { - logger.d("\uD83D\uDCBD Inserting pools") - - val newPools = runCatching { - api.fetchPools(unknownPools.toSet(), stateVersion) - }.onFailure { error -> - cacheErrors.value = error - }.getOrNull() ?: return@transform - - if (newPools.poolItems.isNotEmpty()) { - val join = newPools.poolItems.asPoolsResourcesJoin(SyncInfo(InstantGenerator(), stateVersion)) - dao.updatePools(pools = join) - } else { - emit( - cached.mapNotNull { - it.value.toAccountAddressWithAssets( - accountAddress = it.key, - pools = cachedPools, - validators = cachedValidators - ) - } - ) - } + if (newPools.poolItems.isNotEmpty()) { + val join = newPools.poolItems.asPoolsResourcesJoin(SyncInfo(InstantGenerator(), stateVersion)) + dao.updatePools(pools = join) } else { emit( cached.mapNotNull { @@ -300,7 +285,18 @@ class AccountsStateCache @Inject constructor( } ) } + } else { + emit( + cached.mapNotNull { + it.value.toAccountAddressWithAssets( + accountAddress = it.key, + pools = cachedPools, + validators = cachedValidators + ) + } + ) } + } private data class AccountCachedData( val stateVersion: Long?, diff --git a/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt b/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt index d7c5e2dd7a..2a3d5989b4 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/repository/state/StateRepository.kt @@ -438,7 +438,7 @@ class StateRepositoryImpl @Inject constructor( } else { cachedValidators } - }.mapCatching { entities -> + }.mapCatching { entities -> entities.map { it.asValidatorDetail() } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt index 8c14039ae2..54481260b8 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt @@ -276,19 +276,21 @@ fun MetadataValueView( }, style = RadixTheme.typography.body1StandaloneLink, color = RadixTheme.colors.blue1, - inlineContent = mapOf("link_icon" to InlineTextContent( - Placeholder( - RadixTheme.typography.body1StandaloneLink.fontSize, - RadixTheme.typography.body1StandaloneLink.fontSize, - PlaceholderVerticalAlign.TextCenter - ) - ) { - Icon( - painter = painterResource(id = R.drawable.ic_external_link), - contentDescription = null, - tint = color - ) - }) + inlineContent = mapOf( + "link_icon" to InlineTextContent( + Placeholder( + RadixTheme.typography.body1StandaloneLink.fontSize, + RadixTheme.typography.body1StandaloneLink.fontSize, + PlaceholderVerticalAlign.TextCenter + ) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_external_link), + contentDescription = null, + tint = color + ) + } + ) ) } } @@ -297,6 +299,6 @@ fun MetadataValueView( private const val ASSET_METADATA_SHORT_STRING_THRESHOLD = 40 private val Metadata.isRenderedInNewLine: Boolean get() = this is Metadata.Primitive && ( - valueType is MetadataType.Url || - (valueType is MetadataType.String && value.length > ASSET_METADATA_SHORT_STRING_THRESHOLD) - ) + valueType is MetadataType.Url || + (valueType is MetadataType.String && value.length > ASSET_METADATA_SHORT_STRING_THRESHOLD) + ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt index 2e6b58a7fb..4363dcf1ec 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt @@ -162,7 +162,6 @@ fun DescriptionSection( HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) } - } @Composable diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt index 373f9ff346..3ce8484694 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt @@ -63,22 +63,9 @@ fun FungibleDialogContent( ), horizontalAlignment = Alignment.CenterHorizontally ) { - if (token?.resource != null) { - Thumbnail.Fungible( - modifier = Modifier.size(104.dp), - token = token.resource - ) - } else { - Box( - modifier = Modifier - .size(104.dp) - .radixPlaceholder( - visible = true, - shape = CircleShape - ) - ) - } + FungibleIconSection(token = token) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) + if (amount != null) { TokenBalance( modifier = Modifier @@ -169,3 +156,25 @@ fun FungibleDialogContent( } } } + +@Composable +private fun FungibleIconSection( + modifier: Modifier = Modifier, + token: Token? +) { + if (token?.resource != null) { + Thumbnail.Fungible( + modifier = modifier.size(104.dp), + token = token.resource + ) + } else { + Box( + modifier = modifier + .size(104.dp) + .radixPlaceholder( + visible = true, + shape = CircleShape + ) + ) + } +} diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt index 1f8e140518..3192a9c6bb 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt @@ -73,22 +73,9 @@ fun LSUDialogContent( ), horizontalAlignment = Alignment.CenterHorizontally ) { - if (lsu != null) { - Thumbnail.LSU( - modifier = Modifier.size(104.dp), - liquidStakeUnit = lsu - ) - } else { - Box( - modifier = Modifier - .size(104.dp) - .radixPlaceholder( - visible = true, - shape = CircleShape - ) - ) - } + LSUIconSection(lsu = lsu) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) + TokenBalance( modifier = Modifier .fillMaxWidth(fraction = if (lsu == null) 0.5f else 1f) @@ -238,6 +225,28 @@ fun LSUDialogContent( } } +@Composable +private fun LSUIconSection( + modifier: Modifier = Modifier, + lsu: LiquidStakeUnit? +) { + if (lsu != null) { + Thumbnail.LSU( + modifier = modifier.size(104.dp), + liquidStakeUnit = lsu + ) + } else { + Box( + modifier = modifier + .size(104.dp) + .radixPlaceholder( + visible = true, + shape = CircleShape + ) + ) + } +} + @Composable private fun LSUResourceValue( modifier: Modifier = Modifier, 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 9c251634eb..35b396ea2a 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 @@ -2,10 +2,8 @@ package com.babylon.wallet.android.presentation.ui.composables.actionableaddress -import android.content.ClipData import android.content.Context import android.net.Uri -import android.os.Build import android.widget.Toast import androidx.annotation.DrawableRes import androidx.annotation.VisibleForTesting @@ -45,7 +43,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension -import androidx.core.content.getSystemService import androidx.core.net.toUri import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme diff --git a/app/src/test/java/com/babylon/wallet/android/domain/usecases/SearchFeePayersUseCaseTest.kt b/app/src/test/java/com/babylon/wallet/android/domain/usecases/SearchFeePayersUseCaseTest.kt index 36c95090ec..12c32db309 100644 --- a/app/src/test/java/com/babylon/wallet/android/domain/usecases/SearchFeePayersUseCaseTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/domain/usecases/SearchFeePayersUseCaseTest.kt @@ -148,7 +148,8 @@ class SearchFeePayersUseCaseTest { override suspend fun getResources( addresses: Set, underAccountAddress: AccountAddress?, - withDetails: Boolean + withDetails: Boolean, + withAllMetadata: Boolean ): Result> { TODO("Not yet implemented") } diff --git a/app/src/test/java/com/babylon/wallet/android/fakes/StateRepositoryFake.kt b/app/src/test/java/com/babylon/wallet/android/fakes/StateRepositoryFake.kt index 589e7a67f9..353085772f 100644 --- a/app/src/test/java/com/babylon/wallet/android/fakes/StateRepositoryFake.kt +++ b/app/src/test/java/com/babylon/wallet/android/fakes/StateRepositoryFake.kt @@ -37,7 +37,12 @@ open class StateRepositoryFake : StateRepository { override suspend fun updateStakeClaims(account: Account, claims: List): Result> = Result.success(claims) - override suspend fun getResources(addresses: Set, underAccountAddress: AccountAddress?, withDetails: Boolean): Result> = + override suspend fun getResources( + addresses: Set, + underAccountAddress: AccountAddress?, + withDetails: Boolean, + withAllMetadata: Boolean + ): Result> = Result.failure(RuntimeException("Not implemented")) override suspend fun getPools(poolAddresses: Set): Result> = Result.failure(RuntimeException("Not implemented")) @@ -45,7 +50,10 @@ open class StateRepositoryFake : StateRepository { override suspend fun getValidators(validatorAddresses: Set): Result> = Result.failure(RuntimeException("Not implemented")) - override suspend fun getNFTDetails(resourceAddress: ResourceAddress, localIds: Set): Result> = + override suspend fun getNFTDetails( + resourceAddress: ResourceAddress, + localIds: Set + ): Result> = Result.failure(RuntimeException("Not implemented")) override suspend fun getOwnedXRD(accounts: List): Result> = diff --git a/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt b/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt index c53a311008..7915fdee49 100644 --- a/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt +++ b/app/src/test/java/com/babylon/wallet/android/presentation/dapp/login/DAppAuthorizedLoginViewModelTest.kt @@ -305,7 +305,8 @@ class DAppAuthorizedLoginViewModelTest : StateViewModelTest, underAccountAddress: AccountAddress?, - withDetails: Boolean + withDetails: Boolean, + withAllMetadata: Boolean ): Result> { TODO("Not yet implemented") } From 72be1549848020f6e5e0a9328d2046a283dd364b Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Thu, 27 Jun 2024 10:32:19 +0300 Subject: [PATCH 11/18] Put back info url --- .../works/core/domain/resources/ExplicitMetadataKey.kt | 2 ++ .../java/rdx/works/core/domain/resources/Resource.kt | 9 +++++++++ .../core/domain/resources/metadata/StandardMetadata.kt | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/core/src/main/java/rdx/works/core/domain/resources/ExplicitMetadataKey.kt b/core/src/main/java/rdx/works/core/domain/resources/ExplicitMetadataKey.kt index c197103521..207678d1e5 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/ExplicitMetadataKey.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/ExplicitMetadataKey.kt @@ -19,6 +19,7 @@ enum class ExplicitMetadataKey(val key: String) { TAGS("tags"), KEY_IMAGE_URL("key_image_url"), ICON_URL("icon_url"), + INFO_URL("info_url"), VALIDATOR("validator"), CLAIM_AMOUNT("claim_amount"), CLAIM_EPOCH("claim_epoch"), @@ -35,6 +36,7 @@ enum class ExplicitMetadataKey(val key: String) { DESCRIPTION, RELATED_WEBSITES, ICON_URL, + INFO_URL, VALIDATOR, POOL, TAGS, diff --git a/core/src/main/java/rdx/works/core/domain/resources/Resource.kt b/core/src/main/java/rdx/works/core/domain/resources/Resource.kt index 84dab7ed1e..2bc6d1524d 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/Resource.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/Resource.kt @@ -26,6 +26,7 @@ import rdx.works.core.domain.resources.metadata.claimAmount import rdx.works.core.domain.resources.metadata.claimEpoch import rdx.works.core.domain.resources.metadata.description import rdx.works.core.domain.resources.metadata.iconUrl +import rdx.works.core.domain.resources.metadata.infoUrl import rdx.works.core.domain.resources.metadata.isLocked import rdx.works.core.domain.resources.metadata.keyImageUrl import rdx.works.core.domain.resources.metadata.name @@ -95,6 +96,10 @@ sealed class Resource { metadata.isLocked(key = ExplicitMetadataKey.ICON_URL) } + val infoUrl: Uri? by lazy { + metadata.infoUrl() + } + override val validatorAddress: ValidatorAddress? by lazy { metadata.validatorAddress() } @@ -209,6 +214,10 @@ sealed class Resource { metadata.isLocked(key = ExplicitMetadataKey.ICON_URL) } + val infoUrl: Uri? by lazy { + metadata.infoUrl() + } + val tags: ImmutableList by lazy { metadata.tags().orEmpty().map { Tag.Dynamic(name = it.truncate(maxNumberOfCharacters = TAG_MAX_CHARS)) diff --git a/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt b/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt index c094131cfc..cb84e1527d 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt @@ -42,6 +42,11 @@ fun List.name(): String? = findPrimitive( type = MetadataType.String )?.value +fun List.infoUrl(): Uri? = findPrimitive( + key = ExplicitMetadataKey.INFO_URL, + type = MetadataType.Url +)?.value?.toUri() + fun List.iconUrl(): Uri? = findPrimitive( key = ExplicitMetadataKey.ICON_URL, type = MetadataType.Url From 76a8dee8b9c26f139ac6410416f024bf1079fa9b Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Thu, 27 Jun 2024 11:02:45 +0300 Subject: [PATCH 12/18] Add more info url --- .../presentation/status/assets/AssetDialog.kt | 90 ++++++++++++++++--- .../assets/fungible/FungibleDialogContent.kt | 12 +-- .../status/assets/lsu/LSUDialogContent.kt | 11 ++- .../NonFungibleAssetDialogContent.kt | 17 ++-- .../assets/pool/PoolUnitDialogContent.kt | 11 ++- 5 files changed, 104 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt index 4363dcf1ec..6120339cd8 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt @@ -1,6 +1,9 @@ package com.babylon.wallet.android.presentation.status.assets +import android.net.Uri +import androidx.compose.foundation.background import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi @@ -10,14 +13,25 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.InlineTextContent +import androidx.compose.foundation.text.appendInlineContent import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.Placeholder +import androidx.compose.ui.text.PlaceholderVerticalAlign +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.babylon.wallet.android.R @@ -34,7 +48,9 @@ import com.babylon.wallet.android.presentation.ui.composables.assets.Behaviour import com.babylon.wallet.android.presentation.ui.composables.assets.Tag import com.babylon.wallet.android.presentation.ui.composables.icon import com.babylon.wallet.android.presentation.ui.composables.name +import com.babylon.wallet.android.presentation.ui.modifier.applyIf import com.babylon.wallet.android.presentation.ui.modifier.radixPlaceholder +import com.babylon.wallet.android.utils.openUrl import kotlinx.collections.immutable.ImmutableList import rdx.works.core.domain.assets.Asset import rdx.works.core.domain.assets.AssetBehaviours @@ -147,20 +163,72 @@ fun Asset.displayTitle() = when (this) { @Composable fun DescriptionSection( modifier: Modifier = Modifier, - description: String + description: String?, + infoUrl: Uri? ) { Column( - modifier = modifier + modifier = modifier.fillMaxWidth() ) { - Text( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - text = description, - style = RadixTheme.typography.body1Regular, - color = RadixTheme.colors.gray1 - ) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) + if (!description.isNullOrBlank()) { + Text( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = RadixTheme.dimensions.paddingSmall) + .padding(bottom = if (infoUrl != null) RadixTheme.dimensions.paddingSemiLarge else 0.dp), + text = description, + style = RadixTheme.typography.body1Regular, + color = RadixTheme.colors.gray1, + textAlign = TextAlign.Start + ) + } + + if (infoUrl != null) { + Text( + modifier = Modifier + .padding(horizontal = RadixTheme.dimensions.paddingSmall), + text = stringResource(id = R.string.assetDetails_moreInfo), + style = RadixTheme.typography.body1Regular, + color = RadixTheme.colors.gray2 + ) + + val context = LocalContext.current + Text( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = RadixTheme.dimensions.paddingSmall) + .padding(top = RadixTheme.dimensions.paddingXSmall) + .clickable { context.openUrl(infoUrl) }, + text = buildAnnotatedString { + append(infoUrl.toString()) + append(" ") + appendInlineContent(id = "link_icon") + }, + style = RadixTheme.typography.body1StandaloneLink, + color = RadixTheme.colors.blue1, + inlineContent = mapOf( + "link_icon" to InlineTextContent( + Placeholder( + RadixTheme.typography.body1StandaloneLink.fontSize, + RadixTheme.typography.body1StandaloneLink.fontSize, + PlaceholderVerticalAlign.TextCenter + ) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_external_link), + contentDescription = null, + tint = RadixTheme.colors.gray2 + ) + } + ), + textAlign = TextAlign.Start, + ) + } + + if (!description.isNullOrBlank() || infoUrl != null) { + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) + HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) + } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt index 3ce8484694..06519ed415 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt @@ -97,12 +97,12 @@ fun FungibleDialogContent( HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - if (!token?.resource?.description.isNullOrBlank()) { - DescriptionSection( - modifier = Modifier.fillMaxWidth(), - description = token?.resource?.description.orEmpty() - ) - } + DescriptionSection( + modifier = Modifier.fillMaxWidth(), + description = token?.resource?.description, + infoUrl = token?.resource?.infoUrl + ) + AddressRow( modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt index 3192a9c6bb..9d1b106bd5 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt @@ -135,12 +135,11 @@ fun LSUDialogContent( ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - if (!lsu?.fungibleResource?.description.isNullOrBlank()) { - DescriptionSection( - modifier = Modifier.fillMaxWidth(), - description = lsu?.fungibleResource?.description.orEmpty() - ) - } + DescriptionSection( + modifier = Modifier.fillMaxWidth(), + description = lsu?.fungibleResource?.description, + infoUrl = lsu?.fungibleResource?.infoUrl + ) AddressRow( modifier = Modifier diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt index c37bb8b74e..99eb7b3b77 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt @@ -23,6 +23,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -202,14 +203,14 @@ fun NonFungibleAssetDialogContent( ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - if (!asset?.resource?.description.isNullOrBlank()) { - DescriptionSection( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = RadixTheme.dimensions.paddingLarge), - description = asset?.resource?.description.orEmpty() - ) - } + DescriptionSection( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = RadixTheme.dimensions.paddingLarge), + description = asset?.resource?.description, + infoUrl = asset?.resource?.infoUrl + ) + AddressRow( modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt index 476a7ab967..f59248cc12 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt @@ -152,12 +152,11 @@ fun PoolUnitDialogContent( ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) - if (!poolUnit?.stake?.description.isNullOrBlank()) { - DescriptionSection( - modifier = Modifier.fillMaxWidth(), - description = poolUnit?.stake?.description.orEmpty() - ) - } + DescriptionSection( + modifier = Modifier.fillMaxWidth(), + description = poolUnit?.stake?.description, + infoUrl = poolUnit?.stake?.infoUrl + ) AddressRow( modifier = Modifier From 2a350f2b85daad2cb75d7ffec98281d5ae5a215a Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Thu, 27 Jun 2024 11:14:13 +0300 Subject: [PATCH 13/18] Unify usage of LinkText --- .../account/composable/MetadataView.kt | 32 +------- .../dappdetail/DappDetailScreen.kt | 34 ++------ .../presentation/status/assets/AssetDialog.kt | 45 +---------- .../presentation/ui/composables/LinkText.kt | 80 +++++++++++++++++++ 4 files changed, 95 insertions(+), 96 deletions(-) create mode 100644 app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/LinkText.kt diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt index 54481260b8..916927ba38 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt @@ -1,6 +1,5 @@ package com.babylon.wallet.android.presentation.account.composable -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -28,10 +27,10 @@ import androidx.compose.ui.text.style.TextOverflow import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.ui.composables.ExpandableText +import com.babylon.wallet.android.presentation.ui.composables.LinkText import com.babylon.wallet.android.presentation.ui.composables.actionableaddress.ActionableAddressView import com.babylon.wallet.android.presentation.ui.modifier.throttleClickable import com.babylon.wallet.android.utils.copyToClipboard -import com.babylon.wallet.android.utils.openUrl import com.radixdlt.sargon.Address import com.radixdlt.sargon.NonFungibleGlobalId import com.radixdlt.sargon.NonFungibleLocalId @@ -265,32 +264,9 @@ fun MetadataValueView( maxLines = 2 ) - MetadataType.Url -> Text( - modifier = modifier - .fillMaxWidth() - .clickable { context.openUrl(metadata.value) }, - text = buildAnnotatedString { - append(metadata.value) - append(" ") - appendInlineContent(id = "link_icon") - }, - style = RadixTheme.typography.body1StandaloneLink, - color = RadixTheme.colors.blue1, - inlineContent = mapOf( - "link_icon" to InlineTextContent( - Placeholder( - RadixTheme.typography.body1StandaloneLink.fontSize, - RadixTheme.typography.body1StandaloneLink.fontSize, - PlaceholderVerticalAlign.TextCenter - ) - ) { - Icon( - painter = painterResource(id = R.drawable.ic_external_link), - contentDescription = null, - tint = color - ) - } - ) + MetadataType.Url -> LinkText( + modifier = modifier.fillMaxWidth(), + url = metadata.value ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt b/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt index 9449202a75..9b9b484b4e 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt @@ -4,7 +4,6 @@ package com.babylon.wallet.android.presentation.settings.approveddapps.dappdetai import androidx.activity.compose.BackHandler import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -26,7 +25,6 @@ import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.rememberModalBottomSheetState @@ -43,7 +41,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview @@ -64,6 +61,7 @@ import com.babylon.wallet.android.presentation.ui.RadixWalletPreviewTheme import com.babylon.wallet.android.presentation.ui.composables.BasicPromptAlertDialog import com.babylon.wallet.android.presentation.ui.composables.DefaultModalSheetLayout import com.babylon.wallet.android.presentation.ui.composables.GrayBackgroundWrapper +import com.babylon.wallet.android.presentation.ui.composables.LinkText import com.babylon.wallet.android.presentation.ui.composables.PersonaDataFieldRow import com.babylon.wallet.android.presentation.ui.composables.PersonaDataStringField import com.babylon.wallet.android.presentation.ui.composables.RadixCenteredTopAppBar @@ -75,7 +73,6 @@ import com.babylon.wallet.android.presentation.ui.composables.card.NonFungibleCa import com.babylon.wallet.android.presentation.ui.composables.card.PersonaCard import com.babylon.wallet.android.presentation.ui.modifier.radixPlaceholder import com.babylon.wallet.android.presentation.ui.modifier.throttleClickable -import com.babylon.wallet.android.utils.openUrl import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.Address import com.radixdlt.sargon.AppearanceId @@ -499,31 +496,14 @@ fun DAppWebsiteAddressRow( style = RadixTheme.typography.body1Regular, color = RadixTheme.colors.gray2 ) - Row( + + LinkText( modifier = Modifier .fillMaxWidth() - .clickable(enabled = website != null) { - if (website != null) { - context.openUrl(website) - } - }, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(dimensions.paddingSmall) - ) { - Text( - modifier = Modifier - .weight(1f) - .radixPlaceholder(visible = website == null), - text = website.orEmpty(), - style = RadixTheme.typography.body1HighImportance, - color = RadixTheme.colors.blue1 - ) - Icon( - painter = painterResource(id = com.babylon.wallet.android.designsystem.R.drawable.ic_link_out), - tint = RadixTheme.colors.gray3, - contentDescription = null - ) - } + .radixPlaceholder(visible = website == null), + clickable = website != null, + url = website.orEmpty() + ) } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt index 6120339cd8..3b7fc1340a 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt @@ -1,9 +1,7 @@ package com.babylon.wallet.android.presentation.status.assets import android.net.Uri -import androidx.compose.foundation.background import androidx.compose.foundation.border -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi @@ -13,25 +11,15 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.text.InlineTextContent -import androidx.compose.foundation.text.appendInlineContent import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.Placeholder -import androidx.compose.ui.text.PlaceholderVerticalAlign -import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.babylon.wallet.android.R @@ -43,14 +31,13 @@ import com.babylon.wallet.android.presentation.status.assets.lsu.LSUDialogConten import com.babylon.wallet.android.presentation.status.assets.nonfungible.NonFungibleAssetDialogContent import com.babylon.wallet.android.presentation.status.assets.pool.PoolUnitDialogContent import com.babylon.wallet.android.presentation.ui.composables.BottomSheetDialogWrapper +import com.babylon.wallet.android.presentation.ui.composables.LinkText import com.babylon.wallet.android.presentation.ui.composables.SnackbarUiMessageHandler import com.babylon.wallet.android.presentation.ui.composables.assets.Behaviour import com.babylon.wallet.android.presentation.ui.composables.assets.Tag import com.babylon.wallet.android.presentation.ui.composables.icon import com.babylon.wallet.android.presentation.ui.composables.name -import com.babylon.wallet.android.presentation.ui.modifier.applyIf import com.babylon.wallet.android.presentation.ui.modifier.radixPlaceholder -import com.babylon.wallet.android.utils.openUrl import kotlinx.collections.immutable.ImmutableList import rdx.works.core.domain.assets.Asset import rdx.works.core.domain.assets.AssetBehaviours @@ -191,36 +178,12 @@ fun DescriptionSection( color = RadixTheme.colors.gray2 ) - val context = LocalContext.current - Text( + LinkText( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingSmall) - .padding(top = RadixTheme.dimensions.paddingXSmall) - .clickable { context.openUrl(infoUrl) }, - text = buildAnnotatedString { - append(infoUrl.toString()) - append(" ") - appendInlineContent(id = "link_icon") - }, - style = RadixTheme.typography.body1StandaloneLink, - color = RadixTheme.colors.blue1, - inlineContent = mapOf( - "link_icon" to InlineTextContent( - Placeholder( - RadixTheme.typography.body1StandaloneLink.fontSize, - RadixTheme.typography.body1StandaloneLink.fontSize, - PlaceholderVerticalAlign.TextCenter - ) - ) { - Icon( - painter = painterResource(id = R.drawable.ic_external_link), - contentDescription = null, - tint = RadixTheme.colors.gray2 - ) - } - ), - textAlign = TextAlign.Start, + .padding(top = RadixTheme.dimensions.paddingXSmall), + url = infoUrl ) } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/LinkText.kt b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/LinkText.kt new file mode 100644 index 0000000000..efc8221dfa --- /dev/null +++ b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/LinkText.kt @@ -0,0 +1,80 @@ +package com.babylon.wallet.android.presentation.ui.composables + +import android.net.Uri +import androidx.compose.foundation.text.InlineTextContent +import androidx.compose.foundation.text.appendInlineContent +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.Placeholder +import androidx.compose.ui.text.PlaceholderVerticalAlign +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.style.TextAlign +import com.babylon.wallet.android.R +import com.babylon.wallet.android.designsystem.theme.RadixTheme +import com.babylon.wallet.android.presentation.ui.modifier.throttleClickable +import com.babylon.wallet.android.utils.openUrl + +@Composable +fun LinkText( + modifier: Modifier = Modifier, + url: Uri, + clickable: Boolean = true, + linkStyle: TextStyle = RadixTheme.typography.body1StandaloneLink, + linkColor: Color = RadixTheme.colors.blue1, + linkIconColor: Color = RadixTheme.colors.gray2 +) { + LinkText( + modifier = modifier, + url = url.toString(), + clickable = clickable, + linkStyle = linkStyle, + linkColor = linkColor, + linkIconColor = linkIconColor + ) +} + +@Composable +fun LinkText( + modifier: Modifier = Modifier, + url: String, + clickable: Boolean = true, + linkStyle: TextStyle = RadixTheme.typography.body1StandaloneLink, + linkColor: Color = RadixTheme.colors.blue1, + linkIconColor: Color = RadixTheme.colors.gray2 +) { + val context = LocalContext.current + Text( + modifier = modifier.throttleClickable(enabled = clickable) { + context.openUrl(url) + }, + text = buildAnnotatedString { + append(url) + append(" ") + appendInlineContent(id = "link_icon") + }, + style = linkStyle, + color = linkColor, + inlineContent = mapOf( + "link_icon" to InlineTextContent( + Placeholder( + linkStyle.fontSize, + linkStyle.fontSize, + PlaceholderVerticalAlign.TextCenter + ) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_external_link), + contentDescription = null, + tint = linkIconColor + ) + } + ), + textAlign = TextAlign.Start, + ) +} \ No newline at end of file From 0195e7faffc1dbafafffb2c39bbb2c91ae744cfb Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Thu, 27 Jun 2024 12:23:33 +0300 Subject: [PATCH 14/18] Put non standard metadata at the end of the sheet --- .../presentation/status/assets/AssetDialog.kt | 16 +++++--- .../assets/fungible/FungibleDialogContent.kt | 14 +++---- .../status/assets/lsu/LSUDialogContent.kt | 17 +++------ .../NonFungibleAssetDialogContent.kt | 20 +++++----- .../assets/pool/PoolUnitDialogContent.kt | 14 +++---- .../works/core/domain/resources/Resource.kt | 37 ------------------- .../resources/metadata/StandardMetadata.kt | 2 - 7 files changed, 36 insertions(+), 84 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt index 3b7fc1340a..6c10d99f52 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/AssetDialog.kt @@ -208,9 +208,17 @@ fun NonStandardMetadataSection( Column( modifier = modifier ) { + Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingLarge)) + HorizontalDivider(Modifier.fillMaxWidth(), color = RadixTheme.colors.gray4) + metadata.forEach { metadata -> Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) - MetadataView(modifier = Modifier.fillMaxWidth(), metadata = metadata) + MetadataView( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = RadixTheme.dimensions.paddingSmall), + metadata = metadata + ) } } } @@ -266,8 +274,7 @@ fun BehavioursSection( @Composable fun TagsSection( modifier: Modifier = Modifier, - tags: ImmutableList?, - isLocked: Boolean + tags: ImmutableList? ) { if (!tags.isNullOrEmpty()) { Column(modifier = modifier) { @@ -275,7 +282,7 @@ fun TagsSection( MetadataKeyView( modifier = Modifier.fillMaxWidth(), key = stringResource(id = R.string.assetDetails_tags), - isLocked = isLocked + isLocked = false ) Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingDefault)) FlowRow( @@ -297,7 +304,6 @@ fun TagsSection( } } ) - Spacer(modifier = Modifier.height(RadixTheme.dimensions.paddingXXLarge)) } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt index 06519ed415..c1926988dc 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/fungible/FungibleDialogContent.kt @@ -135,13 +135,6 @@ fun FungibleDialogContent( ) } - token?.resource?.let { resource -> - NonStandardMetadataSection( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - resource = resource - ) - } - BehavioursSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), isXRD = token?.resource?.isXrd ?: false, @@ -150,9 +143,12 @@ fun FungibleDialogContent( TagsSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - tags = token?.resource?.tags, - isLocked = token?.resource?.isTagsLocked ?: false + tags = token?.resource?.tags ) + + token?.resource?.let { resource -> + NonStandardMetadataSection(resource = resource) + } } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt index 9d1b106bd5..1b0095c772 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt @@ -165,8 +165,7 @@ fun LSUDialogContent( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingSmall), - key = stringResource(id = R.string.assetDetails_name), - isLocked = lsu?.resource?.isNameLocked ?: false + key = stringResource(id = R.string.assetDetails_name) ) { Text( modifier = Modifier @@ -204,13 +203,6 @@ fun LSUDialogContent( ) } - lsu?.resource?.let { resource -> - NonStandardMetadataSection( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - resource = resource - ) - } - BehavioursSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), behaviours = lsu?.fungibleResource?.behaviours @@ -218,9 +210,12 @@ fun LSUDialogContent( TagsSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - tags = lsu?.fungibleResource?.tags, - isLocked = lsu?.resource?.isTagsLocked ?: false + tags = lsu?.fungibleResource?.tags ) + + lsu?.resource?.let { resource -> + NonStandardMetadataSection(resource = resource) + } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt index 99eb7b3b77..2c6d227bdd 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt @@ -224,8 +224,7 @@ fun NonFungibleAssetDialogContent( modifier = Modifier .fillMaxWidth() .padding(horizontal = RadixTheme.dimensions.paddingXXLarge), - key = stringResource(id = R.string.assetDetails_name), - isLocked = asset?.resource?.isNameLocked ?: false + key = stringResource(id = R.string.assetDetails_name) ) { Text( text = asset?.resource?.name.orEmpty(), @@ -262,13 +261,6 @@ fun NonFungibleAssetDialogContent( ) } - asset?.resource?.let { resource -> - NonStandardMetadataSection( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingXXLarge), - resource = resource - ) - } - BehavioursSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingXXLarge), behaviours = asset?.resource?.behaviours @@ -276,9 +268,15 @@ fun NonFungibleAssetDialogContent( TagsSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingXXLarge), - tags = asset?.resource?.tags, - isLocked = asset?.resource?.isTagsLocked ?: false + tags = asset?.resource?.tags ) + + asset?.resource?.let { resource -> + NonStandardMetadataSection( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingLarge), + resource = resource + ) + } } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt index f59248cc12..978ce17fb9 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt @@ -188,13 +188,6 @@ fun PoolUnitDialogContent( ) } - poolUnit?.resource?.let { resource -> - NonStandardMetadataSection( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - resource = resource - ) - } - BehavioursSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), behaviours = poolUnit?.resource?.behaviours @@ -202,8 +195,11 @@ fun PoolUnitDialogContent( TagsSection( modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), - tags = poolUnit?.resource?.tags, - isLocked = poolUnit?.resource?.isTagsLocked ?: false + tags = poolUnit?.resource?.tags ) + + poolUnit?.resource?.let { resource -> + NonStandardMetadataSection(resource = resource) + } } } diff --git a/core/src/main/java/rdx/works/core/domain/resources/Resource.kt b/core/src/main/java/rdx/works/core/domain/resources/Resource.kt index 2bc6d1524d..23a92e47fb 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/Resource.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/Resource.kt @@ -27,7 +27,6 @@ import rdx.works.core.domain.resources.metadata.claimEpoch import rdx.works.core.domain.resources.metadata.description import rdx.works.core.domain.resources.metadata.iconUrl import rdx.works.core.domain.resources.metadata.infoUrl -import rdx.works.core.domain.resources.metadata.isLocked import rdx.works.core.domain.resources.metadata.keyImageUrl import rdx.works.core.domain.resources.metadata.name import rdx.works.core.domain.resources.metadata.poolAddress @@ -68,34 +67,18 @@ sealed class Resource { metadata.name().orEmpty().truncate(maxNumberOfCharacters = NAME_MAX_CHARS) } - val isNameLocked: Boolean by lazy { - metadata.isLocked(key = ExplicitMetadataKey.NAME) - } - val symbol: String by lazy { metadata.symbol().orEmpty() } - val isSymbolLocked: Boolean by lazy { - metadata.isLocked(key = ExplicitMetadataKey.SYMBOL) - } - val description: String by lazy { metadata.description().orEmpty().truncate(maxNumberOfCharacters = DESCRIPTION_MAX_CHARS) } - val isDescriptionLocked: Boolean by lazy { - metadata.isLocked(key = ExplicitMetadataKey.DESCRIPTION) - } - override val iconUrl: Uri? by lazy { metadata.iconUrl() } - val isIconUrlLocked: Boolean by lazy { - metadata.isLocked(key = ExplicitMetadataKey.ICON_URL) - } - val infoUrl: Uri? by lazy { metadata.infoUrl() } @@ -124,10 +107,6 @@ sealed class Resource { }.take(TAGS_MAX).toImmutableList() } - val isTagsLocked: Boolean by lazy { - metadata.isLocked(key = ExplicitMetadataKey.TAGS) - } - val behaviours: AssetBehaviours? = if (assetBehaviours != null && isXrd) { assetBehaviours.filterNot { it == AssetBehaviour.INFORMATION_CHANGEABLE }.toSet() } else { @@ -194,26 +173,14 @@ sealed class Resource { metadata.name().orEmpty().truncate(maxNumberOfCharacters = NAME_MAX_CHARS) } - val isNameLocked: Boolean by lazy { - metadata.isLocked(key = ExplicitMetadataKey.NAME) - } - val description: String by lazy { metadata.description().orEmpty().truncate(maxNumberOfCharacters = DESCRIPTION_MAX_CHARS) } - val isDescriptionLocked: Boolean by lazy { - metadata.isLocked(key = ExplicitMetadataKey.DESCRIPTION) - } - override val iconUrl: Uri? by lazy { metadata.iconUrl() } - val isIconUrlLocked: Boolean by lazy { - metadata.isLocked(key = ExplicitMetadataKey.ICON_URL) - } - val infoUrl: Uri? by lazy { metadata.infoUrl() } @@ -224,10 +191,6 @@ sealed class Resource { }.take(TAGS_MAX).toImmutableList() } - val isTagsLocked: Boolean by lazy { - metadata.isLocked(key = ExplicitMetadataKey.TAGS) - } - override val validatorAddress: ValidatorAddress? by lazy { metadata.validatorAddress() } diff --git a/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt b/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt index cb84e1527d..be8d72dc71 100644 --- a/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt +++ b/core/src/main/java/rdx/works/core/domain/resources/metadata/StandardMetadata.kt @@ -25,8 +25,6 @@ private fun List.findCollection(key: ExplicitMetadataKey, type: Metada ?.takeIf { values -> values.all { it.valueType == type } } } -fun List.isLocked(key: ExplicitMetadataKey) = find { it.key == key.key }?.isLocked ?: false - fun List.description(): String? = findPrimitive( key = ExplicitMetadataKey.DESCRIPTION, type = MetadataType.String From 9f49a92cf8ebe3b050f2701ca3bf6a9e94c6eaeb Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Thu, 27 Jun 2024 13:07:23 +0300 Subject: [PATCH 15/18] Implement redesigned claim nft --- .../dappdetail/DappDetailScreen.kt | 2 - .../NonFungibleAssetDialogContent.kt | 101 +++++++++++------- .../presentation/ui/composables/LinkText.kt | 2 +- .../ui/composables/assets/StakingTab.kt | 11 +- 4 files changed, 69 insertions(+), 47 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt b/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt index 9b9b484b4e..6262d4098c 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/settings/approveddapps/dappdetail/DappDetailScreen.kt @@ -40,7 +40,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview @@ -484,7 +483,6 @@ fun DAppWebsiteAddressRow( modifier: Modifier = Modifier, website: String?, ) { - val context = LocalContext.current Column( modifier = modifier, verticalArrangement = Arrangement.spacedBy(dimensions.paddingSmall) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt index 2c6d227bdd..b92196dcdc 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt @@ -23,12 +23,11 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.babylon.wallet.android.R -import com.babylon.wallet.android.designsystem.composable.RadixTextButton +import com.babylon.wallet.android.designsystem.composable.RadixPrimaryButton import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.account.composable.MetadataView import com.babylon.wallet.android.presentation.status.assets.AssetDialogViewModel @@ -295,57 +294,77 @@ private fun ClaimNFTInfo( val showClaimButton = claimState is AssetDialogViewModel.State.ClaimState.ReadyToClaim && !accountContextMissing Column( modifier = modifier - .padding(horizontal = RadixTheme.dimensions.paddingXXLarge) + .padding(horizontal = RadixTheme.dimensions.paddingLarge) .fillMaxWidth() ) { - Row( - modifier = Modifier.padding(bottom = if (showClaimButton) 0.dp else RadixTheme.dimensions.paddingSmall), - horizontalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingSmall), - verticalAlignment = Alignment.CenterVertically - ) { - Text( - modifier = Modifier.weight(1f), - text = when (claimState) { - is AssetDialogViewModel.State.ClaimState.ReadyToClaim -> stringResource( - id = if (accountContextMissing) { - R.string.transactionReview_toBeClaimed - } else { - R.string.account_staking_readyToBeClaimed - } - ) - is AssetDialogViewModel.State.ClaimState.Unstaking -> - stringResource(id = R.string.account_staking_unstaking) - null -> "" - }.uppercase(), - style = RadixTheme.typography.body2HighImportance, - color = RadixTheme.colors.gray2 - ) + HorizontalDivider( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = RadixTheme.dimensions.paddingDefault), + color = RadixTheme.colors.gray4 + ) - if (showClaimButton) { - RadixTextButton( - text = stringResource(id = R.string.account_staking_claim), - onClick = onClaimClick, - textStyle = RadixTheme.typography.body2Link - ) - } - } + Text( + modifier = Modifier + .fillMaxWidth() + .padding( + vertical = RadixTheme.dimensions.paddingDefault, + horizontal = RadixTheme.dimensions.paddingMedium + ), + text = stringResource(id = R.string.account_poolUnits_details_currentRedeemableValue), + style = RadixTheme.typography.secondaryHeader, + color = RadixTheme.colors.gray1, + textAlign = TextAlign.Center + ) val fiatPrice = remember(price, item) { price?.xrdPrice(item) } WorthXRD( + modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingMedium), amount = claimState?.amount, fiatPrice = fiatPrice, - isLoadingBalance = isLoadingBalance + isLoadingBalance = isLoadingBalance, + iconSize = 44.dp, + symbolStyle = RadixTheme.typography.body2HighImportance ) - if (claimState is AssetDialogViewModel.State.ClaimState.Unstaking) { - Text( - modifier = Modifier.padding(top = RadixTheme.dimensions.paddingSmall), - text = stringResource(id = R.string.assetDetails_staking_unstaking, claimState.approximateClaimMinutes), - style = RadixTheme.typography.body2HighImportance, - color = RadixTheme.colors.gray2 - ) + when (claimState) { + is AssetDialogViewModel.State.ClaimState.Unstaking -> { + Row( + modifier = Modifier + .padding(top = RadixTheme.dimensions.paddingDefault) + .padding(horizontal = RadixTheme.dimensions.paddingMedium) + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.Top + ) { + Text( + text = stringResource(id = R.string.assetDetails_staking_readyToClaim), + style = RadixTheme.typography.body1Regular, + color = RadixTheme.colors.gray2 + ) + + Text( + text = stringResource(id = R.string.assetDetails_staking_readyToClaimMinutes, claimState.approximateClaimMinutes), + style = RadixTheme.typography.body1HighImportance, + color = RadixTheme.colors.gray1 + ) + } + } + is AssetDialogViewModel.State.ClaimState.ReadyToClaim -> { + if (showClaimButton) { + RadixPrimaryButton( + modifier = Modifier + .padding(top = RadixTheme.dimensions.paddingDefault) + .padding(horizontal = RadixTheme.dimensions.paddingMedium) + .fillMaxWidth(), + text = stringResource(id = R.string.account_staking_readyToBeClaimed), + onClick = onClaimClick + ) + } + } + null -> {} } } } diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/LinkText.kt b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/LinkText.kt index efc8221dfa..557aebcb76 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/LinkText.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/LinkText.kt @@ -77,4 +77,4 @@ fun LinkText( ), textAlign = TextAlign.Start, ) -} \ No newline at end of file +} diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/assets/StakingTab.kt b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/assets/StakingTab.kt index 1abad4e9bc..7154fded5e 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/assets/StakingTab.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/ui/composables/assets/StakingTab.kt @@ -26,6 +26,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.composable.RadixTextButton @@ -714,6 +715,8 @@ fun WorthXRD( amount: Decimal192?, fiatPrice: FiatPrice?, isLoadingBalance: Boolean, + iconSize: Dp = 24.dp, + symbolStyle: TextStyle = RadixTheme.typography.body2HighImportance, trailingContent: @Composable (() -> Unit)? = null ) { Row( @@ -733,15 +736,17 @@ fun WorthXRD( painter = painterResource(id = com.babylon.wallet.android.designsystem.R.drawable.ic_xrd_token), contentDescription = null, modifier = Modifier - .size(24.dp) + .size(iconSize) .clip(RadixTheme.shapes.circle), tint = Color.Unspecified ) Text( - modifier = Modifier.padding(horizontal = RadixTheme.dimensions.paddingSmall), + modifier = Modifier.padding( + horizontal = RadixTheme.dimensions.paddingSmall + ), text = XrdResource.SYMBOL, - style = RadixTheme.typography.body2HighImportance, + style = symbolStyle, color = RadixTheme.colors.gray1, maxLines = 1 ) From 8454eaa40fa8922a7153afc0b2ebdf370d233ab2 Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Fri, 28 Jun 2024 11:24:21 +0300 Subject: [PATCH 16/18] Create global id string using sargon also for MetadataNonFungibleGlobalIdArrayValue --- .../gateway/extensions/EntityMetadataCollectionExtensions.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt index a84e4c8a4b..ace2fbc168 100644 --- a/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt +++ b/app/src/main/java/com/babylon/wallet/android/data/gateway/extensions/EntityMetadataCollectionExtensions.kt @@ -241,7 +241,10 @@ fun EntityMetadataItem.toMetadata(): Metadata? = when (val typed = value.typed) values = typed.propertyValues.map { Metadata.Primitive( key = key, - value = "${it.resourceAddress}:${it.nonFungibleId}", + value = NonFungibleGlobalId( + resourceAddress = ResourceAddress.init(it.resourceAddress), + nonFungibleLocalId = NonFungibleLocalId.init(it.nonFungibleId) + ).string, valueType = MetadataType.NonFungibleGlobalId, isLocked = isLocked ) From 696baae131f4aa94f8dec20e5fa937a6b6c85a02 Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Fri, 28 Jun 2024 12:39:29 +0300 Subject: [PATCH 17/18] Make metadata keys adapt when they are shown in row form --- .../account/composable/MetadataView.kt | 58 ++++++++++++++----- .../status/assets/lsu/LSUDialogContent.kt | 2 - .../NonFungibleAssetDialogContent.kt | 2 - .../assets/pool/PoolUnitDialogContent.kt | 1 - 4 files changed, 43 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt index 916927ba38..693803322b 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/account/composable/MetadataView.kt @@ -1,11 +1,10 @@ package com.babylon.wallet.android.presentation.account.composable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.text.InlineTextContent import androidx.compose.foundation.text.appendInlineContent import androidx.compose.material3.Icon @@ -24,6 +23,9 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.constraintlayout.compose.ConstraintLayout +import androidx.constraintlayout.compose.Dimension import com.babylon.wallet.android.R import com.babylon.wallet.android.designsystem.theme.RadixTheme import com.babylon.wallet.android.presentation.ui.composables.ExpandableText @@ -50,7 +52,7 @@ fun MetadataView( key: String, isLocked: Boolean = false, isRenderedInNewLine: Boolean = false, - valueView: @Composable () -> Unit + valueContent: @Composable () -> Unit ) { if (isRenderedInNewLine) { Column( @@ -58,17 +60,39 @@ fun MetadataView( verticalArrangement = Arrangement.spacedBy(RadixTheme.dimensions.paddingSmall) ) { MetadataKeyView(key = key, isLocked = isLocked) - valueView() + valueContent() } } else { - Row( - modifier = modifier, - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.Top - ) { - MetadataKeyView(key = key, isLocked = isLocked) - Spacer(modifier = Modifier.width(RadixTheme.dimensions.paddingMedium)) - valueView() + ConstraintLayout(modifier = modifier) { + val (keyView, valueView) = createRefs() + + MetadataKeyView( + modifier = Modifier.constrainAs(keyView) { + start.linkTo(parent.start) + top.linkTo(parent.top) + end.linkTo(valueView.start, margin = 12.dp) + width = if (key.length > SHORT_KEY_THRESHOLD) { + Dimension.fillToConstraints + } else { + Dimension.preferredWrapContent + } + height = Dimension.wrapContent + }, + key = key, + isLocked = isLocked + ) + Box( + modifier = Modifier.constrainAs(valueView) { + start.linkTo(keyView.end) + end.linkTo(parent.end) + top.linkTo(parent.top) + width = Dimension.fillToConstraints + height = Dimension.wrapContent + }, + contentAlignment = Alignment.TopEnd + ) { + valueContent() + } } } } @@ -85,6 +109,9 @@ fun MetadataView( isRenderedInNewLine = metadata.isRenderedInNewLine, ) { MetadataValueView( + modifier = Modifier.wrapContentSize( + align = if (metadata.isRenderedInNewLine) Alignment.TopStart else Alignment.TopEnd + ), metadata = metadata, isRenderedInNewLine = metadata.isRenderedInNewLine ) @@ -272,9 +299,10 @@ fun MetadataValueView( } } -private const val ASSET_METADATA_SHORT_STRING_THRESHOLD = 40 +private const val SHORT_KEY_THRESHOLD = 30 +private const val SHORT_VALUE_THRESHOLD = 40 private val Metadata.isRenderedInNewLine: Boolean get() = this is Metadata.Primitive && ( valueType is MetadataType.Url || - (valueType is MetadataType.String && value.length > ASSET_METADATA_SHORT_STRING_THRESHOLD) + (valueType is MetadataType.String && value.length > SHORT_VALUE_THRESHOLD) ) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt index 1b0095c772..6c3af190d8 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/lsu/LSUDialogContent.kt @@ -169,7 +169,6 @@ fun LSUDialogContent( ) { Text( modifier = Modifier - .padding(start = RadixTheme.dimensions.paddingDefault) .widthIn(min = RadixTheme.dimensions.paddingXXXXLarge * 2) .radixPlaceholder(visible = lsu == null), text = lsu?.name().orEmpty(), @@ -187,7 +186,6 @@ fun LSUDialogContent( ) { Text( modifier = Modifier - .padding(start = RadixTheme.dimensions.paddingDefault) .widthIn(min = RadixTheme.dimensions.paddingXXXXLarge * 2) .radixPlaceholder( visible = lsu?.fungibleResource?.currentSupply == null diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt index b92196dcdc..0d8efc719e 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt @@ -122,7 +122,6 @@ fun NonFungibleAssetDialogContent( key = stringResource(id = R.string.assetDetails_NFTDetails_id) ) { ActionableAddressView( - modifier = Modifier.padding(start = RadixTheme.dimensions.paddingDefault), globalId = item.globalId, visitableInDashboard = !isNewlyCreated, textStyle = RadixTheme.typography.body1HighImportance, @@ -243,7 +242,6 @@ fun NonFungibleAssetDialogContent( ) { Text( modifier = Modifier - .padding(start = RadixTheme.dimensions.paddingDefault) .widthIn(min = RadixTheme.dimensions.paddingXXXXLarge * 2) .radixPlaceholder(visible = asset?.resource?.currentSupply == null), text = when { diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt index 978ce17fb9..649689cfaf 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/pool/PoolUnitDialogContent.kt @@ -174,7 +174,6 @@ fun PoolUnitDialogContent( ) { Text( modifier = Modifier - .padding(start = RadixTheme.dimensions.paddingDefault) .widthIn(min = RadixTheme.dimensions.paddingXXXXLarge * 2) .radixPlaceholder(visible = poolUnit?.stake?.currentSupply == null), text = when (val supply = poolUnit?.stake?.currentSupply) { From 11bb8698eb0ba586a7d8625efcbdd0b052ec369a Mon Sep 17 00:00:00 2001 From: micbakos-rdx Date: Fri, 28 Jun 2024 12:54:03 +0300 Subject: [PATCH 18/18] Update strings --- .../assets/nonfungible/NonFungibleAssetDialogContent.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt index 0d8efc719e..039fb21c23 100644 --- a/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt +++ b/app/src/main/java/com/babylon/wallet/android/presentation/status/assets/nonfungible/NonFungibleAssetDialogContent.kt @@ -309,7 +309,7 @@ private fun ClaimNFTInfo( vertical = RadixTheme.dimensions.paddingDefault, horizontal = RadixTheme.dimensions.paddingMedium ), - text = stringResource(id = R.string.account_poolUnits_details_currentRedeemableValue), + text = stringResource(id = R.string.assetDetails_staking_currentRedeemableValue), style = RadixTheme.typography.secondaryHeader, color = RadixTheme.colors.gray1, textAlign = TextAlign.Center @@ -338,13 +338,13 @@ private fun ClaimNFTInfo( verticalAlignment = Alignment.Top ) { Text( - text = stringResource(id = R.string.assetDetails_staking_readyToClaim), + text = stringResource(id = R.string.assetDetails_staking_readyToClaimIn), style = RadixTheme.typography.body1Regular, color = RadixTheme.colors.gray2 ) Text( - text = stringResource(id = R.string.assetDetails_staking_readyToClaimMinutes, claimState.approximateClaimMinutes), + text = stringResource(id = R.string.assetDetails_staking_readyToClaimInMinutes, claimState.approximateClaimMinutes), style = RadixTheme.typography.body1HighImportance, color = RadixTheme.colors.gray1 ) @@ -357,7 +357,7 @@ private fun ClaimNFTInfo( .padding(top = RadixTheme.dimensions.paddingDefault) .padding(horizontal = RadixTheme.dimensions.paddingMedium) .fillMaxWidth(), - text = stringResource(id = R.string.account_staking_readyToBeClaimed), + text = stringResource(id = R.string.assetDetails_staking_readyToClaim), onClick = onClaimClick ) }