Updated on 2026-08-14
This commit is contained in:
commit
e801bbaed8
10 changed files with 73 additions and 85 deletions
|
|
@ -7,6 +7,7 @@ import com.tangem.tap.common.extensions.stripZeroPlainString
|
|||
import com.tangem.tap.features.send.redux.ReceiptAction.RefreshReceipt
|
||||
import com.tangem.tap.features.send.redux.SendScreenAction
|
||||
import com.tangem.tap.features.send.redux.states.*
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.store
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
@ -15,10 +16,6 @@ import java.math.BigDecimal
|
|||
*/
|
||||
class ReceiptReducer : SendInternalReducer {
|
||||
|
||||
companion object {
|
||||
const val EMPTY = "-"
|
||||
}
|
||||
|
||||
private lateinit var sendState: SendState
|
||||
private lateinit var amountState: AmountState
|
||||
private lateinit var feeState: FeeState
|
||||
|
|
@ -137,9 +134,9 @@ class ReceiptReducer : SendInternalReducer {
|
|||
)
|
||||
} else {
|
||||
ReceiptTokenFiat(
|
||||
amountFiat = EMPTY,
|
||||
feeFiat = EMPTY,
|
||||
totalFiat = EMPTY,
|
||||
amountFiat = UNKNOWN_AMOUNT_SIGN,
|
||||
feeFiat = UNKNOWN_AMOUNT_SIGN,
|
||||
totalFiat = UNKNOWN_AMOUNT_SIGN,
|
||||
willSentToken = tokensToSend.stripZeroPlainString(),
|
||||
willSentFeeCoin = feeCoin.stripZeroPlainString(),
|
||||
symbols = symbols
|
||||
|
|
@ -169,7 +166,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
ReceiptTokenCrypto(
|
||||
amountToken = tokensToSend.stripZeroPlainString(),
|
||||
feeCoin = feeCoin.stripZeroPlainString().addPrecisionSign(),
|
||||
totalFiat = EMPTY,
|
||||
totalFiat = UNKNOWN_AMOUNT_SIGN,
|
||||
symbols = symbols
|
||||
)
|
||||
}
|
||||
|
|
@ -206,7 +203,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
return when {
|
||||
!isToken && sendState.coinIsConvertible() -> sendState.coinConverter!!.toFiatWithPrecision(value).stripZeroPlainString()
|
||||
isToken && sendState.tokenIsConvertible() -> sendState.tokenConverter!!.toFiatWithPrecision(value).stripZeroPlainString()
|
||||
else -> EMPTY
|
||||
else -> UNKNOWN_AMOUNT_SIGN
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,12 +17,13 @@ import com.tangem.tap.features.BaseStoreFragment
|
|||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error
|
||||
import com.tangem.tap.features.send.redux.FeeAction
|
||||
import com.tangem.tap.features.send.redux.SendAction
|
||||
import com.tangem.tap.features.send.redux.reducers.ReceiptReducer
|
||||
import com.tangem.tap.features.send.redux.states.*
|
||||
import com.tangem.tap.features.send.ui.FeeUiHelper
|
||||
import com.tangem.tap.features.send.ui.SendFragment
|
||||
import com.tangem.tap.features.send.ui.dialogs.SendTransactionFailsDialog
|
||||
import com.tangem.tap.features.send.ui.dialogs.TezosWarningDialog
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.ROUGH_SIGN
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -257,12 +258,12 @@ class SendStateSubscriber(fragment: BaseStoreFragment) :
|
|||
val mainLayout = clReceiptContainer as ViewGroup
|
||||
val totalLayout = llTotalContainer.llTotal as ViewGroup
|
||||
val totalTokenLayout = llTotalContainer.flTotalTokenCrypto as ViewGroup
|
||||
fun getString(id: Int, vararg formatStrings: String): String =
|
||||
mainLayout.context.getString(id, *formatStrings)
|
||||
|
||||
val rough = getString(R.string.sign_rough)
|
||||
fun roughOrEmpty(value: String): String =
|
||||
if (value == ReceiptReducer.EMPTY) value else "$rough $value"
|
||||
fun getString(id: Int, vararg formatStrings: String): String = mainLayout.getString(id, *formatStrings)
|
||||
|
||||
fun roughOrEmpty(value: String): String {
|
||||
return if (value == UNKNOWN_AMOUNT_SIGN) value else "$ROUGH_SIGN $value"
|
||||
}
|
||||
|
||||
when (state.visibleTypeOfReceipt) {
|
||||
ReceiptLayoutType.FIAT -> {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
package com.tangem.tap.features.wallet.redux
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.DerivationStyle
|
||||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.common.address.AddressType
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.domain.common.extensions.canHandleToken
|
||||
|
|
@ -24,21 +19,15 @@ import com.tangem.tap.domain.extensions.sellIsAllowed
|
|||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
|
||||
import com.tangem.tap.features.tokens.redux.TokenWithBlockchain
|
||||
import com.tangem.tap.features.wallet.models.PendingTransaction
|
||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
||||
import com.tangem.tap.features.wallet.models.WalletRent
|
||||
import com.tangem.tap.features.wallet.models.WalletWarning
|
||||
import com.tangem.tap.features.wallet.models.hasPendingTransactions
|
||||
import com.tangem.tap.features.wallet.models.hasSendableAmounts
|
||||
import com.tangem.tap.features.wallet.models.isSendableAmount
|
||||
import com.tangem.tap.features.wallet.models.*
|
||||
import com.tangem.tap.features.wallet.redux.reducers.calculateTotalFiatAmount
|
||||
import com.tangem.tap.features.wallet.redux.reducers.findProgressState
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
|
||||
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
|
||||
import com.tangem.tap.store
|
||||
import java.math.BigDecimal
|
||||
import org.rekotlin.StateType
|
||||
import java.math.BigDecimal
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
|
||||
data class WalletState(
|
||||
|
|
@ -315,6 +304,11 @@ data class WalletState(
|
|||
)
|
||||
} else this
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val UNKNOWN_AMOUNT_SIGN = "—"
|
||||
const val ROUGH_SIGN = "≈"
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface WalletDialog : StateDialog {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.tap.features.wallet.models.filterByToken
|
|||
import com.tangem.tap.features.wallet.models.getPendingTransactions
|
||||
import com.tangem.tap.features.wallet.models.removeUnknownTransactions
|
||||
import com.tangem.tap.features.wallet.redux.*
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
|
||||
import com.tangem.tap.features.wallet.ui.TokenData
|
||||
|
|
@ -125,9 +126,8 @@ class MultiWalletReducer {
|
|||
action.amount.decimals, action.amount.currencySymbol
|
||||
),
|
||||
fiatAmountFormatted = tokenWalletData.fiatRate?.let {
|
||||
action.amount.value
|
||||
?.toFiatString(it, store.state.globalState.appCurrency.symbol)
|
||||
},
|
||||
action.amount.value?.toFiatString(it, store.state.globalState.appCurrency.symbol)
|
||||
} ?: UNKNOWN_AMOUNT_SIGN,
|
||||
blockchainAmount = wallet.amounts[AmountType.Coin]?.value ?: BigDecimal.ZERO
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ import com.tangem.tap.features.wallet.models.filterByToken
|
|||
import com.tangem.tap.features.wallet.models.getPendingTransactions
|
||||
import com.tangem.tap.features.wallet.models.removeUnknownTransactions
|
||||
import com.tangem.tap.features.wallet.redux.*
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
|
||||
import com.tangem.tap.features.wallet.ui.TokenData
|
||||
import com.tangem.tap.store
|
||||
import java.math.RoundingMode
|
||||
|
||||
class OnWalletLoadedReducer {
|
||||
|
||||
|
|
@ -54,6 +54,8 @@ class OnWalletLoadedReducer {
|
|||
}
|
||||
|
||||
val fiatAmount = walletData.fiatRate?.let { coinAmountValue?.toFiatValue(it) }
|
||||
val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrency.symbol) ?: UNKNOWN_AMOUNT_SIGN
|
||||
|
||||
val newWalletData = walletData.copy(
|
||||
currencyData = walletData.currencyData.copy(
|
||||
status = balanceStatus,
|
||||
|
|
@ -63,7 +65,7 @@ class OnWalletLoadedReducer {
|
|||
amount = coinAmountValue,
|
||||
amountFormatted = formattedAmount,
|
||||
fiatAmount = fiatAmount,
|
||||
fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrency.symbol)
|
||||
fiatAmountFormatted = fiatAmountFormatted,
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(isCoinSendButtonEnabled),
|
||||
|
|
@ -81,8 +83,9 @@ class OnWalletLoadedReducer {
|
|||
else -> BalanceStatus.VerifiedOnline
|
||||
}
|
||||
val tokenAmountValue = wallet.getTokenAmount(token)?.value
|
||||
val tokenFiatAmount =
|
||||
tokenWalletData?.fiatRate?.let { rate -> tokenAmountValue?.toFiatValue(rate) }
|
||||
val tokenFiatAmount = tokenWalletData?.fiatRate?.let { tokenAmountValue?.toFiatValue(it) }
|
||||
val tokenFiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrency.symbol)
|
||||
?: UNKNOWN_AMOUNT_SIGN
|
||||
|
||||
val isTokenSendButtonEnabled = newWalletData.shouldEnableTokenSendButton()
|
||||
&& pendingTransactions.isEmpty()
|
||||
|
|
@ -96,7 +99,7 @@ class OnWalletLoadedReducer {
|
|||
token.symbol
|
||||
),
|
||||
fiatAmount = tokenFiatAmount,
|
||||
fiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrency.symbol)
|
||||
fiatAmountFormatted = tokenFiatAmountFormatted,
|
||||
),
|
||||
pendingTransactions = tokenPendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(isTokenSendButtonEnabled),
|
||||
|
|
@ -140,9 +143,8 @@ class OnWalletLoadedReducer {
|
|||
wallet.blockchain.decimals(),
|
||||
wallet.blockchain.currency
|
||||
)
|
||||
val fiatRate = walletState.primaryWallet?.fiatRate
|
||||
val fiatAmountRaw = fiatRate?.multiply(amount)?.setScale(2, RoundingMode.DOWN)
|
||||
val fiatAmount = fiatRate?.let { amount?.toFiatString(it, fiatCurrencyName) }
|
||||
val fiatAmount = walletState.primaryWallet?.fiatRate?.let { amount?.toFiatValue(it) }
|
||||
val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrencyName) ?: UNKNOWN_AMOUNT_SIGN
|
||||
|
||||
val pendingTransactions = wallet.getPendingTransactions()
|
||||
val sendButtonEnabled = amount?.isZero() == false && pendingTransactions.isEmpty()
|
||||
|
|
@ -159,8 +161,8 @@ class OnWalletLoadedReducer {
|
|||
blockchainAmount = amount,
|
||||
amount = amount,
|
||||
amountFormatted = formattedAmount,
|
||||
fiatAmountFormatted = fiatAmount,
|
||||
fiatAmount = fiatAmountRaw
|
||||
fiatAmount = fiatAmount,
|
||||
fiatAmountFormatted = fiatAmountFormatted
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(sendButtonEnabled),
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ data class BalanceWidgetData(
|
|||
val blockchainAmount: BigDecimal? = BigDecimal.ZERO,
|
||||
val amount: BigDecimal? = null,
|
||||
val amountFormatted: String? = null,
|
||||
val fiatAmountFormatted: String? = null,
|
||||
val fiatAmount: BigDecimal? = null,
|
||||
val fiatAmountFormatted: String? = null,
|
||||
val token: TokenData? = null,
|
||||
val amountToCreateAccount: String? = null,
|
||||
val errorMessage: String? = null
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
package com.tangem.tap.features.wallet.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.*
|
||||
import android.widget.TextView
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.annotation.ColorRes
|
||||
|
|
@ -16,28 +12,17 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||
import androidx.transition.TransitionInflater
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.tangem.tangem_sdk_new.extensions.dpToPx
|
||||
import com.tangem.tap.common.SnackbarHandler
|
||||
import com.tangem.tap.common.TestActions
|
||||
import com.tangem.tap.common.extensions.appendIfNotNull
|
||||
import com.tangem.tap.common.extensions.beginDelayedTransition
|
||||
import com.tangem.tap.common.extensions.fitChipsByGroupWidth
|
||||
import com.tangem.tap.common.extensions.getColor
|
||||
import com.tangem.tap.common.extensions.getString
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.loadCurrenciesIcon
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.extensions.toQrCode
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||
import com.tangem.tap.features.onboarding.getQRReceiveMessage
|
||||
import com.tangem.tap.features.wallet.models.PendingTransaction
|
||||
import com.tangem.tap.features.wallet.redux.Currency
|
||||
import com.tangem.tap.features.wallet.redux.ErrorType
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletData
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import com.tangem.tap.features.wallet.redux.*
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter
|
||||
import com.tangem.tap.features.wallet.ui.adapters.WalletDetailWarningMessagesAdapter
|
||||
import com.tangem.tap.features.wallet.ui.test.TestWalletDetails
|
||||
|
|
@ -143,6 +128,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
|
||||
handleCurrencyIcon(selectedWallet)
|
||||
handleWarnings(selectedWallet)
|
||||
updateViewMeasurements()
|
||||
|
||||
binding.srlWalletDetails.setOnRefreshListener {
|
||||
if (selectedWallet.currencyData.status != BalanceStatus.Loading) {
|
||||
|
|
@ -161,13 +147,27 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateViewMeasurements() {
|
||||
val tvFiatAmount = binding.lWalletDetails.lBalance.tvFiatAmount
|
||||
val paddingStart = when (tvFiatAmount.text) {
|
||||
UNKNOWN_AMOUNT_SIGN -> 16f
|
||||
else -> 12f
|
||||
}
|
||||
tvFiatAmount.setPadding(
|
||||
tvFiatAmount.dpToPx(paddingStart).toInt(),
|
||||
tvFiatAmount.paddingTop,
|
||||
tvFiatAmount.paddingEnd,
|
||||
tvFiatAmount.paddingBottom,
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupCurrency(currencyData: BalanceWidgetData, currency: Currency) = with(binding) {
|
||||
tvCurrencyTitle.text = currencyData.currency
|
||||
if (currency is Currency.Token) {
|
||||
binding.tvCurrencySubtitle.text = currency.blockchain.tokenDisplayName()
|
||||
binding.tvCurrencySubtitle.show()
|
||||
tvCurrencySubtitle.text = currency.blockchain.tokenDisplayName()
|
||||
tvCurrencySubtitle.show()
|
||||
} else {
|
||||
binding.tvCurrencySubtitle.hide()
|
||||
tvCurrencySubtitle.hide()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,8 +106,8 @@ class WalletAdapter
|
|||
)
|
||||
|
||||
lContent.tvCurrency.text = wallet.currencyData.currency
|
||||
lContent.tvAmountFiat.text = wallet.currencyData.fiatAmountFormatted ?: "—"
|
||||
lContent.tvAmount.text = wallet.currencyData.amountFormatted ?: "—"
|
||||
lContent.tvAmountFiat.text = wallet.currencyData.fiatAmountFormatted
|
||||
lContent.tvAmount.text = wallet.currencyData.amountFormatted
|
||||
|
||||
lContent.tvStatus.isVisible = statusMessage != null
|
||||
lContent.tvStatus.text = statusMessage
|
||||
|
|
|
|||
|
|
@ -7,13 +7,12 @@
|
|||
android:layout_height="120dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_amount"
|
||||
android:id="@+id/tv_fiat_amount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textColor="@color/darkGray6"
|
||||
|
|
@ -23,10 +22,10 @@
|
|||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="2000.43 USD" />
|
||||
tools:text="496304.28 RUB" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_fiat_amount"
|
||||
android:id="@+id/tv_amount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
|
|
@ -37,8 +36,8 @@
|
|||
app:layout_constraintEnd_toStartOf="@id/iv_currency"
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_amount"
|
||||
tools:text="3.588 ETH" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_fiat_amount"
|
||||
tools:text="0.43 BTC" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/iv_currency"
|
||||
|
|
@ -73,7 +72,7 @@
|
|||
android:paddingEnd="16dp"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_fiat_amount"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_amount"
|
||||
tools:text="@string/wallet_balance_verified" />
|
||||
|
||||
<TextView
|
||||
|
|
@ -87,17 +86,17 @@
|
|||
android:paddingTop="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textSize="14sp"
|
||||
android:visibility="visible"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toStartOf="@+id/iv_currency"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_fiat_amount"
|
||||
tools:text="@string/lorem_ipsum" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_amount"
|
||||
tools:text="Some error" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_balance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:visibility="visible"
|
||||
app:constraint_referenced_ids="tv_amount, tv_fiat_amount, tv_status" />
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
<resources>
|
||||
|
||||
<string name="sign_rough">≈</string>
|
||||
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue