Updated on 2026-08-14
This commit is contained in:
parent
43c6359d2f
commit
880668b575
32 changed files with 898 additions and 17 deletions
|
|
@ -207,6 +207,8 @@ dependencies {
|
|||
implementation(projects.features.nft.impl)
|
||||
implementation(projects.features.walletconnect.api)
|
||||
implementation(projects.features.walletconnect.impl)
|
||||
implementation(projects.features.feeSelector.api)
|
||||
implementation(projects.features.feeSelector.impl)
|
||||
|
||||
/** AndroidX libraries */
|
||||
implementation(deps.androidx.core.ktx)
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ fun AmountTextField(
|
|||
textStyle: TextStyle,
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = TangemTheme.colors.text.primary1,
|
||||
backgroundColor: Color = TangemTheme.colors.background.action,
|
||||
visualTransformation: VisualTransformation = AmountVisualTransformation(decimals),
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Number,
|
||||
|
|
@ -117,7 +118,7 @@ fun AmountTextField(
|
|||
singleLine = true,
|
||||
readOnly = !isEnabled,
|
||||
visualTransformation = visualTransformation,
|
||||
modifier = Modifier.background(TangemTheme.colors.background.action),
|
||||
modifier = Modifier.background(backgroundColor),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
package com.tangem.core.ui.components.inputrow
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.fields.AmountTextField
|
||||
import com.tangem.core.ui.components.fields.visualtransformations.AmountVisualTransformation
|
||||
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
|
||||
|
|
@ -106,3 +107,76 @@ fun InputRowEnterInfoAmount(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun InputRowEnterInfoAmountV2(
|
||||
title: TextReference,
|
||||
text: String,
|
||||
decimals: Int,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
symbol: String? = null,
|
||||
info: TextReference? = null,
|
||||
titleColor: Color = TangemTheme.colors.text.secondary,
|
||||
textColor: Color = TangemTheme.colors.text.primary1,
|
||||
infoColor: Color = TangemTheme.colors.text.tertiary,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
showDivider: Boolean = false,
|
||||
isReadOnly: Boolean = false,
|
||||
) {
|
||||
DividerContainer(
|
||||
modifier = modifier,
|
||||
showDivider = showDivider,
|
||||
paddingValues = PaddingValues(horizontal = 12.dp),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth().padding(16.dp),
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(2.dp)) {
|
||||
Text(
|
||||
text = title.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = titleColor,
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.size(16.dp),
|
||||
painter = painterResource(R.drawable.ic_union_16),
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
Row {
|
||||
AmountTextField(
|
||||
value = text,
|
||||
decimals = decimals,
|
||||
visualTransformation = AmountVisualTransformation(
|
||||
decimals = decimals,
|
||||
symbol = symbol,
|
||||
decimalFormat = rememberDecimalFormat(),
|
||||
),
|
||||
onValueChange = onValueChange,
|
||||
color = textColor,
|
||||
isEnabled = !isReadOnly,
|
||||
textStyle = TangemTheme.typography.body2,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
backgroundColor = Color.Transparent,
|
||||
modifier = Modifier
|
||||
.padding(top = TangemTheme.dimens.spacing8)
|
||||
.weight(1f),
|
||||
)
|
||||
info?.let {
|
||||
Text(
|
||||
text = it.resolveReference(),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = infoColor,
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens.spacing8)
|
||||
.align(Alignment.Bottom),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
core/ui/src/main/res/drawable/ic_edit_v2_24.xml
Normal file
12
core/ui/src/main/res/drawable/ic_edit_v2_24.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#1E1E1E"
|
||||
android:pathData="M6.749,18.142L16.677,8.183L14.812,6.309L4.879,16.267L4.026,18.424C3.9,18.765 4.249,19.094 4.556,18.976L6.749,18.142ZM17.598,7.269L18.614,6.263C19.106,5.77 19.131,5.201 18.669,4.734L18.266,4.325C17.808,3.862 17.232,3.904 16.736,4.388L15.724,5.395L17.598,7.269Z" />
|
||||
|
||||
</vector>
|
||||
13
core/ui/src/main/res/drawable/ic_star_mini_24.xml
Normal file
13
core/ui/src/main/res/drawable/ic_star_mini_24.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#0099FF"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M11.481,6.351C11.481,6.351 11.481,6.351 11.481,6.351L10.245,8.844C10.094,9.153 9.847,9.409 9.601,9.593C9.355,9.777 9.041,9.94 8.706,9.997L8.704,9.998L6.46,10.373C5.875,10.472 5.77,10.688 5.758,10.726C5.745,10.766 5.709,11.009 6.129,11.432L7.874,13.191C8.134,13.453 8.3,13.795 8.391,14.114C8.482,14.434 8.519,14.81 8.44,15.166L8.438,15.171L7.939,17.349C7.855,17.713 7.854,17.969 7.884,18.128C7.898,18.205 7.918,18.251 7.932,18.275C7.944,18.297 7.952,18.303 7.953,18.303C7.953,18.304 7.961,18.31 7.984,18.315C8.009,18.32 8.057,18.325 8.133,18.316C8.29,18.296 8.53,18.218 8.849,18.027L10.958,16.768C11.293,16.572 11.685,16.495 12.037,16.495C12.387,16.495 12.781,16.572 13.115,16.771C13.115,16.771 13.115,16.771 13.115,16.771L15.218,18.027C15.218,18.027 15.218,18.027 15.218,18.027C15.539,18.218 15.781,18.296 15.939,18.317C16.016,18.326 16.064,18.322 16.089,18.316C16.101,18.314 16.109,18.311 16.112,18.309C16.116,18.308 16.117,18.306 16.118,18.306C16.119,18.306 16.12,18.304 16.123,18.301C16.126,18.298 16.131,18.291 16.138,18.279C16.151,18.256 16.171,18.21 16.185,18.133C16.214,17.972 16.213,17.715 16.129,17.348L15.629,15.166C15.55,14.81 15.586,14.434 15.677,14.114C15.768,13.795 15.935,13.453 16.194,13.191L17.939,11.432L17.941,11.431C18.364,11.007 18.326,10.766 18.314,10.727C18.301,10.689 18.194,10.472 17.608,10.373L15.365,9.998C15.027,9.941 14.711,9.778 14.462,9.594C14.215,9.41 13.967,9.153 13.816,8.844L12.579,6.348C12.297,5.777 12.055,5.75 12.033,5.75C12.01,5.75 11.766,5.78 11.481,6.351ZM13.923,5.683C13.536,4.9 12.896,4.25 12.033,4.25C11.172,4.25 10.529,4.898 10.139,5.682L10.138,5.683L8.9,8.18L8.897,8.185C8.879,8.222 8.817,8.306 8.703,8.391C8.59,8.476 8.493,8.512 8.454,8.519L6.212,8.894C5.361,9.037 4.583,9.467 4.328,10.273C4.073,11.076 4.457,11.877 5.064,12.489L6.809,14.248C6.845,14.284 6.907,14.379 6.948,14.524C6.989,14.667 6.988,14.783 6.976,14.839L6.477,17.014C6.477,17.014 6.477,17.014 6.477,17.014C6.265,17.937 6.312,18.959 7.064,19.512C7.82,20.068 8.807,19.8 9.619,19.315C9.619,19.315 9.619,19.315 9.619,19.315L11.719,18.061C11.771,18.031 11.885,17.995 12.037,17.995C12.191,17.995 12.3,18.032 12.346,18.059L14.45,19.315C15.261,19.798 16.251,20.07 17.006,19.515C17.759,18.961 17.803,17.938 17.591,17.014L17.093,14.839C17.081,14.783 17.08,14.667 17.12,14.524C17.161,14.379 17.223,14.284 17.259,14.248L19.002,12.49C19.003,12.49 19.003,12.49 19.003,12.489C19.614,11.877 19.999,11.076 19.743,10.271C19.486,9.466 18.707,9.037 17.857,8.894L15.613,8.518C15.613,8.518 15.613,8.518 15.613,8.518C15.57,8.511 15.471,8.475 15.358,8.39C15.243,8.305 15.182,8.222 15.164,8.185L13.923,5.683C13.924,5.684 13.923,5.683 13.923,5.683Z" />
|
||||
|
||||
</vector>
|
||||
12
core/ui/src/main/res/drawable/ic_union_16.xml
Normal file
12
core/ui/src/main/res/drawable/ic_union_16.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
|
||||
<path
|
||||
android:fillColor="#919191"
|
||||
android:pathData="M8,1.5C9.724,1.5 11.378,2.184 12.597,3.403C13.816,4.622 14.5,6.276 14.5,8C14.5,9.724 13.816,11.378 12.597,12.597C11.378,13.816 9.724,14.5 8,14.5C6.276,14.5 4.622,13.816 3.403,12.597C2.184,11.378 1.5,9.724 1.5,8C1.5,6.276 2.184,4.622 3.403,3.403C4.622,2.184 6.276,1.5 8,1.5ZM8,2.5C6.541,2.5 5.143,3.08 4.111,4.111C3.08,5.143 2.5,6.541 2.5,8C2.5,9.459 3.08,10.857 4.111,11.889C5.143,12.92 6.541,13.5 8,13.5C9.459,13.5 10.857,12.92 11.889,11.889C12.92,10.857 13.5,9.459 13.5,8C13.5,6.541 12.92,5.143 11.889,4.111C10.857,3.08 9.459,2.5 8,2.5ZM8,6.667C8.133,6.667 8.26,6.72 8.354,6.813C8.447,6.907 8.5,7.034 8.5,7.167V10.667H9C9.133,10.667 9.26,10.72 9.354,10.814C9.447,10.907 9.5,11.035 9.5,11.167C9.5,11.3 9.447,11.427 9.354,11.521C9.26,11.614 9.133,11.667 9,11.667H7C6.867,11.667 6.74,11.614 6.646,11.521C6.553,11.427 6.5,11.3 6.5,11.167C6.5,11.035 6.553,10.907 6.646,10.814C6.74,10.72 6.867,10.667 7,10.667H7.5V7.667H7.333C7.201,7.667 7.073,7.614 6.979,7.521C6.886,7.427 6.833,7.299 6.833,7.167C6.833,7.035 6.886,6.907 6.979,6.813C7.073,6.72 7.201,6.667 7.333,6.667H8ZM8,4.333C8.46,4.333 8.833,4.707 8.833,5.167C8.833,5.627 8.46,6 8,6C7.54,6 7.167,5.627 7.167,5.167C7.167,4.707 7.54,4.333 8,4.333Z" />
|
||||
|
||||
</vector>
|
||||
1
features/fee-selector/api/.gitignore
vendored
Normal file
1
features/fee-selector/api/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
27
features/fee-selector/api/build.gradle.kts
Normal file
27
features/fee-selector/api/build.gradle.kts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
plugins {
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.features.feeselector.api"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
/** Project - Core */
|
||||
implementation(projects.core.ui)
|
||||
implementation(projects.core.decompose)
|
||||
|
||||
/** Domain models */
|
||||
// api(projects.domain.models)
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
// implementation(projects.domain.wallets.models)
|
||||
|
||||
/** Compose */
|
||||
implementation(deps.compose.runtime)
|
||||
implementation(deps.compose.foundation)
|
||||
|
||||
/** Other */
|
||||
implementation(deps.kotlin.immutable.collections)
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.features.feeselector.api.component
|
||||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
|
||||
interface FeeSelectorComponent : ComposableContentComponent, ComposableBottomSheetComponent {
|
||||
data class Params(val appCurrency: AppCurrency)
|
||||
|
||||
interface Factory : ComponentFactory<Params, FeeSelectorComponent>
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.features.send.v2.subcomponents.fee.ui.state
|
||||
package com.tangem.features.feeselector.api.entity
|
||||
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
|
|
@ -6,7 +6,7 @@ import androidx.compose.runtime.Immutable
|
|||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
@Immutable
|
||||
internal data class CustomFeeFieldUM(
|
||||
data class CustomFeeFieldUM(
|
||||
val value: String,
|
||||
val onValueChange: (String) -> Unit,
|
||||
val keyboardOptions: KeyboardOptions,
|
||||
1
features/fee-selector/impl/.gitignore
vendored
Normal file
1
features/fee-selector/impl/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
57
features/fee-selector/impl/build.gradle.kts
Normal file
57
features/fee-selector/impl/build.gradle.kts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
plugins {
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
alias(deps.plugins.kotlin.serialization)
|
||||
alias(deps.plugins.kotlin.kapt)
|
||||
alias(deps.plugins.hilt.android)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.features.feeselector.impl"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
/** Project - API */
|
||||
implementation(projects.features.feeSelector.api)
|
||||
|
||||
/** Project - Core */
|
||||
implementation(projects.common.ui)
|
||||
implementation(projects.common.routing)
|
||||
implementation(projects.core.decompose)
|
||||
implementation(projects.core.ui)
|
||||
implementation(projects.core.pagination)
|
||||
implementation(projects.core.navigation)
|
||||
|
||||
/** Project - Domain */
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.wallets)
|
||||
implementation(projects.domain.wallets.models)
|
||||
|
||||
/** AndroidX */
|
||||
implementation(deps.androidx.activity.compose)
|
||||
implementation(deps.lifecycle.compose)
|
||||
|
||||
/** Compose */
|
||||
implementation(deps.compose.ui)
|
||||
implementation(deps.compose.ui.tooling)
|
||||
implementation(deps.compose.foundation)
|
||||
implementation(deps.compose.material3)
|
||||
implementation(deps.compose.shimmer)
|
||||
|
||||
/*** Tangem SDK */
|
||||
implementation(tangemDeps.blockchain)
|
||||
|
||||
/** DI */
|
||||
implementation(deps.hilt.android)
|
||||
kapt(deps.hilt.kapt)
|
||||
|
||||
/** Other */
|
||||
implementation(deps.arrow.core)
|
||||
implementation(deps.kotlin.immutable.collections)
|
||||
implementation(deps.decompose.ext.compose)
|
||||
implementation(deps.timber)
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.tangem.features.feeselector.impl.component
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.features.feeselector.api.component.FeeSelectorComponent
|
||||
import com.tangem.features.feeselector.impl.model.FeeSelectorModel
|
||||
import com.tangem.features.feeselector.impl.ui.FeeSelectorModalBottomSheet
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
internal class DefaultFeeSelectorComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted private val params: FeeSelectorComponent.Params,
|
||||
) : FeeSelectorComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val model: FeeSelectorModel = getOrCreateModel(params = params)
|
||||
|
||||
override fun dismiss() {
|
||||
model.dismiss()
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun BottomSheet() {
|
||||
FeeSelectorModalBottomSheet(onDismiss = ::dismiss, state = TODO())
|
||||
}
|
||||
|
||||
// Temporary workaround, to use test this component
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
BackHandler(onBack = router::pop)
|
||||
FeeSelectorModalBottomSheet(onDismiss = ::dismiss, state = TODO())
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : FeeSelectorComponent.Factory {
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: FeeSelectorComponent.Params,
|
||||
): DefaultFeeSelectorComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.features.feeselector.impl.di
|
||||
|
||||
import com.tangem.features.feeselector.api.component.FeeSelectorComponent
|
||||
import com.tangem.features.feeselector.impl.component.DefaultFeeSelectorComponent
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface FeeSelectorFeatureModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindComponentFactory(factory: DefaultFeeSelectorComponent.Factory): FeeSelectorComponent.Factory
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tangem.features.feeselector.impl.di
|
||||
|
||||
import com.tangem.core.decompose.di.ModelComponent
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.features.feeselector.impl.model.FeeSelectorModel
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.multibindings.ClassKey
|
||||
import dagger.multibindings.IntoMap
|
||||
|
||||
@Module
|
||||
@InstallIn(ModelComponent::class)
|
||||
internal interface FeeSelectorModelModule {
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(FeeSelectorModel::class)
|
||||
fun bindModel(model: FeeSelectorModel): Model
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package com.tangem.features.feeselector.impl.entity
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Immutable
|
||||
internal sealed class FeeSelectorUM {
|
||||
|
||||
data object Loading : FeeSelectorUM()
|
||||
|
||||
data class Content(
|
||||
val isDoneEnabled: Boolean,
|
||||
val feeItems: ImmutableList<FeeItem>,
|
||||
val selectedFeeItem: FeeItem,
|
||||
val isFeeApproximate: Boolean,
|
||||
val feeFiatRateDataHolder: FeeFiatRateDataHolder?,
|
||||
) : FeeSelectorUM()
|
||||
}
|
||||
|
||||
@Immutable
|
||||
data class FeeFiatRateDataHolder(
|
||||
val rate: BigDecimal,
|
||||
val appCurrency: AppCurrency,
|
||||
)
|
||||
|
||||
@Immutable
|
||||
internal sealed class FeeItem {
|
||||
abstract val onSelect: () -> Unit
|
||||
|
||||
data class Suggested(val title: TextReference, val amount: Amount, override val onSelect: () -> Unit) : FeeItem()
|
||||
data class Slow(val amount: Amount, override val onSelect: () -> Unit) : FeeItem()
|
||||
data class Market(val amount: Amount, override val onSelect: () -> Unit) : FeeItem()
|
||||
data class Fast(val amount: Amount, override val onSelect: () -> Unit) : FeeItem()
|
||||
data class Custom(val customValues: ImmutableList<CustomFeeFieldUM>, override val onSelect: () -> Unit) : FeeItem()
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.tangem.features.feeselector.impl.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.features.feeselector.api.component.FeeSelectorComponent
|
||||
import com.tangem.features.feeselector.impl.entity.FeeSelectorUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
|
||||
@Stable
|
||||
@ModelScoped
|
||||
internal class FeeSelectorModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
private val router: Router,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model() {
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private val params = paramsContainer.require<FeeSelectorComponent.Params>()
|
||||
val uiState: StateFlow<FeeSelectorUM>
|
||||
field = MutableStateFlow<FeeSelectorUM>(FeeSelectorUM.Loading)
|
||||
|
||||
fun dismiss() {
|
||||
router.pop()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,510 @@
|
|||
package com.tangem.features.feeselector.impl.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
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.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatReference
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.components.atoms.text.EllipsisText
|
||||
import com.tangem.core.ui.components.atoms.text.TextEllipsis
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetWithFooter
|
||||
import com.tangem.core.ui.components.inputrow.InputRowEnterInfoAmountV2
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fee
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import com.tangem.features.feeselector.impl.R
|
||||
import com.tangem.features.feeselector.impl.entity.FeeFiatRateDataHolder
|
||||
import com.tangem.features.feeselector.impl.entity.FeeItem
|
||||
import com.tangem.features.feeselector.impl.entity.FeeSelectorUM
|
||||
import com.tangem.utils.StringsSigns
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Composable
|
||||
internal fun FeeSelectorModalBottomSheet(state: FeeSelectorUM.Content, onDismiss: () -> Unit) {
|
||||
TangemModalBottomSheetWithFooter<TangemBottomSheetConfigContent.Empty>(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = onDismiss,
|
||||
content = TangemBottomSheetConfigContent.Empty,
|
||||
),
|
||||
containerColor = TangemTheme.colors.background.primary,
|
||||
title = {
|
||||
TangemModalBottomSheetTitle(
|
||||
title = resourceReference(R.string.common_network_fee_title),
|
||||
startIconRes = R.drawable.ic_back_24,
|
||||
onStartClick = onDismiss,
|
||||
)
|
||||
},
|
||||
content = {
|
||||
FeeSelectorItems(state = state, modifier = Modifier.padding(vertical = 4.dp, horizontal = 16.dp))
|
||||
},
|
||||
footer = {
|
||||
PrimaryButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp),
|
||||
text = stringResourceSafe(R.string.common_done),
|
||||
onClick = onDismiss,
|
||||
enabled = state.isDoneEnabled,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
@Composable
|
||||
private fun FeeSelectorItems(state: FeeSelectorUM.Content, modifier: Modifier = Modifier) {
|
||||
Column(modifier = modifier) {
|
||||
state.feeItems.fastForEachIndexed { index, item ->
|
||||
val isSelected = item == state.selectedFeeItem
|
||||
val lastItem = index == state.feeItems.size - 1
|
||||
val iconTint by animateColorAsState(
|
||||
targetValue = if (isSelected) TangemTheme.colors.icon.accent else TangemTheme.colors.text.tertiary,
|
||||
label = "Fee selector icon tint change",
|
||||
)
|
||||
val iconBackgroundColor by animateColorAsState(
|
||||
targetValue = if (isSelected) {
|
||||
TangemTheme.colors.icon.accent.copy(alpha = 0.1F)
|
||||
} else {
|
||||
TangemTheme.colors.background.secondary
|
||||
},
|
||||
label = "Fee selector icon background change",
|
||||
)
|
||||
val onSelect by rememberUpdatedState(item.onSelect)
|
||||
val itemModifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(TangemTheme.colors.background.primary)
|
||||
.then(
|
||||
if (isSelected) {
|
||||
Modifier
|
||||
.border(
|
||||
width = 2.5.dp,
|
||||
color = iconTint.copy(alpha = 0.2F),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
)
|
||||
.padding(2.5.dp)
|
||||
.border(width = 1.dp, color = iconTint, shape = RoundedCornerShape(14.dp))
|
||||
.clip(RoundedCornerShape(14.dp))
|
||||
} else {
|
||||
Modifier
|
||||
},
|
||||
)
|
||||
.clickableSingle(onClick = onSelect)
|
||||
when (item) {
|
||||
is FeeItem.Suggested -> RegularFeeItemContent(
|
||||
modifier = itemModifier,
|
||||
title = item.title,
|
||||
iconRes = R.drawable.ic_star_mini_24,
|
||||
iconBackgroundColor = iconBackgroundColor,
|
||||
iconTint = iconTint,
|
||||
preDot = stringReference(
|
||||
item.amount.value.format {
|
||||
crypto(
|
||||
symbol = item.amount.currencySymbol,
|
||||
decimals = item.amount.decimals,
|
||||
).fee(canBeLower = state.isFeeApproximate)
|
||||
},
|
||||
),
|
||||
postDot = if (state.feeFiatRateDataHolder != null) {
|
||||
getFiatReference(
|
||||
value = item.amount.value,
|
||||
rate = state.feeFiatRateDataHolder.rate,
|
||||
appCurrency = state.feeFiatRateDataHolder.appCurrency,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = item.amount.currencySymbol.length,
|
||||
showDivider = !isSelected && !lastItem,
|
||||
)
|
||||
is FeeItem.Slow -> RegularFeeItemContent(
|
||||
modifier = itemModifier,
|
||||
title = resourceReference(R.string.common_fee_selector_option_slow),
|
||||
iconRes = R.drawable.ic_tortoise_24,
|
||||
iconBackgroundColor = iconBackgroundColor,
|
||||
iconTint = iconTint,
|
||||
preDot = stringReference(
|
||||
item.amount.value.format {
|
||||
crypto(
|
||||
symbol = item.amount.currencySymbol,
|
||||
decimals = item.amount.decimals,
|
||||
).fee(canBeLower = state.isFeeApproximate)
|
||||
},
|
||||
),
|
||||
postDot = if (state.feeFiatRateDataHolder != null) {
|
||||
getFiatReference(
|
||||
value = item.amount.value,
|
||||
rate = state.feeFiatRateDataHolder.rate,
|
||||
appCurrency = state.feeFiatRateDataHolder.appCurrency,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = item.amount.currencySymbol.length,
|
||||
showDivider = !isSelected && !lastItem,
|
||||
)
|
||||
is FeeItem.Market -> RegularFeeItemContent(
|
||||
modifier = itemModifier,
|
||||
title = resourceReference(R.string.common_fee_selector_option_market),
|
||||
iconRes = R.drawable.ic_bird_24,
|
||||
iconBackgroundColor = iconBackgroundColor,
|
||||
iconTint = iconTint,
|
||||
preDot = stringReference(
|
||||
item.amount.value.format {
|
||||
crypto(
|
||||
symbol = item.amount.currencySymbol,
|
||||
decimals = item.amount.decimals,
|
||||
).fee(canBeLower = state.isFeeApproximate)
|
||||
},
|
||||
),
|
||||
postDot = if (state.feeFiatRateDataHolder != null) {
|
||||
getFiatReference(
|
||||
value = item.amount.value,
|
||||
rate = state.feeFiatRateDataHolder.rate,
|
||||
appCurrency = state.feeFiatRateDataHolder.appCurrency,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = item.amount.currencySymbol.length,
|
||||
showDivider = !isSelected && !lastItem,
|
||||
)
|
||||
is FeeItem.Fast -> RegularFeeItemContent(
|
||||
modifier = itemModifier,
|
||||
title = resourceReference(R.string.common_fee_selector_option_fast),
|
||||
iconRes = R.drawable.ic_hare_24,
|
||||
iconBackgroundColor = iconBackgroundColor,
|
||||
iconTint = iconTint,
|
||||
preDot = stringReference(
|
||||
item.amount.value.format {
|
||||
crypto(
|
||||
symbol = item.amount.currencySymbol,
|
||||
decimals = item.amount.decimals,
|
||||
).fee(canBeLower = state.isFeeApproximate)
|
||||
},
|
||||
),
|
||||
postDot = if (state.feeFiatRateDataHolder != null) {
|
||||
getFiatReference(
|
||||
value = item.amount.value,
|
||||
rate = state.feeFiatRateDataHolder.rate,
|
||||
appCurrency = state.feeFiatRateDataHolder.appCurrency,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
ellipsizeOffset = item.amount.currencySymbol.length,
|
||||
showDivider = !isSelected && !lastItem,
|
||||
)
|
||||
is FeeItem.Custom -> CustomFeeBlock(
|
||||
modifier = itemModifier,
|
||||
customFee = item,
|
||||
isSelected = isSelected,
|
||||
iconBackgroundColor = iconBackgroundColor,
|
||||
iconTint = iconTint,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CustomFeeBlock(
|
||||
customFee: FeeItem.Custom,
|
||||
isSelected: Boolean,
|
||||
iconBackgroundColor: Color,
|
||||
iconTint: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
Row(
|
||||
modifier = Modifier.padding(all = 12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
.background(color = iconBackgroundColor, shape = CircleShape)
|
||||
.padding(6.dp),
|
||||
painter = painterResource(R.drawable.ic_edit_v2_24),
|
||||
tint = iconTint,
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.common_custom),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
visible = isSelected,
|
||||
label = "Custom Fee Selected Animation",
|
||||
enter = expandVertically().plus(fadeIn()),
|
||||
exit = shrinkVertically().plus(fadeOut()),
|
||||
) {
|
||||
ExpandedCustomFeeItems(customFeeFields = customFee.customValues, onValueChange = { _, _ -> })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ExpandedCustomFeeItems(
|
||||
customFeeFields: ImmutableList<CustomFeeFieldUM>,
|
||||
onValueChange: (Int, String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
customFeeFields.fastForEachIndexed { index, field ->
|
||||
val showDivider = index != customFeeFields.size - 1
|
||||
if (field.label != null) {
|
||||
InputRowEnterInfoAmountV2(
|
||||
text = field.value,
|
||||
decimals = field.decimals,
|
||||
symbol = field.symbol,
|
||||
title = field.title,
|
||||
titleColor = TangemTheme.colors.text.tertiary,
|
||||
info = field.label,
|
||||
keyboardOptions = field.keyboardOptions,
|
||||
keyboardActions = field.keyboardActions,
|
||||
onValueChange = { onValueChange(index, it) },
|
||||
showDivider = showDivider,
|
||||
isReadOnly = field.isReadonly,
|
||||
)
|
||||
} else {
|
||||
InputRowEnterInfoAmountV2(
|
||||
text = field.value,
|
||||
decimals = field.decimals,
|
||||
title = field.title,
|
||||
titleColor = TangemTheme.colors.text.tertiary,
|
||||
symbol = field.symbol,
|
||||
onValueChange = { onValueChange(index, it) },
|
||||
keyboardOptions = field.keyboardOptions,
|
||||
keyboardActions = field.keyboardActions,
|
||||
showDivider = showDivider,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RegularFeeItemContent(
|
||||
title: TextReference,
|
||||
@DrawableRes iconRes: Int,
|
||||
iconBackgroundColor: Color,
|
||||
iconTint: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
preDot: TextReference? = null,
|
||||
postDot: TextReference? = null,
|
||||
ellipsizeOffset: Int? = null,
|
||||
showDivider: Boolean = true,
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
Row(
|
||||
modifier = Modifier.padding(all = 12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
.background(color = iconBackgroundColor, shape = CircleShape)
|
||||
.padding(6.dp),
|
||||
painter = painterResource(iconRes),
|
||||
tint = iconTint,
|
||||
contentDescription = null,
|
||||
)
|
||||
FeeDescription(
|
||||
title = title,
|
||||
preDot = preDot,
|
||||
postDot = postDot,
|
||||
ellipsizeOffset = ellipsizeOffset,
|
||||
)
|
||||
}
|
||||
if (showDivider) {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(start = 60.dp, end = 12.dp),
|
||||
color = TangemTheme.colors.stroke.primary,
|
||||
thickness = 0.5.dp,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FeeDescription(
|
||||
title: TextReference,
|
||||
modifier: Modifier = Modifier,
|
||||
preDot: TextReference? = null,
|
||||
postDot: TextReference? = null,
|
||||
ellipsizeOffset: Int? = null,
|
||||
) {
|
||||
Column(modifier = modifier, verticalArrangement = Arrangement.spacedBy(2.dp)) {
|
||||
Text(
|
||||
text = title.resolveReference(),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
)
|
||||
if (preDot != null) {
|
||||
FeeValueContent(preDot = preDot, postDot = postDot, ellipsizeOffset = ellipsizeOffset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FeeValueContent(preDot: TextReference, postDot: TextReference?, ellipsizeOffset: Int? = null) {
|
||||
val ellipsis = if (ellipsizeOffset == null) {
|
||||
TextEllipsis.End
|
||||
} else {
|
||||
TextEllipsis.OffsetEnd(ellipsizeOffset)
|
||||
}
|
||||
val textColor = TangemTheme.colors.text.tertiary
|
||||
val textStyle = TangemTheme.typography.caption1
|
||||
Row {
|
||||
EllipsisText(
|
||||
text = preDot.resolveReference(),
|
||||
style = textStyle,
|
||||
color = textColor,
|
||||
textAlign = TextAlign.End,
|
||||
ellipsis = ellipsis,
|
||||
)
|
||||
if (postDot != null) {
|
||||
Text(
|
||||
text = StringsSigns.DOT,
|
||||
style = textStyle,
|
||||
color = textColor,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing4),
|
||||
)
|
||||
Text(text = postDot.resolveReference(), style = textStyle, color = textColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO)
|
||||
@Preview(showBackground = true, device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun FeeSelectorBS_Preview(
|
||||
@PreviewParameter(FeeSelectorUMContentProvider::class)
|
||||
state: FeeSelectorUM.Content,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
FeeSelectorModalBottomSheet(onDismiss = {}, state = state)
|
||||
}
|
||||
}
|
||||
|
||||
private class FeeSelectorUMContentProvider : CollectionPreviewParameterProvider<FeeSelectorUM.Content>(
|
||||
collection = listOf(
|
||||
FeeSelectorUM.Content(
|
||||
isDoneEnabled = false,
|
||||
feeItems = persistentListOf(
|
||||
FeeItem.Suggested(
|
||||
title = stringReference("Suggested by Tangem"),
|
||||
amount = Amount(value = BigDecimal("0.1"), blockchain = Blockchain.Ethereum),
|
||||
onSelect = onSelectStub,
|
||||
),
|
||||
FeeItem.Slow(
|
||||
amount = Amount(value = BigDecimal("0.01"), blockchain = Blockchain.Ethereum),
|
||||
onSelect = onSelectStub,
|
||||
),
|
||||
FeeItem.Market(
|
||||
amount = Amount(value = BigDecimal("0.02"), blockchain = Blockchain.Ethereum),
|
||||
onSelect = onSelectStub,
|
||||
),
|
||||
FeeItem.Fast(
|
||||
amount = Amount(value = BigDecimal("0.3"), blockchain = Blockchain.Ethereum),
|
||||
onSelect = onSelectStub,
|
||||
),
|
||||
FeeItem.Custom(customValues = customFeeFields, onSelect = onSelectStub),
|
||||
),
|
||||
// selectedFeeItem = FeeItem.Market(
|
||||
// amount = Amount(value = BigDecimal("0.02"), blockchain = Blockchain.Ethereum),
|
||||
// onSelect = onSelectStub
|
||||
// ),
|
||||
selectedFeeItem = FeeItem.Custom(customValues = customFeeFields, onSelect = onSelectStub),
|
||||
isFeeApproximate = true,
|
||||
feeFiatRateDataHolder = FeeFiatRateDataHolder(
|
||||
rate = BigDecimal.TEN,
|
||||
appCurrency = AppCurrency.Default,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
private val onSelectStub: () -> Unit = {}
|
||||
|
||||
private val customFeeFields = persistentListOf(
|
||||
CustomFeeFieldUM(
|
||||
value = "0.119806",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions(),
|
||||
keyboardActions = KeyboardActions(),
|
||||
symbol = "ETH",
|
||||
decimals = 8,
|
||||
title = resourceReference(R.string.send_max_fee),
|
||||
footer = resourceReference(R.string.send_custom_amount_fee_footer),
|
||||
label = stringReference("~ 0,03 \$"),
|
||||
isReadonly = false,
|
||||
),
|
||||
CustomFeeFieldUM(
|
||||
value = "40000",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions(),
|
||||
keyboardActions = KeyboardActions(),
|
||||
symbol = "GWEI",
|
||||
decimals = 8,
|
||||
title = resourceReference(R.string.send_gas_price),
|
||||
footer = resourceReference(R.string.send_gas_price_footer),
|
||||
label = null,
|
||||
isReadonly = false,
|
||||
),
|
||||
CustomFeeFieldUM(
|
||||
value = "31400",
|
||||
onValueChange = {},
|
||||
keyboardOptions = KeyboardOptions(),
|
||||
keyboardActions = KeyboardActions(),
|
||||
symbol = null,
|
||||
decimals = 8,
|
||||
title = resourceReference(R.string.send_gas_limit),
|
||||
footer = resourceReference(R.string.send_gas_limit_footer),
|
||||
label = null,
|
||||
isReadonly = false,
|
||||
),
|
||||
)
|
||||
|
|
@ -16,6 +16,7 @@ dependencies {
|
|||
implementation(projects.features.sendV2.api)
|
||||
implementation(projects.features.txhistory.api)
|
||||
implementation(projects.features.nft.api)
|
||||
implementation(projects.features.feeSelector.api)
|
||||
|
||||
/** Libs */
|
||||
implementation(projects.libs.crypto)
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import com.tangem.blockchain.common.transaction.Fee
|
|||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeType
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ import com.tangem.blockchain.common.transaction.TransactionFee
|
|||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.bitcoin.BitcoinCustomFeeConverter
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.ethereum.EthereumCustomFeeConverter
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.kaspa.KaspaCustomFeeConverter
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeSelectorUM
|
||||
import com.tangem.utils.converter.TwoWayConverter
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.features.send.v2.subcomponents.fee.model.converters.custom
|
||||
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ import com.tangem.core.ui.utils.parseBigDecimal
|
|||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.checkExceedBalance
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.CustomFeeConverter
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import com.tangem.lib.crypto.BlockchainUtils
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.ethereum
|
||||
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.CustomFeeConverter
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.checkExceedBalance
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.core.ui.utils.parseBigDecimal
|
|||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.checkExceedBalance
|
||||
|
|
@ -19,7 +20,6 @@ import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.eth
|
|||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.ethereum.EthereumCustomFeeConverter.Companion.GAS_DECIMALS
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.ethereum.EthereumCustomFeeConverter.Companion.GIGA_DECIMALS
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.setEmpty
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.core.ui.utils.parseBigDecimal
|
|||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.checkExceedBalance
|
||||
|
|
@ -19,7 +20,6 @@ import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.eth
|
|||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.ethereum.EthereumCustomFeeConverter.Companion.GAS_DECIMALS
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.ethereum.EthereumCustomFeeConverter.Companion.GIGA_DECIMALS
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.setEmpty
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ import com.tangem.core.ui.utils.parseBigDecimal
|
|||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.SendFeeClickIntents
|
||||
import com.tangem.features.send.v2.subcomponents.fee.model.converters.custom.CustomFeeConverter
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.tangem.core.ui.components.containers.FooterContainer
|
|||
import com.tangem.core.ui.components.inputrow.InputRowEnterAmount
|
||||
import com.tangem.core.ui.components.inputrow.InputRowEnterInfoAmount
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.CustomFeeFieldUM
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeType
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.blockchain.common.transaction.Fee
|
|||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.send.v2.subcomponents.fee.ui.state
|
|||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.features.feeselector.api.entity.CustomFeeFieldUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
|
|
|||
|
|
@ -239,6 +239,9 @@ include(":features:nft:impl")
|
|||
|
||||
include(":features:walletconnect:api")
|
||||
include(":features:walletconnect:impl")
|
||||
|
||||
include(":features:fee-selector:api")
|
||||
include(":features:fee-selector:impl")
|
||||
// endregion Feature modules
|
||||
|
||||
// region Domain modules
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue