Updated on 2026-08-14
This commit is contained in:
parent
084d4282f7
commit
7a10191880
6 changed files with 297 additions and 2 deletions
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.tap.di.routing
|
||||
|
||||
import com.tangem.tap.routing.RoutingComponent
|
||||
import com.tangem.tap.routing.impl.DefaultRoutingComponent
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.components.ActivityComponent
|
||||
import dagger.hilt.android.scopes.ActivityScoped
|
||||
|
||||
@Module
|
||||
@InstallIn(ActivityComponent::class)
|
||||
internal interface RoutingComponentModule {
|
||||
|
||||
@Binds
|
||||
@ActivityScoped
|
||||
fun bindRoutingComponentFactory(factory: DefaultRoutingComponent.Factory): RoutingComponent.Factory
|
||||
}
|
||||
33
app/src/main/java/com/tangem/tap/routing/RoutingComponent.kt
Normal file
33
app/src/main/java/com/tangem/tap/routing/RoutingComponent.kt
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package com.tangem.tap.routing
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.arkivanov.decompose.router.stack.ChildStack
|
||||
import com.arkivanov.decompose.value.Value
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.utils.Provider
|
||||
|
||||
internal interface RoutingComponent {
|
||||
|
||||
val router: Router
|
||||
|
||||
val stack: Value<ChildStack<AppRoute, Child>>
|
||||
|
||||
sealed class Child {
|
||||
|
||||
data object Initial : Child()
|
||||
|
||||
data class LegacyFragment(
|
||||
val name: String,
|
||||
val fragmentProvider: Provider<Fragment>,
|
||||
) : Child()
|
||||
|
||||
data class LegacyIntent(val intent: Intent) : Child()
|
||||
}
|
||||
|
||||
interface Factory {
|
||||
fun create(context: AppComponentContext): RoutingComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.tangem.tap.routing.impl
|
||||
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import com.arkivanov.decompose.router.stack.ChildStack
|
||||
import com.arkivanov.decompose.router.stack.childStack
|
||||
import com.arkivanov.decompose.value.Value
|
||||
import com.arkivanov.essenty.backhandler.BackCallback
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.navigation.getOrCreateTyped
|
||||
import com.tangem.tap.routing.RoutingComponent
|
||||
import com.tangem.tap.routing.RoutingComponent.Child
|
||||
import com.tangem.tap.routing.utils.ChildFactory
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class DefaultRoutingComponent @AssistedInject constructor(
|
||||
@Assisted context: AppComponentContext,
|
||||
private val childFactory: ChildFactory,
|
||||
) : RoutingComponent, AppComponentContext by context {
|
||||
|
||||
private val backCallback = BackCallback(priority = Int.MIN_VALUE, onBack = router::pop)
|
||||
|
||||
override val stack: Value<ChildStack<AppRoute, Child>> = childStack(
|
||||
source = navigationProvider.getOrCreateTyped(),
|
||||
serializer = AppRoute.serializer(),
|
||||
initialConfiguration = getInitialRoute(),
|
||||
handleBackButton = false,
|
||||
childFactory = ::child,
|
||||
)
|
||||
|
||||
init {
|
||||
backHandler.register(backCallback)
|
||||
}
|
||||
|
||||
private fun getInitialRoute(): AppRoute = AppRoute.Initial
|
||||
|
||||
private fun child(route: AppRoute, context: ComponentContext): Child {
|
||||
return childFactory.createChild(route, { childByContext(context) })
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : RoutingComponent.Factory {
|
||||
override fun create(context: AppComponentContext): DefaultRoutingComponent
|
||||
}
|
||||
}
|
||||
155
app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt
Normal file
155
app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
package com.tangem.tap.routing.utils
|
||||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.feature.qrscanning.QrScanningRouter
|
||||
import com.tangem.feature.referral.ReferralFragment
|
||||
import com.tangem.feature.swap.presentation.SwapFragment
|
||||
import com.tangem.features.details.component.DetailsComponent
|
||||
import com.tangem.features.send.api.navigation.SendRouter
|
||||
import com.tangem.features.staking.api.navigation.StakingRouter
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||
import com.tangem.features.wallet.navigation.WalletRouter
|
||||
import com.tangem.tap.features.customtoken.impl.presentation.AddCustomTokenFragment
|
||||
import com.tangem.tap.features.details.ui.appcurrency.AppCurrencySelectorFragment
|
||||
import com.tangem.tap.features.details.ui.appsettings.AppSettingsFragment
|
||||
import com.tangem.tap.features.details.ui.cardsettings.CardSettingsFragment
|
||||
import com.tangem.tap.features.details.ui.cardsettings.coderecovery.AccessCodeRecoveryFragment
|
||||
import com.tangem.tap.features.details.ui.resetcard.ResetCardFragment
|
||||
import com.tangem.tap.features.details.ui.securitymode.SecurityModeFragment
|
||||
import com.tangem.tap.features.details.ui.walletconnect.WalletConnectFragment
|
||||
import com.tangem.tap.features.disclaimer.ui.DisclaimerFragment
|
||||
import com.tangem.tap.features.home.HomeFragment
|
||||
import com.tangem.tap.features.main.ui.ModalNotificationBottomSheetFragment
|
||||
import com.tangem.tap.features.onboarding.products.note.OnboardingNoteFragment
|
||||
import com.tangem.tap.features.onboarding.products.otherCards.OnboardingOtherCardsFragment
|
||||
import com.tangem.tap.features.onboarding.products.twins.ui.OnboardingTwinsFragment
|
||||
import com.tangem.tap.features.onboarding.products.wallet.ui.OnboardingWalletFragment
|
||||
import com.tangem.tap.features.saveWallet.ui.SaveWalletBottomSheetFragment
|
||||
import com.tangem.tap.features.tokens.impl.presentation.TokensListFragment
|
||||
import com.tangem.tap.features.welcome.ui.WelcomeFragment
|
||||
import com.tangem.tap.routing.RoutingComponent.Child
|
||||
import com.tangem.utils.Provider
|
||||
import dagger.hilt.android.scopes.ActivityScoped
|
||||
import java.util.WeakHashMap
|
||||
import javax.inject.Inject
|
||||
|
||||
@ActivityScoped
|
||||
@Suppress("LongParameterList")
|
||||
internal class ChildFactory @Inject constructor(
|
||||
private val detailsComponentFactory: DetailsComponent.Factory,
|
||||
private val sendRouter: SendRouter,
|
||||
private val tokenDetailsRouter: TokenDetailsRouter,
|
||||
private val walletRouter: WalletRouter,
|
||||
private val qrScanningRouter: QrScanningRouter,
|
||||
private val stakingRouter: StakingRouter,
|
||||
) {
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
fun createChild(route: AppRoute, contextFactory: (route: AppRoute) -> AppComponentContext): Child {
|
||||
componentContexts[route] = contextFactory(route)
|
||||
|
||||
return when (route) {
|
||||
is AppRoute.Initial -> {
|
||||
Child.Initial
|
||||
}
|
||||
is AppRoute.AccessCodeRecovery -> {
|
||||
route.asFragmentChild(Provider { AccessCodeRecoveryFragment() })
|
||||
}
|
||||
is AppRoute.AddCustomToken -> {
|
||||
route.asFragmentChild(Provider { AddCustomTokenFragment() })
|
||||
}
|
||||
is AppRoute.AppCurrencySelector -> {
|
||||
route.asFragmentChild(Provider { AppCurrencySelectorFragment() })
|
||||
}
|
||||
is AppRoute.ModalNotification -> {
|
||||
route.asFragmentChild(Provider { ModalNotificationBottomSheetFragment() })
|
||||
}
|
||||
is AppRoute.SaveWallet -> {
|
||||
route.asFragmentChild(Provider { SaveWalletBottomSheetFragment() })
|
||||
}
|
||||
is AppRoute.Send -> {
|
||||
route.asFragmentChild(Provider { sendRouter.getEntryFragment() })
|
||||
}
|
||||
is AppRoute.AppSettings -> {
|
||||
route.asFragmentChild(Provider { AppSettingsFragment() })
|
||||
}
|
||||
is AppRoute.CardSettings -> {
|
||||
route.asFragmentChild(Provider { CardSettingsFragment() })
|
||||
}
|
||||
is AppRoute.Details -> {
|
||||
route.asComponentChild(
|
||||
contextProvider = contextProvider(route, contextFactory),
|
||||
params = DetailsComponent.Params(route.userWalletId),
|
||||
componentFactory = detailsComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.DetailsSecurity -> {
|
||||
route.asFragmentChild(Provider { SecurityModeFragment() })
|
||||
}
|
||||
is AppRoute.Disclaimer -> {
|
||||
route.asFragmentChild(Provider { DisclaimerFragment() })
|
||||
}
|
||||
is AppRoute.Home -> {
|
||||
route.asFragmentChild(Provider { HomeFragment() })
|
||||
}
|
||||
is AppRoute.ManageTokens -> {
|
||||
route.asFragmentChild(Provider { TokensListFragment() })
|
||||
}
|
||||
is AppRoute.OnboardingNote -> {
|
||||
route.asFragmentChild(Provider { OnboardingNoteFragment() })
|
||||
}
|
||||
is AppRoute.OnboardingOther -> {
|
||||
route.asFragmentChild(Provider { OnboardingOtherCardsFragment() })
|
||||
}
|
||||
is AppRoute.OnboardingTwins -> {
|
||||
route.asFragmentChild(Provider { OnboardingTwinsFragment() })
|
||||
}
|
||||
is AppRoute.OnboardingWallet -> {
|
||||
route.asFragmentChild(Provider { OnboardingWalletFragment() })
|
||||
}
|
||||
is AppRoute.QrScanning -> {
|
||||
route.asFragmentChild(Provider { qrScanningRouter.getEntryFragment() })
|
||||
}
|
||||
is AppRoute.ReferralProgram -> {
|
||||
route.asFragmentChild(Provider { ReferralFragment() })
|
||||
}
|
||||
is AppRoute.ResetToFactory -> {
|
||||
route.asFragmentChild(Provider { ResetCardFragment() })
|
||||
}
|
||||
is AppRoute.Swap -> {
|
||||
route.asFragmentChild(Provider { SwapFragment() })
|
||||
}
|
||||
is AppRoute.Wallet -> {
|
||||
route.asFragmentChild(Provider { walletRouter.getEntryFragment() })
|
||||
}
|
||||
is AppRoute.WalletConnectSessions -> {
|
||||
route.asFragmentChild(Provider { WalletConnectFragment() })
|
||||
}
|
||||
is AppRoute.CurrencyDetails -> {
|
||||
route.asFragmentChild(Provider { tokenDetailsRouter.getEntryFragment() })
|
||||
}
|
||||
is AppRoute.Welcome -> {
|
||||
route.asFragmentChild(Provider { WelcomeFragment() })
|
||||
}
|
||||
is AppRoute.TesterMenu -> {
|
||||
TODO("Will be implemented later")
|
||||
}
|
||||
is AppRoute.Staking -> {
|
||||
route.asFragmentChild(Provider { stakingRouter.getEntryFragment() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun contextProvider(
|
||||
appRoute: AppRoute,
|
||||
contextFactory: (route: AppRoute) -> AppComponentContext,
|
||||
): Provider<AppComponentContext> = Provider {
|
||||
componentContexts.getOrPut(appRoute) { contextFactory(appRoute) }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
val componentContexts = WeakHashMap<AppRoute, AppComponentContext>()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package com.tangem.tap.routing.utils
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.bundle.RouteBundleParams
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.ComposableContentComponent
|
||||
import com.tangem.tap.DecomposeFragment
|
||||
import com.tangem.tap.routing.RoutingComponent.Child
|
||||
import com.tangem.utils.Provider
|
||||
|
||||
internal fun AppRoute.asFragmentChild(fragmentProvider: Provider<Fragment>): Child {
|
||||
val provider = Provider {
|
||||
val bundle = (this as? RouteBundleParams)?.getBundle()
|
||||
|
||||
fragmentProvider().apply {
|
||||
arguments = bundle
|
||||
}
|
||||
}
|
||||
|
||||
return Child.LegacyFragment(path, provider)
|
||||
}
|
||||
|
||||
internal fun <C : ComposableContentComponent, P : Any, F : ComponentFactory<C, P>> AppRoute.asComponentChild(
|
||||
contextProvider: Provider<AppComponentContext>,
|
||||
params: P,
|
||||
componentFactory: F,
|
||||
): Child {
|
||||
val fragmentProvider = Provider {
|
||||
DecomposeFragment.newInstance(
|
||||
contextProvider = contextProvider,
|
||||
params = params,
|
||||
componentFactory = componentFactory,
|
||||
)
|
||||
}
|
||||
|
||||
return Child.LegacyFragment(path, fragmentProvider)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue