Move Pending Signatures from the wallet home screen to the Bridge screen

Wrong screen in the previous commit - moved it to sit right below the
existing per-leg renewal sign buttons on the Bridge input screen, which
is where it was actually asked for: a signatory renewing their own
wUSDT/Polkadot USDT allowance there should also see (and be able to
jump to) other pending multisig operations - e.g. someone else's large
bridge swap - waiting on their signature, without navigating elsewhere.

BalanceListFragment/ViewModel/Module are reverted to their prior state.
The reusable pieces (PendingSignatureModel, item_pending_signature_row
layout) are kept and repurposed for the Bridge screen; the RecyclerView
SingleItemAdapter/card layout built for the home screen are removed
since Bridge is a plain (non-RecyclerView) fragment - rows are inflated
directly into a LinearLayout container instead, same underlying data
and MultisigCallFormatter reuse as before.

The feature-assets -> feature-multisig:operations dependency and the
FeatureApi wiring (AssetsFeatureComponent/Dependencies/Holder) from the
previous commit stay as-is - Bridge is the same Gradle module, so no
change needed there.
This commit is contained in:
2026-07-17 14:43:18 -07:00
parent 707d1baba4
commit 6f14c8bf05
10 changed files with 124 additions and 187 deletions
@@ -36,9 +36,6 @@ 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
@@ -52,7 +49,6 @@ class BalanceListFragment :
AssetsHeaderAdapter.Handler,
ManageAssetsAdapter.Handler,
PezkuwiDashboardAdapter.Handler,
PendingSignaturesAdapter.Handler,
CitizenshipBottomSheet.CitizenshipDismissListener {
override fun createBinding() = FragmentBalanceListBinding.inflate(layoutInflater)
@@ -70,10 +66,6 @@ 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)
}
@@ -94,15 +86,7 @@ class BalanceListFragment :
}
private val adapter by lazy(LazyThreadSafetyMode.NONE) {
ConcatAdapter(
headerAdapter,
pezkuwiDashboardAdapter,
pendingSignaturesAdapter,
bannerAdapter,
manageAssetsAdapter,
emptyAssetsPlaceholder,
assetsAdapter
)
ConcatAdapter(headerAdapter, pezkuwiDashboardAdapter, bannerAdapter, manageAssetsAdapter, emptyAssetsPlaceholder, assetsAdapter)
}
override fun applyInsets(rootView: View) {
@@ -159,11 +143,6 @@ class BalanceListFragment :
}
}
viewModel.pendingSignaturesFlow.observe { models ->
pendingSignaturesAdapter.setModels(models)
pendingSignaturesAdapter.show(models.isNotEmpty())
}
viewModel.bannersMixin.bindWithAdapter(bannerAdapter) {
binder.balanceListAssets.invalidateItemDecorations()
}
@@ -322,10 +301,6 @@ class BalanceListFragment :
viewModel.startTrackingClicked()
}
override fun onSignClicked(model: PendingSignatureModel) {
viewModel.pendingSignatureSignClicked(model)
}
private fun setupRecyclerViewSpacing() {
binder.balanceListAssets.addSpaceItemDecoration {
add(SpaceBetween(AssetsHeaderHolder, PezkuwiDashboardHolder, spaceDp = 8))
@@ -334,11 +309,6 @@ 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))
}
}
@@ -20,15 +20,10 @@ 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
@@ -47,7 +42,6 @@ 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
@@ -58,10 +52,6 @@ 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
@@ -118,7 +108,6 @@ 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,
@@ -259,38 +248,6 @@ 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 ->
@@ -13,7 +13,6 @@ 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
@@ -123,7 +122,6 @@ class BalanceListModule {
amountFormatter: AmountFormatter,
buySellSelectorMixinFactory: BuySellSelectorMixinFactory,
multisigPendingOperationsService: MultisigPendingOperationsService,
multisigCallFormatter: MultisigCallFormatter,
novaCardRestrictionCheckMixin: NovaCardRestrictionCheckMixin,
maskableValueFormatterProvider: MaskableValueFormatterProvider,
maskingModeUseCase: MaskingModeUseCase,
@@ -150,7 +148,6 @@ class BalanceListModule {
maskableValueFormatterProvider = maskableValueFormatterProvider,
buySellSelectorMixinFactory = buySellSelectorMixinFactory,
multisigPendingOperationsService = multisigPendingOperationsService,
multisigCallFormatter = multisigCallFormatter,
novaCardRestrictionCheckMixin = novaCardRestrictionCheckMixin,
maskingModeUseCase = maskingModeUseCase,
fiatFormatter = fiatFormatter,
@@ -1,74 +0,0 @@
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)
}
}
}
@@ -3,19 +3,27 @@ package io.novafoundation.nova.feature_assets.presentation.bridge
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import coil.ImageLoader
import io.novafoundation.nova.common.base.BaseFragment
import io.novafoundation.nova.common.di.FeatureUtils
import io.novafoundation.nova.common.utils.inflater
import io.novafoundation.nova.common.utils.setVisible
import io.novafoundation.nova.common.view.AlertView
import io.novafoundation.nova.common.view.setState
import io.novafoundation.nova.feature_account_api.presenatation.chain.loadChainIcon
import io.novafoundation.nova.feature_assets.R
import io.novafoundation.nova.feature_assets.databinding.FragmentBridgeBinding
import io.novafoundation.nova.feature_assets.databinding.ItemPendingSignatureRowBinding
import io.novafoundation.nova.feature_assets.di.AssetsFeatureApi
import io.novafoundation.nova.feature_assets.di.AssetsFeatureComponent
import io.novafoundation.nova.feature_wallet_api.presentation.mixin.amountChooser.MaxActionAvailability
import javax.inject.Inject
class BridgeFragment : BaseFragment<BridgeViewModel, FragmentBridgeBinding>() {
@Inject
lateinit var imageLoader: ImageLoader
override fun createBinding() = FragmentBridgeBinding.inflate(layoutInflater)
override fun initViews() {
@@ -196,6 +204,34 @@ class BridgeFragment : BaseFragment<BridgeViewModel, FragmentBridgeBinding>() {
viewModel.fillAmountEvent.observeEvent { amount ->
binder.bridgeFromCard.amountInput.setText(amount)
}
viewModel.pendingSignatures.observe { models ->
bindPendingSignatures(models)
}
}
private fun bindPendingSignatures(models: List<PendingSignatureModel>) {
val visibility = if (models.isEmpty()) View.GONE else View.VISIBLE
binder.bridgePendingSignaturesTitle.visibility = visibility
binder.bridgePendingSignaturesContainer.visibility = visibility
val container = binder.bridgePendingSignaturesContainer
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 row - 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 { viewModel.pendingSignatureSignClicked(model) }
container.addView(rowBinding.root)
}
}
}
@@ -6,8 +6,17 @@ import io.novafoundation.nova.common.base.BaseViewModel
import io.novafoundation.nova.common.presentation.AssetIconProvider
import io.novafoundation.nova.common.resources.ResourceManager
import io.novafoundation.nova.common.utils.Event
import io.novafoundation.nova.common.utils.formatting.format
import io.novafoundation.nova.common.utils.images.Icon
import io.novafoundation.nova.common.view.ButtonState
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.requireAccountIdKeyIn
import io.novafoundation.nova.feature_account_api.presenatation.chain.getAssetIconOrFallback
import io.novafoundation.nova.feature_assets.R
import io.novafoundation.nova.feature_assets.domain.WalletInteractor
@@ -16,12 +25,17 @@ import io.novafoundation.nova.feature_assets.domain.bridge.multisig.BridgeMultis
import io.novafoundation.nova.feature_assets.domain.bridge.multisig.BridgeSignerState
import io.novafoundation.nova.feature_assets.presentation.AssetsRouter
import io.novafoundation.nova.feature_assets.presentation.bridge.execution.BridgeExecutionPayload
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.runtime.ext.ChainGeneses
import io.novafoundation.nova.runtime.ext.addressOf
import io.novafoundation.nova.runtime.ext.displayNameWithAssetStandard
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
import io.novasama.substrate_sdk_android.ss58.SS58Encoder.toAccountId
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import java.math.BigDecimal
import java.math.RoundingMode
@@ -48,6 +62,9 @@ class BridgeViewModel(
private val assetIconProvider: AssetIconProvider,
private val walletInteractor: WalletInteractor,
private val bridgeMultisigInteractor: BridgeMultisigInteractor,
private val multisigPendingOperationsService: MultisigPendingOperationsService,
private val multisigCallFormatter: MultisigCallFormatter,
private val selectedAccountUseCase: SelectedAccountUseCase,
) : BaseViewModel() {
companion object {
@@ -130,6 +147,15 @@ class BridgeViewModel(
private val _polkadotSignButtonLabel = MutableLiveData("")
val polkadotSignButtonLabel: LiveData<String> = _polkadotSignButtonLabel
/** Multisig operations (any of them - not just bridge swaps, since a signatory of this bridge
* account may also be a signatory of other multisig accounts) still awaiting this wallet's
* own approval - shown below the renewal sign buttons above so a signatory doesn't have to
* separately navigate to the pending-operations list to find and sign a swap someone else
* submitted (see the "Sign" buttons above, which renew this wallet's own on-chain allowance -
* this is a different, complementary concern: approving *other people's* pending calls). */
private val _pendingSignatures = MutableLiveData<List<PendingSignatureModel>>(emptyList())
val pendingSignatures: LiveData<List<PendingSignatureModel>> = _pendingSignatures
private val _fromCard = MutableLiveData<BridgeAssetCardUi>()
val fromCard: LiveData<BridgeAssetCardUi> = _fromCard
@@ -452,6 +478,38 @@ class BridgeViewModel(
fun refreshBridgeStatus() {
fetchReserveStatus()
refreshSignerState()
refreshPendingSignatures()
}
fun refreshPendingSignatures() {
launch {
val account = selectedAccountUseCase.getSelectedMetaAccount()
val models = multisigPendingOperationsService.pendingOperations().first()
.filter { it.userAction() is MultisigAction.CanApprove }
.map { it.toPendingSignatureUi(account) }
_pendingSignatures.postValue(models)
}
}
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())
)
}
fun refreshSignerState() {
@@ -1,4 +1,4 @@
package io.novafoundation.nova.feature_assets.presentation.balance.list.model
package io.novafoundation.nova.feature_assets.presentation.bridge
import io.novafoundation.nova.feature_account_api.data.multisig.model.PendingMultisigOperationId
import io.novafoundation.nova.feature_account_api.presenatation.chain.ChainUi
@@ -11,12 +11,14 @@ import io.novafoundation.nova.common.di.viewmodel.ViewModelModule
import io.novafoundation.nova.common.presentation.AssetIconProvider
import io.novafoundation.nova.common.resources.ResourceManager
import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService
import io.novafoundation.nova.feature_account_api.data.multisig.MultisigPendingOperationsService
import io.novafoundation.nova.feature_account_api.domain.interfaces.SelectedAccountUseCase
import io.novafoundation.nova.feature_assets.domain.WalletInteractor
import io.novafoundation.nova.feature_assets.domain.bridge.multisig.BridgeMultisigInteractor
import io.novafoundation.nova.feature_assets.domain.bridge.multisig.RealBridgeMultisigInteractor
import io.novafoundation.nova.feature_assets.presentation.AssetsRouter
import io.novafoundation.nova.feature_assets.presentation.bridge.BridgeViewModel
import io.novafoundation.nova.feature_multisig_operations.presentation.callFormatting.MultisigCallFormatter
import io.novafoundation.nova.runtime.di.REMOTE_STORAGE_SOURCE
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
import io.novafoundation.nova.runtime.storage.source.StorageDataSource
@@ -45,6 +47,9 @@ class BridgeModule {
assetIconProvider: AssetIconProvider,
walletInteractor: WalletInteractor,
bridgeMultisigInteractor: BridgeMultisigInteractor,
multisigPendingOperationsService: MultisigPendingOperationsService,
multisigCallFormatter: MultisigCallFormatter,
selectedAccountUseCase: SelectedAccountUseCase,
): ViewModel {
return BridgeViewModel(
router,
@@ -53,6 +58,9 @@ class BridgeModule {
assetIconProvider,
walletInteractor,
bridgeMultisigInteractor,
multisigPendingOperationsService,
multisigCallFormatter,
selectedAccountUseCase,
)
}
@@ -214,6 +214,26 @@
android:text="@string/bridge_sign_button"
android:visibility="gone" />
<!-- Pending multisig operations awaiting this signatory's own approval (someone
else's swap, not this wallet's own renewal above) - one row per operation,
populated dynamically, see BridgeViewModel.pendingSignatures. -->
<TextView
android:id="@+id/bridgePendingSignaturesTitle"
style="@style/TextAppearance.NovaFoundation.SemiBold.Caption1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/pending_signatures_title"
android:textColor="@color/text_secondary"
android:visibility="gone" />
<LinearLayout
android:id="@+id/bridgePendingSignaturesContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:orientation="vertical" />
</LinearLayout>
</ScrollView>
@@ -1,35 +0,0 @@
<?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>