Updated on 2026-08-14
This commit is contained in:
parent
401e4f8a90
commit
6e40671419
9 changed files with 411 additions and 7 deletions
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.tap.features.customtoken.impl.di
|
||||
|
||||
import com.tangem.tap.features.customtoken.impl.presentation.routers.CustomTokenRouter
|
||||
import com.tangem.tap.features.customtoken.impl.presentation.routers.DefaultCustomTokenRouter
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.components.ViewModelComponent
|
||||
import dagger.hilt.android.scopes.ViewModelScoped
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Module
|
||||
@InstallIn(ViewModelComponent::class)
|
||||
internal object CustomTokenRouterModule {
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideAddCustomTokenRouter(): CustomTokenRouter = DefaultCustomTokenRouter()
|
||||
}
|
||||
|
|
@ -0,0 +1,269 @@
|
|||
package com.tangem.tap.features.customtoken.impl.presentation.models
|
||||
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.tangem.tap.features.details.ui.cardsettings.TextReference
|
||||
import com.tangem.wallet.R
|
||||
|
||||
/**
|
||||
* Toolbar model of add custom token screen
|
||||
*
|
||||
* @property title title
|
||||
* @property onBackButtonClick lambda be invoked when back button is been pressed
|
||||
*/
|
||||
internal data class AddCustomTokensToolbar(val title: TextReference, val onBackButtonClick: () -> Unit)
|
||||
|
||||
/**
|
||||
* Model of block with fields for testing
|
||||
*
|
||||
* @property chooseTokenButtonText choose token button text
|
||||
* @property clearButtonText clear button text
|
||||
* @property resetButtonText reset button text
|
||||
* @property onClearAddressButtonClick lambda be invoked when clear address button is been pressed
|
||||
* @property onResetButtonClick lambda be invoked when reset form fields button is been pressed
|
||||
*/
|
||||
internal data class AddCustomTokenTestBlock(
|
||||
val chooseTokenButtonText: String,
|
||||
val clearButtonText: String,
|
||||
val resetButtonText: String,
|
||||
val onClearAddressButtonClick: () -> Unit,
|
||||
val onResetButtonClick: () -> Unit,
|
||||
)
|
||||
|
||||
/**
|
||||
* Bottom sheet model for choose custom token
|
||||
*
|
||||
* @property categoriesBlocks tokens categories
|
||||
* @property onTestTokenClick lambda be invoked when token is been pressed
|
||||
*/
|
||||
internal data class AddCustomTokenChooseTokenBottomSheet(
|
||||
val categoriesBlocks: List<TokensCategoryBlock>,
|
||||
val onTestTokenClick: (String) -> Unit,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Tokens category model
|
||||
*
|
||||
* @property name category name
|
||||
* @property items category items
|
||||
*/
|
||||
data class TokensCategoryBlock(val name: String, val items: List<TestTokenItem>)
|
||||
|
||||
/**
|
||||
* Test token model
|
||||
*
|
||||
* @property name token name
|
||||
* @property address token address
|
||||
*/
|
||||
data class TestTokenItem(val name: String, val address: String)
|
||||
}
|
||||
|
||||
/**
|
||||
* Form with fields model of add custom token screen
|
||||
*
|
||||
* @property contractAddressInputField input field to enter the contract address
|
||||
* @property networkSelectorField selector field to select the token network
|
||||
* @property tokenNameInputField input field to enter the token name
|
||||
* @property tokenSymbolInputField input field to enter the token symbol
|
||||
* @property decimalsInputField input field to enter the token decimals
|
||||
* @property derivationPathSelectorField selector field to select the derivation path
|
||||
*/
|
||||
internal data class AddCustomTokenForm(
|
||||
val contractAddressInputField: AddCustomTokenInputField.ContactAddress,
|
||||
val networkSelectorField: AddCustomTokenSelectorField.Network,
|
||||
val tokenNameInputField: AddCustomTokenInputField.TokenName,
|
||||
val tokenSymbolInputField: AddCustomTokenInputField.TokenSymbol,
|
||||
val decimalsInputField: AddCustomTokenInputField.Decimals,
|
||||
val derivationPathSelectorField: AddCustomTokenSelectorField.DerivationPath?,
|
||||
)
|
||||
|
||||
/** Base input field model of add custom token screen */
|
||||
internal sealed interface AddCustomTokenInputField {
|
||||
|
||||
/** Current value */
|
||||
val value: String
|
||||
|
||||
/** Lambda be invoked when value is been changed */
|
||||
val onValueChange: (String) -> Unit
|
||||
|
||||
/** Keyboard options */
|
||||
val keyboardOptions: KeyboardOptions
|
||||
|
||||
/** Label */
|
||||
val label: TextReference
|
||||
|
||||
/** Input availability */
|
||||
val isEnabled: Boolean
|
||||
|
||||
/** Flag that determine if current value has error */
|
||||
val isError: Boolean
|
||||
|
||||
/** Placeholder (hint) */
|
||||
val placeholder: TextReference
|
||||
|
||||
/** Flag that determine the processing of current value */
|
||||
val isLoading: Boolean
|
||||
|
||||
/**
|
||||
* Input field model to enter the contract address
|
||||
*
|
||||
* @property value current value
|
||||
* @property onValueChange lambda be invoked when value is been changed
|
||||
* @property isError flag that determine if current value has error
|
||||
* @property isLoading flag that determine the processing of current value
|
||||
*/
|
||||
data class ContactAddress(
|
||||
override val value: String,
|
||||
override val onValueChange: (String) -> Unit,
|
||||
override val isError: Boolean,
|
||||
override val isLoading: Boolean,
|
||||
) : AddCustomTokenInputField {
|
||||
override val isEnabled = true
|
||||
override val keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next)
|
||||
override val label = TextReference.Res(R.string.custom_token_contract_address_input_title)
|
||||
override val placeholder = TextReference.Str(value = "0x0000000000000000000000000000000000000000")
|
||||
}
|
||||
|
||||
/**
|
||||
* Input field model to enter the token name
|
||||
*
|
||||
* @property value current value
|
||||
* @property onValueChange lambda be invoked when value is been changed
|
||||
* @property isEnabled input availability
|
||||
* @property isError flag that determine if current value has error
|
||||
*/
|
||||
data class TokenName(
|
||||
override val value: String,
|
||||
override val onValueChange: (String) -> Unit,
|
||||
override val isEnabled: Boolean,
|
||||
override val isError: Boolean,
|
||||
) : AddCustomTokenInputField {
|
||||
override val keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next)
|
||||
override val label = TextReference.Res(R.string.custom_token_name_input_title)
|
||||
override val placeholder = TextReference.Res(id = R.string.custom_token_name_input_placeholder)
|
||||
override val isLoading = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Input field model to enter the token symbol
|
||||
*
|
||||
* @property value current value
|
||||
* @property onValueChange lambda be invoked when value is been changed
|
||||
* @property isEnabled input availability
|
||||
* @property isError flag that determine if current value has error
|
||||
*/
|
||||
data class TokenSymbol(
|
||||
override val value: String,
|
||||
override val onValueChange: (String) -> Unit,
|
||||
override val isEnabled: Boolean,
|
||||
override val isError: Boolean,
|
||||
) : AddCustomTokenInputField {
|
||||
override val keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next)
|
||||
override val label = TextReference.Res(R.string.custom_token_token_symbol_input_title)
|
||||
override val placeholder = TextReference.Res(id = R.string.custom_token_token_symbol_input_placeholder)
|
||||
override val isLoading = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Input field model to enter the token decimals
|
||||
*
|
||||
* @property value current value
|
||||
* @property onValueChange lambda be invoked when value is been changed
|
||||
* @property isEnabled input availability
|
||||
* @property isError flag that determine if current value has error
|
||||
*/
|
||||
data class Decimals(
|
||||
override val value: String,
|
||||
override val onValueChange: (String) -> Unit,
|
||||
override val isEnabled: Boolean,
|
||||
override val isError: Boolean,
|
||||
) : AddCustomTokenInputField {
|
||||
override val keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Next)
|
||||
override val label = TextReference.Res(R.string.custom_token_decimals_input_title)
|
||||
override val placeholder = TextReference.Str(value = "8")
|
||||
override val isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
/** Base selector field model of add custom token screen */
|
||||
internal sealed interface AddCustomTokenSelectorField {
|
||||
|
||||
/** Selection availability */
|
||||
val isEnabled: Boolean
|
||||
|
||||
/** Label string resource id */
|
||||
val label: TextReference
|
||||
|
||||
/** Selected menu item */
|
||||
val selectedItem: SelectorItem
|
||||
|
||||
/** Menu items */
|
||||
val items: List<SelectorItem>
|
||||
|
||||
/** Lambda be invoked when menu item is been selected */
|
||||
val onMenuItemClick: (Int) -> Unit
|
||||
|
||||
/**
|
||||
* Network selector model
|
||||
*
|
||||
* @property selectedItem selected menu item
|
||||
* @property items menu items
|
||||
* @property onMenuItemClick lambda be invoked when menu item is been selected
|
||||
*/
|
||||
data class Network(
|
||||
override val selectedItem: SelectorItem.Title,
|
||||
override val items: List<SelectorItem.Title>,
|
||||
override val onMenuItemClick: (Int) -> Unit,
|
||||
) : AddCustomTokenSelectorField {
|
||||
override val isEnabled = true
|
||||
override val label = TextReference.Res(R.string.custom_token_network_input_title)
|
||||
}
|
||||
|
||||
/**
|
||||
* Derivation path selector model
|
||||
*
|
||||
* @property isEnabled selection availability
|
||||
* @property selectedItem selected menu item
|
||||
* @property items menu items
|
||||
* @property onMenuItemClick lambda be invoked when menu item is been selected
|
||||
*/
|
||||
data class DerivationPath(
|
||||
override val isEnabled: Boolean,
|
||||
override val selectedItem: SelectorItem.TitleWithSubtitle,
|
||||
override val items: List<SelectorItem.TitleWithSubtitle>,
|
||||
override val onMenuItemClick: (Int) -> Unit,
|
||||
) : AddCustomTokenSelectorField {
|
||||
override val label = TextReference.Res(R.string.custom_token_derivation_path_input_title)
|
||||
}
|
||||
|
||||
/** Base menu item model */
|
||||
sealed interface SelectorItem {
|
||||
|
||||
/** Title */
|
||||
val title: TextReference
|
||||
|
||||
/**
|
||||
* Menu item with title
|
||||
*
|
||||
* @property title title text
|
||||
*/
|
||||
data class Title(override val title: TextReference) : SelectorItem
|
||||
|
||||
/**
|
||||
* Menu item with title ans subtitle
|
||||
*
|
||||
* @property title title text
|
||||
* @property subtitle subtitle text
|
||||
*/
|
||||
data class TitleWithSubtitle(override val title: TextReference, val subtitle: TextReference) : SelectorItem
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Floating button of add custom token screen
|
||||
*
|
||||
* @property isEnabled button availability
|
||||
* @property onClick lambda be invoked when button is been pressed
|
||||
*/
|
||||
internal data class AddCustomTokenFloatingButton(val isEnabled: Boolean, val onClick: () -> Unit)
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.tap.features.customtoken.impl.presentation.routers
|
||||
|
||||
/**
|
||||
* Custom token feature router
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal interface CustomTokenRouter {
|
||||
|
||||
/** Return to last screen */
|
||||
fun popBackStack()
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.tap.features.customtoken.impl.presentation.routers
|
||||
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.store
|
||||
|
||||
/** Default implementation of custom token feature router */
|
||||
internal class DefaultCustomTokenRouter : CustomTokenRouter {
|
||||
|
||||
override fun popBackStack() {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
package com.tangem.tap.features.customtoken.impl.presentation.states
|
||||
|
||||
import com.tangem.tap.features.customtoken.impl.presentation.models.AddCustomTokenChooseTokenBottomSheet
|
||||
import com.tangem.tap.features.customtoken.impl.presentation.models.AddCustomTokenFloatingButton
|
||||
import com.tangem.tap.features.customtoken.impl.presentation.models.AddCustomTokenForm
|
||||
import com.tangem.tap.features.customtoken.impl.presentation.models.AddCustomTokenTestBlock
|
||||
import com.tangem.tap.features.customtoken.impl.presentation.models.AddCustomTokensToolbar
|
||||
import com.tangem.tap.features.details.ui.cardsettings.TextReference
|
||||
|
||||
/**
|
||||
* State holder of add custom token screen
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal sealed interface AddCustomTokenStateHolder {
|
||||
|
||||
/** Lambda be invoked when system back action is been called */
|
||||
val onBackButtonClick: () -> Unit
|
||||
|
||||
/** Toolbar model */
|
||||
val toolbar: AddCustomTokensToolbar
|
||||
|
||||
/** Form model */
|
||||
val form: AddCustomTokenForm
|
||||
|
||||
/** Warnings */
|
||||
val warnings: List<TextReference>
|
||||
|
||||
/** Floating button model */
|
||||
val floatingButton: AddCustomTokenFloatingButton
|
||||
|
||||
/**
|
||||
* Util function that allow to make a copy
|
||||
*
|
||||
* @param onBackButtonClick lambda be invoked when system back action is been called
|
||||
* @param toolbar toolbar model
|
||||
* @param form form model
|
||||
* @param warnings warnings
|
||||
* @param floatingButton floating button model
|
||||
*/
|
||||
fun copySealed(
|
||||
onBackButtonClick: () -> Unit = this.onBackButtonClick,
|
||||
toolbar: AddCustomTokensToolbar = this.toolbar,
|
||||
form: AddCustomTokenForm = this.form,
|
||||
warnings: List<TextReference> = this.warnings,
|
||||
floatingButton: AddCustomTokenFloatingButton = this.floatingButton,
|
||||
): AddCustomTokenStateHolder {
|
||||
return when (this) {
|
||||
is Content -> copy(onBackButtonClick, toolbar, form, warnings, floatingButton)
|
||||
is TestContent -> copy(onBackButtonClick, toolbar, form, warnings, floatingButton)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Content state
|
||||
*
|
||||
* @property onBackButtonClick lambda be invoked when system back action is been called
|
||||
* @property toolbar toolbar model
|
||||
* @property form form model
|
||||
* @property warnings warnings
|
||||
* @property floatingButton floating button model
|
||||
*/
|
||||
data class Content(
|
||||
override val onBackButtonClick: () -> Unit,
|
||||
override val toolbar: AddCustomTokensToolbar,
|
||||
override val form: AddCustomTokenForm,
|
||||
override val warnings: List<TextReference>,
|
||||
override val floatingButton: AddCustomTokenFloatingButton,
|
||||
) : AddCustomTokenStateHolder
|
||||
|
||||
/**
|
||||
* Content state with fields for testing
|
||||
*
|
||||
* @property onBackButtonClick lambda be invoked when system back action is been called
|
||||
* @property toolbar toolbar model
|
||||
* @property form form model
|
||||
* @property warnings warnings
|
||||
* @property floatingButton floating button model
|
||||
* @property testBlock test block model
|
||||
* @property bottomSheet bottom sheet model
|
||||
*/
|
||||
data class TestContent(
|
||||
override val onBackButtonClick: () -> Unit,
|
||||
override val toolbar: AddCustomTokensToolbar,
|
||||
override val form: AddCustomTokenForm,
|
||||
override val warnings: List<TextReference>,
|
||||
override val floatingButton: AddCustomTokenFloatingButton,
|
||||
val testBlock: AddCustomTokenTestBlock,
|
||||
val bottomSheet: AddCustomTokenChooseTokenBottomSheet,
|
||||
) : AddCustomTokenStateHolder
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue