mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-07-22 19:35:51 +00:00
Add a Pending Signatures card to the wallet home screen
Surfaces multisig operations awaiting the current signatory's own approval directly on the main balance screen, instead of requiring navigation to the separate pending-operations list. Each row shows the formatted amount, destination, chain, and approval progress, with a red Sign button that opens the existing operation-details/approve flow (fee estimation, signatory balance check, and validation are all already handled there - not reimplemented here). Reuses the already-tested MultisigCallFormatter from feature-multisig:operations (added as a new feature-assets dependency, exposed via the standard FeatureApi/FeatureContainer pattern - see AssetsFeatureHolder/AssetsFeatureComponent/AssetsFeatureDependencies) rather than re-deriving call-preview formatting independently. The card follows the same SingleItemAdapter + ConcatAdapter pattern as the existing Pezkuwi Dashboard card on the same screen. Once a pending operation is actually signed, it naturally drops off this list on the next sync (no separate client-side "signed" state is tracked in parallel with the real on-chain approval status). String only added to the base (English) strings.xml for now - not yet translated into the other ~14 locales this app otherwise maintains.
This commit is contained in:
@@ -48,6 +48,7 @@ dependencies {
|
||||
implementation project(':feature-deep-linking')
|
||||
implementation project(':feature-ahm-api')
|
||||
implementation project(':feature-gift-api')
|
||||
implementation project(':feature-multisig:operations')
|
||||
|
||||
implementation kotlinDep
|
||||
|
||||
|
||||
+3
-1
@@ -53,6 +53,7 @@ import io.novafoundation.nova.feature_crowdloan_api.di.CrowdloanFeatureApi
|
||||
import io.novafoundation.nova.feature_currency_api.di.CurrencyFeatureApi
|
||||
import io.novafoundation.nova.feature_deep_linking.di.DeepLinkingFeatureApi
|
||||
import io.novafoundation.nova.feature_gift_api.di.GiftFeatureApi
|
||||
import io.novafoundation.nova.feature_multisig_operations.di.MultisigOperationsFeatureApi
|
||||
import io.novafoundation.nova.feature_nft_api.NftFeatureApi
|
||||
import io.novafoundation.nova.feature_staking_api.di.StakingFeatureApi
|
||||
import io.novafoundation.nova.feature_swap_api.di.SwapFeatureApi
|
||||
@@ -175,7 +176,8 @@ interface AssetsFeatureComponent : AssetsFeatureApi {
|
||||
BannersFeatureApi::class,
|
||||
DeepLinkingFeatureApi::class,
|
||||
ChainMigrationFeatureApi::class,
|
||||
GiftFeatureApi::class
|
||||
GiftFeatureApi::class,
|
||||
MultisigOperationsFeatureApi::class
|
||||
]
|
||||
)
|
||||
interface AssetsFeatureDependenciesComponent : AssetsFeatureDependencies
|
||||
|
||||
+3
@@ -99,6 +99,7 @@ import io.novafoundation.nova.feature_account_api.data.fee.capability.CustomFeeC
|
||||
import io.novafoundation.nova.feature_ahm_api.domain.ChainMigrationInfoUseCase
|
||||
import io.novafoundation.nova.feature_gift_api.domain.GiftsAccountSupportedUseCase
|
||||
import io.novafoundation.nova.feature_gift_api.domain.AvailableGiftAssetsUseCase
|
||||
import io.novafoundation.nova.feature_multisig_operations.presentation.callFormatting.MultisigCallFormatter
|
||||
import io.novafoundation.nova.feature_wallet_api.domain.SendUseCase
|
||||
import io.novafoundation.nova.feature_wallet_api.presentation.mixin.amountChooser.AmountChooserMixin
|
||||
import io.novafoundation.nova.feature_wallet_api.presentation.mixin.fee.FeeLoaderMixin
|
||||
@@ -240,6 +241,8 @@ interface AssetsFeatureDependencies {
|
||||
|
||||
val multisigPendingOperationsService: MultisigPendingOperationsService
|
||||
|
||||
val multisigCallFormatter: MultisigCallFormatter
|
||||
|
||||
val automaticInteractionGate: AutomaticInteractionGate
|
||||
|
||||
val linkBuilderFactory: LinkBuilderFactory
|
||||
|
||||
+2
@@ -15,6 +15,7 @@ import io.novafoundation.nova.feature_crowdloan_api.di.CrowdloanFeatureApi
|
||||
import io.novafoundation.nova.feature_currency_api.di.CurrencyFeatureApi
|
||||
import io.novafoundation.nova.feature_deep_linking.di.DeepLinkingFeatureApi
|
||||
import io.novafoundation.nova.feature_gift_api.di.GiftFeatureApi
|
||||
import io.novafoundation.nova.feature_multisig_operations.di.MultisigOperationsFeatureApi
|
||||
import io.novafoundation.nova.feature_nft_api.NftFeatureApi
|
||||
import io.novafoundation.nova.feature_staking_api.di.StakingFeatureApi
|
||||
import io.novafoundation.nova.feature_swap_api.di.SwapFeatureApi
|
||||
@@ -51,6 +52,7 @@ class AssetsFeatureHolder @Inject constructor(
|
||||
.deepLinkingFeatureApi(getFeature(DeepLinkingFeatureApi::class.java))
|
||||
.chainMigrationFeatureApi(getFeature(ChainMigrationFeatureApi::class.java))
|
||||
.giftFeatureApi(getFeature(GiftFeatureApi::class.java))
|
||||
.multisigOperationsFeatureApi(getFeature(MultisigOperationsFeatureApi::class.java))
|
||||
.build()
|
||||
|
||||
return DaggerAssetsFeatureComponent.factory()
|
||||
|
||||
+3
@@ -11,6 +11,7 @@ import io.novafoundation.nova.feature_assets.presentation.tokens.add.enterInfo.A
|
||||
import io.novafoundation.nova.feature_assets.presentation.tokens.manage.chain.ManageChainTokensPayload
|
||||
import io.novafoundation.nova.feature_assets.presentation.trade.webInterface.TradeWebPayload
|
||||
import io.novafoundation.nova.feature_assets.presentation.transaction.filter.TransactionHistoryFilterPayload
|
||||
import io.novafoundation.nova.feature_multisig_operations.presentation.details.general.MultisigOperationDetailsPayload
|
||||
import io.novafoundation.nova.feature_swap_api.presentation.model.SwapSettingsPayload
|
||||
import io.novafoundation.nova.feature_wallet_api.presentation.model.AssetPayload
|
||||
|
||||
@@ -120,6 +121,8 @@ interface AssetsRouter {
|
||||
|
||||
fun openPendingMultisigOperations()
|
||||
|
||||
fun openMultisigOperationDetails(payload: MultisigOperationDetailsPayload)
|
||||
|
||||
fun openAssetDetailsFromDeepLink(payload: AssetPayload)
|
||||
|
||||
fun openGifts()
|
||||
|
||||
+31
-1
@@ -36,6 +36,9 @@ import android.content.Intent
|
||||
import android.widget.Toast
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.PezkuwiDashboardAdapter
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.PezkuwiDashboardHolder
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.PendingSignaturesAdapter
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.PendingSignaturesHolder
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.model.PendingSignatureModel
|
||||
import io.novafoundation.nova.feature_assets.presentation.citizenship.CitizenshipBottomSheet
|
||||
import io.novafoundation.nova.feature_banners_api.presentation.BannerHolder
|
||||
import io.novafoundation.nova.feature_banners_api.presentation.PromotionBannerAdapter
|
||||
@@ -49,6 +52,7 @@ class BalanceListFragment :
|
||||
AssetsHeaderAdapter.Handler,
|
||||
ManageAssetsAdapter.Handler,
|
||||
PezkuwiDashboardAdapter.Handler,
|
||||
PendingSignaturesAdapter.Handler,
|
||||
CitizenshipBottomSheet.CitizenshipDismissListener {
|
||||
|
||||
override fun createBinding() = FragmentBalanceListBinding.inflate(layoutInflater)
|
||||
@@ -66,6 +70,10 @@ class BalanceListFragment :
|
||||
PezkuwiDashboardAdapter(this)
|
||||
}
|
||||
|
||||
private val pendingSignaturesAdapter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
PendingSignaturesAdapter(imageLoader, this)
|
||||
}
|
||||
|
||||
private val bannerAdapter: PromotionBannerAdapter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
PromotionBannerAdapter(closable = true)
|
||||
}
|
||||
@@ -86,7 +94,15 @@ class BalanceListFragment :
|
||||
}
|
||||
|
||||
private val adapter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
ConcatAdapter(headerAdapter, pezkuwiDashboardAdapter, bannerAdapter, manageAssetsAdapter, emptyAssetsPlaceholder, assetsAdapter)
|
||||
ConcatAdapter(
|
||||
headerAdapter,
|
||||
pezkuwiDashboardAdapter,
|
||||
pendingSignaturesAdapter,
|
||||
bannerAdapter,
|
||||
manageAssetsAdapter,
|
||||
emptyAssetsPlaceholder,
|
||||
assetsAdapter
|
||||
)
|
||||
}
|
||||
|
||||
override fun applyInsets(rootView: View) {
|
||||
@@ -143,6 +159,11 @@ class BalanceListFragment :
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.pendingSignaturesFlow.observe { models ->
|
||||
pendingSignaturesAdapter.setModels(models)
|
||||
pendingSignaturesAdapter.show(models.isNotEmpty())
|
||||
}
|
||||
|
||||
viewModel.bannersMixin.bindWithAdapter(bannerAdapter) {
|
||||
binder.balanceListAssets.invalidateItemDecorations()
|
||||
}
|
||||
@@ -301,6 +322,10 @@ class BalanceListFragment :
|
||||
viewModel.startTrackingClicked()
|
||||
}
|
||||
|
||||
override fun onSignClicked(model: PendingSignatureModel) {
|
||||
viewModel.pendingSignatureSignClicked(model)
|
||||
}
|
||||
|
||||
private fun setupRecyclerViewSpacing() {
|
||||
binder.balanceListAssets.addSpaceItemDecoration {
|
||||
add(SpaceBetween(AssetsHeaderHolder, PezkuwiDashboardHolder, spaceDp = 8))
|
||||
@@ -309,6 +334,11 @@ class BalanceListFragment :
|
||||
add(SpaceBetween(AssetsHeaderHolder, BannerHolder, spaceDp = 4))
|
||||
add(SpaceBetween(BannerHolder, ManageAssetsHolder, spaceDp = 4))
|
||||
add(SpaceBetween(AssetsHeaderHolder, ManageAssetsHolder, spaceDp = 24))
|
||||
|
||||
add(SpaceBetween(AssetsHeaderHolder, PendingSignaturesHolder, spaceDp = 8))
|
||||
add(SpaceBetween(PezkuwiDashboardHolder, PendingSignaturesHolder, spaceDp = 8))
|
||||
add(SpaceBetween(PendingSignaturesHolder, BannerHolder, spaceDp = 4))
|
||||
add(SpaceBetween(PendingSignaturesHolder, ManageAssetsHolder, spaceDp = 24))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
@@ -20,10 +20,15 @@ import io.novafoundation.nova.common.utils.formatting.formatAsPercentage
|
||||
import io.novafoundation.nova.common.utils.inBackground
|
||||
import io.novafoundation.nova.common.utils.launchUnit
|
||||
import io.novafoundation.nova.common.utils.withSafeLoading
|
||||
import io.novafoundation.nova.feature_account_api.data.mappers.mapChainToUi
|
||||
import io.novafoundation.nova.feature_account_api.data.multisig.MultisigPendingOperationsService
|
||||
import io.novafoundation.nova.feature_account_api.data.multisig.model.MultisigAction
|
||||
import io.novafoundation.nova.feature_account_api.data.multisig.model.PendingMultisigOperation
|
||||
import io.novafoundation.nova.feature_account_api.data.multisig.model.userAction
|
||||
import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase
|
||||
import io.novafoundation.nova.feature_account_api.domain.model.MetaAccount
|
||||
import io.novafoundation.nova.feature_account_api.domain.model.defaultSubstrateAddress
|
||||
import io.novafoundation.nova.feature_account_api.domain.model.requireAccountIdKeyIn
|
||||
import io.novafoundation.nova.feature_assets.R
|
||||
import io.novafoundation.nova.feature_assets.domain.WalletInteractor
|
||||
import io.novafoundation.nova.feature_assets.domain.assets.list.AssetsListInteractor
|
||||
@@ -42,6 +47,7 @@ import io.novafoundation.nova.feature_assets.presentation.balance.common.buySell
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.common.buySell.BuySellSelectorMixinFactory
|
||||
import io.novafoundation.nova.feature_assets.presentation.citizenship.PendingCitizenshipReferrer
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.model.NftPreviewUi
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.model.PendingSignatureModel
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.model.TotalBalanceModel
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.AssetViewModeModel
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.PendingOperationsCountModel
|
||||
@@ -52,6 +58,10 @@ import io.novafoundation.nova.feature_banners_api.presentation.source.assetsSour
|
||||
import io.novafoundation.nova.feature_currency_api.domain.CurrencyInteractor
|
||||
import io.novafoundation.nova.feature_currency_api.domain.model.Currency
|
||||
import io.novafoundation.nova.feature_currency_api.presentation.formatters.formatAsCurrency
|
||||
import io.novafoundation.nova.feature_multisig_operations.presentation.callFormatting.MultisigCallFormatter
|
||||
import io.novafoundation.nova.feature_multisig_operations.presentation.common.MultisigOperationPayload
|
||||
import io.novafoundation.nova.feature_multisig_operations.presentation.common.fromOperationId
|
||||
import io.novafoundation.nova.feature_multisig_operations.presentation.details.general.MultisigOperationDetailsPayload
|
||||
import io.novafoundation.nova.feature_nft_api.data.model.Nft
|
||||
import io.novafoundation.nova.feature_swap_api.domain.interactor.SwapAvailabilityInteractor
|
||||
import io.novafoundation.nova.feature_wallet_api.presentation.formatters.amount.AmountFormatter
|
||||
@@ -108,6 +118,7 @@ class BalanceListViewModel(
|
||||
private val maskableValueFormatterProvider: MaskableValueFormatterProvider,
|
||||
private val buySellSelectorMixinFactory: BuySellSelectorMixinFactory,
|
||||
private val multisigPendingOperationsService: MultisigPendingOperationsService,
|
||||
private val multisigCallFormatter: MultisigCallFormatter,
|
||||
private val novaCardRestrictionCheckMixin: NovaCardRestrictionCheckMixin,
|
||||
private val maskingModeUseCase: MaskingModeUseCase,
|
||||
private val giftsRestrictionCheckMixin: GiftsRestrictionCheckMixin,
|
||||
@@ -248,6 +259,38 @@ class BalanceListViewModel(
|
||||
.combine(maskableAmountFormatterFlow, ::formatPendingOperationsCount)
|
||||
.shareInBackground()
|
||||
|
||||
val pendingSignaturesFlow = multisigPendingOperationsService.pendingOperations()
|
||||
.mapLatest { operations ->
|
||||
val account = selectedMetaAccount.first()
|
||||
|
||||
// Only operations still awaiting THIS signatory's own approval - once signed, the
|
||||
// item naturally drops out here on next sync (no client-side "turn green" state to
|
||||
// maintain in parallel with the real, authoritative on-chain approval status).
|
||||
operations
|
||||
.filter { it.userAction() is MultisigAction.CanApprove }
|
||||
.map { it.toPendingSignatureUi(account) }
|
||||
}
|
||||
.shareInBackground()
|
||||
|
||||
fun pendingSignatureSignClicked(model: PendingSignatureModel) {
|
||||
val operationPayload = MultisigOperationPayload.fromOperationId(model.id)
|
||||
router.openMultisigOperationDetails(MultisigOperationDetailsPayload(operationPayload))
|
||||
}
|
||||
|
||||
private suspend fun PendingMultisigOperation.toPendingSignatureUi(selectedAccount: MetaAccount): PendingSignatureModel {
|
||||
val initialOrigin = selectedAccount.requireAccountIdKeyIn(chain)
|
||||
val formattedCall = multisigCallFormatter.formatPreview(call, initialOrigin, chain)
|
||||
|
||||
return PendingSignatureModel(
|
||||
id = operationId,
|
||||
chain = mapChainToUi(chain),
|
||||
title = formattedCall.title,
|
||||
subtitle = formattedCall.subtitle,
|
||||
primaryValue = formattedCall.primaryValue,
|
||||
progress = resourceManager.getString(R.string.multisig_operations_progress, approvals.size.format(), threshold.format())
|
||||
)
|
||||
}
|
||||
|
||||
val pezkuwiDashboardFlow = selectedMetaAccount
|
||||
.combine(dashboardRefreshSignal) { account, _ -> account }
|
||||
.mapLatest { metaAccount ->
|
||||
|
||||
+3
@@ -13,6 +13,7 @@ import io.novafoundation.nova.common.di.viewmodel.ViewModelModule
|
||||
import io.novafoundation.nova.common.domain.usecase.MaskingModeUseCase
|
||||
import io.novafoundation.nova.common.resources.ResourceManager
|
||||
import io.novafoundation.nova.feature_account_api.data.multisig.MultisigPendingOperationsService
|
||||
import io.novafoundation.nova.feature_multisig_operations.presentation.callFormatting.MultisigCallFormatter
|
||||
import io.novafoundation.nova.feature_account_api.domain.interfaces.AccountRepository
|
||||
import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase
|
||||
import io.novafoundation.nova.feature_assets.data.repository.PezkuwiDashboardRepository
|
||||
@@ -122,6 +123,7 @@ class BalanceListModule {
|
||||
amountFormatter: AmountFormatter,
|
||||
buySellSelectorMixinFactory: BuySellSelectorMixinFactory,
|
||||
multisigPendingOperationsService: MultisigPendingOperationsService,
|
||||
multisigCallFormatter: MultisigCallFormatter,
|
||||
novaCardRestrictionCheckMixin: NovaCardRestrictionCheckMixin,
|
||||
maskableValueFormatterProvider: MaskableValueFormatterProvider,
|
||||
maskingModeUseCase: MaskingModeUseCase,
|
||||
@@ -148,6 +150,7 @@ class BalanceListModule {
|
||||
maskableValueFormatterProvider = maskableValueFormatterProvider,
|
||||
buySellSelectorMixinFactory = buySellSelectorMixinFactory,
|
||||
multisigPendingOperationsService = multisigPendingOperationsService,
|
||||
multisigCallFormatter = multisigCallFormatter,
|
||||
novaCardRestrictionCheckMixin = novaCardRestrictionCheckMixin,
|
||||
maskingModeUseCase = maskingModeUseCase,
|
||||
fiatFormatter = fiatFormatter,
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package io.novafoundation.nova.feature_assets.presentation.balance.list.model
|
||||
|
||||
import io.novafoundation.nova.feature_account_api.data.multisig.model.PendingMultisigOperationId
|
||||
import io.novafoundation.nova.feature_account_api.presenatation.chain.ChainUi
|
||||
|
||||
data class PendingSignatureModel(
|
||||
val id: PendingMultisigOperationId,
|
||||
val chain: ChainUi,
|
||||
val title: String,
|
||||
val subtitle: String?,
|
||||
val primaryValue: CharSequence?,
|
||||
val progress: String,
|
||||
)
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package io.novafoundation.nova.feature_assets.presentation.balance.list.view
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import coil.ImageLoader
|
||||
import io.novafoundation.nova.common.list.SingleItemAdapter
|
||||
import io.novafoundation.nova.common.utils.inflater
|
||||
import io.novafoundation.nova.common.utils.recyclerView.WithViewType
|
||||
import io.novafoundation.nova.feature_account_api.presenatation.chain.loadChainIcon
|
||||
import io.novafoundation.nova.feature_assets.R
|
||||
import io.novafoundation.nova.feature_assets.databinding.ItemPendingSignatureRowBinding
|
||||
import io.novafoundation.nova.feature_assets.databinding.ItemPendingSignaturesCardBinding
|
||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.model.PendingSignatureModel
|
||||
|
||||
class PendingSignaturesAdapter(
|
||||
private val imageLoader: ImageLoader,
|
||||
private val handler: Handler
|
||||
) : SingleItemAdapter<PendingSignaturesHolder>(isShownByDefault = false) {
|
||||
|
||||
interface Handler {
|
||||
fun onSignClicked(model: PendingSignatureModel)
|
||||
}
|
||||
|
||||
private var models: List<PendingSignatureModel> = emptyList()
|
||||
|
||||
fun setModels(models: List<PendingSignatureModel>) {
|
||||
this.models = models
|
||||
notifyChangedIfShown()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PendingSignaturesHolder {
|
||||
val binding = ItemPendingSignaturesCardBinding.inflate(parent.inflater(), parent, false)
|
||||
return PendingSignaturesHolder(binding, imageLoader, handler)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PendingSignaturesHolder, position: Int) {
|
||||
holder.bind(models)
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return PendingSignaturesHolder.viewType
|
||||
}
|
||||
}
|
||||
|
||||
class PendingSignaturesHolder(
|
||||
private val binder: ItemPendingSignaturesCardBinding,
|
||||
private val imageLoader: ImageLoader,
|
||||
private val handler: PendingSignaturesAdapter.Handler
|
||||
) : RecyclerView.ViewHolder(binder.root) {
|
||||
|
||||
companion object : WithViewType {
|
||||
override val viewType: Int = R.layout.item_pending_signatures_card
|
||||
}
|
||||
|
||||
fun bind(models: List<PendingSignatureModel>) {
|
||||
val container = binder.pendingSignaturesRowsContainer
|
||||
container.removeAllViews()
|
||||
|
||||
models.forEach { model ->
|
||||
val rowBinding = ItemPendingSignatureRowBinding.inflate(container.inflater(), container, false)
|
||||
|
||||
rowBinding.pendingSignatureChainIcon.loadChainIcon(model.chain.icon, imageLoader)
|
||||
// primaryValue (e.g. "100K USDT") is the amount - the whole point of this card - so it
|
||||
// takes the prominent title line; the call's own title/action name ("Transfer") isn't
|
||||
// shown at all here, only the destination (subtitle) is, to keep the row to two lines.
|
||||
rowBinding.pendingSignatureTitle.text = model.primaryValue ?: model.title
|
||||
rowBinding.pendingSignatureSubtitle.text = listOfNotNull(model.subtitle, model.chain.name, model.progress)
|
||||
.joinToString(separator = " • ")
|
||||
rowBinding.pendingSignatureSignButton.setOnClickListener { handler.onSignClicked(model) }
|
||||
|
||||
container.addView(rowBinding.root)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pendingSignatureChainIcon"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_fallback_network_icon" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pendingSignatureTitle"
|
||||
style="@style/TextAppearance.NovaFoundation.SemiBold.Caption1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textColor="@color/text_primary"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toTopOf="@+id/pendingSignatureSubtitle"
|
||||
app:layout_constraintEnd_toStartOf="@+id/pendingSignatureSignButton"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintStart_toEndOf="@+id/pendingSignatureChainIcon"
|
||||
app:layout_constraintTop_toTopOf="@+id/pendingSignatureChainIcon"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="100K USDT" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pendingSignatureSubtitle"
|
||||
style="@style/TextAppearance.NovaFoundation.Regular.Caption2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="middle"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/text_secondary"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/pendingSignatureChainIcon"
|
||||
app:layout_constraintEnd_toStartOf="@+id/pendingSignatureSignButton"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintStart_toStartOf="@+id/pendingSignatureTitle"
|
||||
app:layout_constraintTop_toBottomOf="@+id/pendingSignatureTitle"
|
||||
tools:text="Polkadot Asset Hub • 2/3" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/pendingSignatureSignButton"
|
||||
style="@style/Widget.Nova.MaterialButton.Negative"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="36dp"
|
||||
android:minWidth="0dp"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:text="@string/pending_signatures_sign"
|
||||
android:textSize="13sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
app:cardBackgroundColor="@android:color/transparent"
|
||||
app:cardCornerRadius="20dp"
|
||||
app:cardElevation="0dp"
|
||||
app:strokeWidth="0dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_pezkuwi_dashboard"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="12dp">
|
||||
|
||||
<TextView
|
||||
style="@style/TextAppearance.NovaFoundation.SemiBold.Caption1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:text="@string/pending_signatures_title"
|
||||
android:textColor="@color/text_secondary" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/pendingSignaturesRowsContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
Reference in New Issue
Block a user