Updated on 2026-08-14
This commit is contained in:
parent
1526da80eb
commit
7bd4bd3d52
13 changed files with 9 additions and 388 deletions
|
|
@ -1,33 +1,8 @@
|
|||
package com.tangem.tap.common.extensions
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.*
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.FragmentShareTransition
|
||||
import com.tangem.feature.referral.ReferralFragment
|
||||
import com.tangem.feature.swap.presentation.SwapFragment
|
||||
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.details.DetailsFragment
|
||||
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.send.ui.SendFragment
|
||||
import com.tangem.tap.features.tokens.impl.presentation.TokensListFragment
|
||||
import com.tangem.tap.features.welcome.ui.WelcomeFragment
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.store
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.wallet.R
|
||||
import timber.log.Timber
|
||||
|
|
@ -73,138 +48,4 @@ private fun Fragment.showFragment(fragmentManager: FragmentManager, name: String
|
|||
transaction.addToBackStack(name)
|
||||
|
||||
transaction.commitAllowingStateLoss()
|
||||
}
|
||||
|
||||
fun FragmentActivity.openFragment(
|
||||
screen: AppScreen,
|
||||
addToBackstack: Boolean,
|
||||
bundle: Bundle? = null,
|
||||
fgShareTransition: FragmentShareTransition? = null,
|
||||
) {
|
||||
val transaction = supportFragmentManager.beginTransaction().apply {
|
||||
setReorderingAllowed(true)
|
||||
}
|
||||
|
||||
val fragment = fragmentFactory(screen).apply {
|
||||
arguments = bundle
|
||||
|
||||
if (fgShareTransition != null) {
|
||||
sharedElementEnterTransition = fgShareTransition.enterTransitionSet
|
||||
sharedElementReturnTransition = fgShareTransition.exitTransitionSet
|
||||
fgShareTransition.shareElements.forEach { shareElement ->
|
||||
shareElement.wView.get()?.let { view ->
|
||||
transaction.addSharedElement(view, shareElement.elementName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (screen.isDialogFragment && fragment is DialogFragment) {
|
||||
fragment.showAllowingStateLoss(
|
||||
fragmentManager = supportFragmentManager,
|
||||
baseTransaction = transaction,
|
||||
tag = screen.name,
|
||||
addToBackstack = addToBackstack,
|
||||
)
|
||||
} else {
|
||||
transaction.replace(R.id.fragment_container, fragment, screen.name)
|
||||
if (addToBackstack) {
|
||||
transaction.addToBackStack(screen.name)
|
||||
}
|
||||
transaction.commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun DialogFragment.showAllowingStateLoss(
|
||||
fragmentManager: FragmentManager,
|
||||
baseTransaction: FragmentTransaction,
|
||||
tag: String,
|
||||
addToBackstack: Boolean,
|
||||
) {
|
||||
runCatching {
|
||||
if (addToBackstack) baseTransaction.addToBackStack(tag)
|
||||
show(baseTransaction, tag)
|
||||
}
|
||||
.onFailure { throwable ->
|
||||
if (throwable is IllegalStateException) {
|
||||
val transaction = fragmentManager.beginTransaction()
|
||||
transaction.add(this, tag)
|
||||
if (addToBackstack) transaction.addToBackStack(tag)
|
||||
|
||||
transaction.commitAllowingStateLoss()
|
||||
} else {
|
||||
Timber.e(throwable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun FragmentActivity.popBackTo(screen: AppScreen?, inclusive: Boolean = false) {
|
||||
val inclusiveFlag = if (inclusive) FragmentManager.POP_BACK_STACK_INCLUSIVE else 0
|
||||
try {
|
||||
this.supportFragmentManager.popBackStack(screen?.name, inclusiveFlag)
|
||||
} catch (e: IllegalStateException) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun FragmentActivity.getPreviousScreen(): AppScreen? {
|
||||
val indexOfLastFragment = if (this.supportFragmentManager.backStackEntryCount > 0) {
|
||||
this.supportFragmentManager.backStackEntryCount - 1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
val tag = if (indexOfLastFragment < this.supportFragmentManager.backStackEntryCount) {
|
||||
this.supportFragmentManager.getBackStackEntryAt(indexOfLastFragment).name
|
||||
} else {
|
||||
null
|
||||
}
|
||||
return tag?.let { AppScreen.valueOf(tag) }
|
||||
}
|
||||
|
||||
@Suppress("ComplexMethod", "LongMethod")
|
||||
private fun fragmentFactory(screen: AppScreen): Fragment {
|
||||
return when (screen) {
|
||||
AppScreen.Home -> HomeFragment()
|
||||
AppScreen.OnboardingNote -> OnboardingNoteFragment()
|
||||
AppScreen.OnboardingWallet -> OnboardingWalletFragment()
|
||||
AppScreen.OnboardingTwins -> OnboardingTwinsFragment()
|
||||
AppScreen.OnboardingOther -> OnboardingOtherCardsFragment()
|
||||
AppScreen.Wallet -> {
|
||||
store.inject(getDependency = DaggerGraphState::walletRouter).getEntryFragment()
|
||||
}
|
||||
AppScreen.Send -> {
|
||||
val featureToggles = store.inject(getDependency = DaggerGraphState::sendFeatureToggles)
|
||||
|
||||
if (featureToggles.isRedesignedSendEnabled) {
|
||||
store.inject(getDependency = DaggerGraphState::sendRouter).getEntryFragment()
|
||||
} else {
|
||||
SendFragment()
|
||||
}
|
||||
}
|
||||
AppScreen.Details -> {
|
||||
DetailsFragment()
|
||||
}
|
||||
AppScreen.DetailsSecurity -> SecurityModeFragment()
|
||||
AppScreen.CardSettings -> CardSettingsFragment()
|
||||
AppScreen.AppSettings -> AppSettingsFragment()
|
||||
AppScreen.ResetToFactory -> ResetCardFragment()
|
||||
AppScreen.AccessCodeRecovery -> AccessCodeRecoveryFragment()
|
||||
AppScreen.Disclaimer -> DisclaimerFragment()
|
||||
AppScreen.ManageTokens -> TokensListFragment()
|
||||
AppScreen.AddCustomToken -> AddCustomTokenFragment()
|
||||
AppScreen.WalletDetails -> {
|
||||
store.inject(getDependency = DaggerGraphState::tokenDetailsRouter).getEntryFragment()
|
||||
}
|
||||
AppScreen.WalletConnectSessions -> WalletConnectFragment()
|
||||
AppScreen.QrScanning -> {
|
||||
store.inject(getDependency = DaggerGraphState::qrScanningRouter).getEntryFragment()
|
||||
}
|
||||
AppScreen.ReferralProgram -> ReferralFragment()
|
||||
AppScreen.Swap -> SwapFragment()
|
||||
AppScreen.Welcome -> WelcomeFragment()
|
||||
AppScreen.SaveWallet -> SaveWalletBottomSheetFragment()
|
||||
AppScreen.AppCurrencySelector -> AppCurrencySelectorFragment()
|
||||
AppScreen.ModalNotification -> ModalNotificationBottomSheetFragment()
|
||||
AppScreen.Staking -> store.inject(getDependency = DaggerGraphState::stakingRouter).getEntryFragment()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.tap.common.redux
|
||||
|
||||
import com.tangem.tap.common.redux.global.globalReducer
|
||||
import com.tangem.tap.common.redux.navigation.NavigationReducer
|
||||
import com.tangem.tap.features.details.redux.DetailsReducer
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectReducer
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerReducer
|
||||
|
|
@ -23,7 +22,6 @@ fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder)
|
|||
if (action is AppAction.RestoreState) return action.state
|
||||
|
||||
return AppState(
|
||||
navigationState = NavigationReducer.reduce(action, state),
|
||||
globalState = globalReducer(action, state, appStateHolder),
|
||||
homeState = HomeReducer.reduce(action, state),
|
||||
onboardingNoteState = OnboardingNoteReducer.reduce(action, state),
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
package com.tangem.tap.common.redux
|
||||
|
||||
import com.tangem.core.navigation.NavigationState
|
||||
import com.tangem.domain.redux.DomainState
|
||||
import com.tangem.domain.redux.domainStore
|
||||
import com.tangem.domain.redux.global.NetworkServices
|
||||
import com.tangem.tap.common.redux.global.GlobalMiddleware
|
||||
import com.tangem.tap.common.redux.global.GlobalState
|
||||
import com.tangem.tap.common.redux.legacy.LegacyMiddleware
|
||||
import com.tangem.tap.common.redux.navigation.navigationMiddleware
|
||||
import com.tangem.tap.features.details.redux.DetailsMiddleware
|
||||
import com.tangem.tap.features.details.redux.DetailsState
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectMiddleware
|
||||
|
|
@ -40,7 +38,6 @@ import org.rekotlin.Middleware
|
|||
import org.rekotlin.StateType
|
||||
|
||||
data class AppState(
|
||||
val navigationState: NavigationState = NavigationState(),
|
||||
val globalState: GlobalState = GlobalState(),
|
||||
val homeState: HomeState = HomeState(),
|
||||
val onboardingNoteState: OnboardingNoteState = OnboardingNoteState(),
|
||||
|
|
@ -73,7 +70,6 @@ data class AppState(
|
|||
fun getMiddleware(): List<Middleware<AppState>> {
|
||||
return listOf(
|
||||
logMiddleware,
|
||||
navigationMiddleware,
|
||||
notificationsMiddleware,
|
||||
GlobalMiddleware.handler,
|
||||
HomeMiddleware.handler,
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
package com.tangem.tap.common.redux.navigation
|
||||
|
||||
import android.content.Intent
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.openFragment
|
||||
import com.tangem.tap.common.extensions.popBackTo
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.store
|
||||
import org.rekotlin.Middleware
|
||||
|
||||
val navigationMiddleware: Middleware<AppState> = { _, state ->
|
||||
{ next ->
|
||||
{ action ->
|
||||
if (action is NavigationAction) {
|
||||
val navState = state()?.navigationState
|
||||
when (action) {
|
||||
is NavigationAction.NavigateTo -> {
|
||||
navState?.activity?.get()?.openFragment(
|
||||
screen = action.screen,
|
||||
addToBackstack = action.addToBackstack,
|
||||
fgShareTransition = action.fragmentShareTransition,
|
||||
bundle = action.bundle,
|
||||
)
|
||||
}
|
||||
is NavigationAction.PopBackTo -> {
|
||||
if (navState?.backStack?.lastOrNull() != action.screen) {
|
||||
when (val screen = action.screen) {
|
||||
AppScreen.Home,
|
||||
AppScreen.Welcome,
|
||||
-> {
|
||||
if (navState?.backStack?.contains(screen) == false) {
|
||||
// Pop back to activity
|
||||
navState.activity?.get()?.popBackTo(screen = null, inclusive = true)
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(screen))
|
||||
} else {
|
||||
navState?.activity?.get()?.popBackTo(screen, action.inclusive)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
navState?.activity?.get()?.popBackTo(screen, action.inclusive)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is NavigationAction.OpenDocument -> {
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.data = action.url
|
||||
navState?.activity?.get()?.startActivity(intent)
|
||||
}
|
||||
is NavigationAction.ActivityCreated,
|
||||
is NavigationAction.ActivityDestroyed,
|
||||
-> Unit
|
||||
}
|
||||
}
|
||||
next(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
package com.tangem.tap.common.redux.navigation
|
||||
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.navigation.NavigationState
|
||||
import com.tangem.tap.common.extensions.getPreviousScreen
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import org.rekotlin.Action
|
||||
|
||||
object NavigationReducer {
|
||||
fun reduce(action: Action, state: AppState): NavigationState = internalReduce(action, state)
|
||||
}
|
||||
|
||||
private fun internalReduce(action: Action, state: AppState): NavigationState {
|
||||
val navigationAction = action as? NavigationAction ?: return state.navigationState
|
||||
val navState = state.navigationState
|
||||
|
||||
return when (navigationAction) {
|
||||
is NavigationAction.NavigateTo -> {
|
||||
navState.copy(backStack = navState.backStack + navigationAction.screen)
|
||||
}
|
||||
is NavigationAction.PopBackTo -> {
|
||||
if (navState.backStack.lastOrNull() == navigationAction.screen) return navState
|
||||
|
||||
val screen = navigationAction.screen ?: navState.activity?.get()?.getPreviousScreen()
|
||||
val index = navState.backStack.lastIndexOf(screen) + 1
|
||||
state.navigationState.copy(backStack = navState.backStack.subList(0, index))
|
||||
}
|
||||
is NavigationAction.ActivityCreated -> navState.copy(activity = navigationAction.activity)
|
||||
is NavigationAction.ActivityDestroyed -> {
|
||||
when {
|
||||
// Destroy the activity if it invoked for the same activity. Prevents overwriting to null if there is a
|
||||
// new scan from the background [REDACTED_TASK_KEY]
|
||||
navState.activity?.get() == navigationAction.activity.get() -> navState.copy(activity = null)
|
||||
else -> navState
|
||||
}
|
||||
}
|
||||
else -> navState
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue