Updated on 2026-08-14
This commit is contained in:
parent
2782d8a846
commit
8262c72f40
15 changed files with 230 additions and 18 deletions
|
|
@ -12,6 +12,7 @@ import com.google.android.material.snackbar.Snackbar
|
|||
import com.tangem.TangemSdk
|
||||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.features.tester.api.TesterRouter
|
||||
import com.tangem.features.wallet.navigation.WalletRouter
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.sdk.extensions.init
|
||||
import com.tangem.tap.common.ActivityResultCallbackHolder
|
||||
|
|
@ -86,6 +87,9 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
@Inject
|
||||
lateinit var scanCardUseCase: ScanCardUseCase
|
||||
|
||||
@Inject
|
||||
lateinit var walletRouter: WalletRouter
|
||||
|
||||
private var snackbar: Snackbar? = null
|
||||
private val dialogManager = DialogManager()
|
||||
private val binding: ActivityMainBinding by viewBinding(ActivityMainBinding::bind)
|
||||
|
|
@ -113,7 +117,13 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
),
|
||||
)
|
||||
|
||||
store.dispatch(DaggerGraphAction.SetActivityDependencies(testerRouter, scanCardUseCase))
|
||||
store.dispatch(
|
||||
DaggerGraphAction.SetActivityDependencies(
|
||||
testerRouter = testerRouter,
|
||||
scanCardUseCase = scanCardUseCase,
|
||||
walletRouter = walletRouter,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun initUserWalletsListManager() {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import com.tangem.tap.proxy.redux.DaggerGraphState
|
|||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import timber.log.Timber
|
||||
import com.tangem.feature.wallet.presentation.WalletFragment as RedesignedWalletFragment
|
||||
import com.tangem.tap.features.customtoken.impl.presentation.AddCustomTokenFragment as RedesignedAddCustomTokenFragment
|
||||
|
||||
fun FragmentActivity.openFragment(
|
||||
|
|
@ -140,7 +139,9 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
|
|||
getDependency = DaggerGraphState::walletFeatureToggles,
|
||||
)
|
||||
if (featureToggles.isRedesignedScreenEnabled) {
|
||||
RedesignedWalletFragment()
|
||||
store.state.daggerGraphState
|
||||
.get(getDependency = DaggerGraphState::walletRouter)
|
||||
.getEntryFragment()
|
||||
} else {
|
||||
WalletFragment()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.proxy.redux
|
|||
|
||||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.features.tester.api.TesterRouter
|
||||
import com.tangem.features.wallet.navigation.WalletRouter
|
||||
import org.rekotlin.Action
|
||||
|
||||
sealed interface DaggerGraphAction : Action {
|
||||
|
|
@ -9,5 +10,6 @@ sealed interface DaggerGraphAction : Action {
|
|||
data class SetActivityDependencies(
|
||||
val testerRouter: TesterRouter,
|
||||
val scanCardUseCase: ScanCardUseCase,
|
||||
val walletRouter: WalletRouter,
|
||||
) : DaggerGraphAction
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ object DaggerGraphReducer {
|
|||
is DaggerGraphAction.SetActivityDependencies -> state.daggerGraphState.copy(
|
||||
testerRouter = action.testerRouter,
|
||||
scanCardUseCase = action.scanCardUseCase,
|
||||
walletRouter = action.walletRouter,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.datasource.connection.NetworkConnectionManager
|
|||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.features.tester.api.TesterRouter
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import com.tangem.features.wallet.navigation.WalletRouter
|
||||
import com.tangem.tap.features.customtoken.api.featuretoggles.CustomTokenFeatureToggles
|
||||
import org.rekotlin.StateType
|
||||
|
||||
|
|
@ -15,6 +16,7 @@ data class DaggerGraphState(
|
|||
val customTokenFeatureToggles: CustomTokenFeatureToggles? = null,
|
||||
val scanCardUseCase: ScanCardUseCase? = null,
|
||||
val walletFeatureToggles: WalletFeatureToggles? = null,
|
||||
val walletRouter: WalletRouter? = null,
|
||||
) : StateType {
|
||||
|
||||
inline fun <reified T> get(getDependency: DaggerGraphState.() -> T?): T {
|
||||
|
|
|
|||
|
|
@ -2,4 +2,9 @@ plugins {
|
|||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
/** AndroidX */
|
||||
implementation(deps.androidx.fragment.ktx)
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.features.wallet.navigation
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
/**
|
||||
* Wallet feature router
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface WalletRouter {
|
||||
|
||||
/** Get feature entry point [Fragment] */
|
||||
fun getEntryFragment(): Fragment
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.feature.wallet.di
|
||||
|
||||
import com.tangem.feature.wallet.presentation.router.DefaultWalletRouter
|
||||
import com.tangem.features.wallet.navigation.WalletRouter
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.components.ActivityComponent
|
||||
import dagger.hilt.android.scopes.ActivityScoped
|
||||
|
||||
@Module
|
||||
@InstallIn(ActivityComponent::class)
|
||||
internal object WalletRouterModule {
|
||||
|
||||
@Provides
|
||||
@ActivityScoped
|
||||
fun provideWalletRouter(): WalletRouter = DefaultWalletRouter()
|
||||
}
|
||||
|
|
@ -8,9 +8,11 @@ import android.view.ViewGroup
|
|||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
import com.tangem.features.wallet.navigation.WalletRouter
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Wallet fragment
|
||||
|
|
@ -18,7 +20,16 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class WalletFragment : Fragment() {
|
||||
internal class WalletFragment : Fragment() {
|
||||
|
||||
/** Feature router */
|
||||
@Inject
|
||||
internal lateinit var walletRouter: WalletRouter
|
||||
|
||||
private val _walletRouter: InnerWalletRouter
|
||||
get() = requireNotNull(walletRouter as? InnerWalletRouter) {
|
||||
"_walletRouter should be instance of InnerWalletRouter"
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) }
|
||||
|
|
@ -31,11 +42,14 @@ class WalletFragment : Fragment() {
|
|||
return ComposeView(inflater.context).apply {
|
||||
setContent {
|
||||
isTransitionGroup = true
|
||||
|
||||
TangemTheme {
|
||||
// TODO: [REDACTED_TASK_KEY] Call WalletScreen
|
||||
}
|
||||
_walletRouter.Initialize()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
/** Create wallet fragment instance */
|
||||
fun create(): WalletFragment = WalletFragment()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package com.tangem.feature.wallet.presentation.router
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.presentation.WalletFragment
|
||||
import com.tangem.feature.wallet.presentation.ui.WalletScreen
|
||||
import com.tangem.feature.wallet.presentation.viewmodels.WalletViewModel
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
/** Default implementation of wallet feature router */
|
||||
internal class DefaultWalletRouter : InnerWalletRouter {
|
||||
|
||||
private var navController: NavHostController by Delegates.notNull()
|
||||
|
||||
override fun getEntryFragment(): Fragment = WalletFragment.create()
|
||||
|
||||
@Composable
|
||||
override fun Initialize() {
|
||||
TangemTheme {
|
||||
NavHost(
|
||||
navController = rememberNavController().apply { navController = this },
|
||||
startDestination = WalletScreens.WALLET.name,
|
||||
) {
|
||||
composable(WalletScreens.WALLET.name) {
|
||||
val viewModel = hiltViewModel<WalletViewModel>().apply { router = this@DefaultWalletRouter }
|
||||
WalletScreen(state = viewModel.uiState)
|
||||
}
|
||||
|
||||
composable(WalletScreens.ORGANIZE_TOKENS.name) {
|
||||
BackHandler(onBack = ::popBackStack)
|
||||
// TODO: Add OrganizeTokensScreen
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun popBackStack() {
|
||||
navController.popBackStack()
|
||||
}
|
||||
|
||||
override fun openOrganizeTokensScreen() {
|
||||
navController.navigate(WalletScreens.ORGANIZE_TOKENS.name)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.feature.wallet.presentation.router
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.tangem.features.wallet.navigation.WalletRouter
|
||||
|
||||
/**
|
||||
* Interface of inner wallet feature router
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal interface InnerWalletRouter : WalletRouter {
|
||||
|
||||
/** Initialize router */
|
||||
@Suppress("TopLevelComposableFunctions")
|
||||
@Composable
|
||||
fun Initialize()
|
||||
|
||||
/** Pop back stack */
|
||||
fun popBackStack()
|
||||
|
||||
/** Open organize tokens screen */
|
||||
fun openOrganizeTokensScreen()
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.feature.wallet.presentation.router
|
||||
|
||||
/**
|
||||
* Wallet feature screens
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
enum class WalletScreens {
|
||||
WALLET, ORGANIZE_TOKENS
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.ui
|
|||
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.feature.wallet.presentation.state.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.state.WalletStateHolder
|
||||
import java.util.UUID
|
||||
|
||||
internal object WalletPreviewData {
|
||||
|
|
@ -38,4 +39,13 @@ internal object WalletPreviewData {
|
|||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = {},
|
||||
)
|
||||
|
||||
val walletScreenState = WalletStateHolder(
|
||||
onBackClick = {},
|
||||
headerConfig = WalletStateHolder.HeaderConfig(
|
||||
wallets = listOf(walletCardContent, walletCardLoading, walletCardHiddenContent, walletCardError),
|
||||
onScanCardClick = {},
|
||||
onMoreClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,11 +1,17 @@
|
|||
package com.tangem.feature.wallet.presentation.ui.components
|
||||
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.LocalOverscrollConfiguration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.res.painterResource
|
||||
|
|
@ -26,6 +32,7 @@ import com.tangem.feature.wallet.presentation.ui.WalletPreviewData
|
|||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
internal fun WalletHeader(config: WalletStateHolder.HeaderConfig) {
|
||||
Column(
|
||||
|
|
@ -34,15 +41,23 @@ internal fun WalletHeader(config: WalletStateHolder.HeaderConfig) {
|
|||
.padding(bottom = TangemTheme.dimens.spacing14),
|
||||
) {
|
||||
TopBar(onScanCardClick = config.onScanCardClick, onMoreClick = config.onMoreClick)
|
||||
LazyRow(
|
||||
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||
) {
|
||||
items(items = config.wallets, key = WalletCardState::id) { state ->
|
||||
WalletCard(
|
||||
state = state,
|
||||
modifier = Modifier.width(LocalConfiguration.current.screenWidthDp.dp - TangemTheme.dimens.size32),
|
||||
)
|
||||
|
||||
CompositionLocalProvider(LocalOverscrollConfiguration provides null) {
|
||||
val lazyListState = rememberLazyListState()
|
||||
LazyRow(
|
||||
state = lazyListState,
|
||||
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||
flingBehavior = rememberSnapFlingBehavior(lazyListState = lazyListState),
|
||||
) {
|
||||
items(items = config.wallets, key = WalletCardState::id) { state ->
|
||||
WalletCard(
|
||||
state = state,
|
||||
modifier = Modifier.width(
|
||||
LocalConfiguration.current.screenWidthDp.dp - TangemTheme.dimens.size32,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
package com.tangem.feature.wallet.presentation.viewmodels
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
import com.tangem.feature.wallet.presentation.state.WalletStateHolder
|
||||
import com.tangem.feature.wallet.presentation.ui.WalletPreviewData
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
/**
|
||||
* Wallet screen view model
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@HiltViewModel
|
||||
internal class WalletViewModel @Inject constructor() : ViewModel() {
|
||||
|
||||
/** Feature router */
|
||||
var router: InnerWalletRouter by Delegates.notNull()
|
||||
|
||||
/** Screen state */
|
||||
var uiState by mutableStateOf(getInitialState())
|
||||
private set
|
||||
|
||||
// TODO: [REDACTED_TASK_KEY] Use production data instead of WalletPreviewData
|
||||
private fun getInitialState(): WalletStateHolder = WalletPreviewData.walletScreenState.copy(
|
||||
onBackClick = { router.popBackStack() },
|
||||
headerConfig = WalletPreviewData.walletScreenState.headerConfig.copy(
|
||||
onScanCardClick = { router.openOrganizeTokensScreen() },
|
||||
),
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue