Updated on 2026-08-14
This commit is contained in:
commit
d95e16e3c4
6 changed files with 87 additions and 20 deletions
|
|
@ -242,6 +242,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
|
||||
appRouterConfig.routerScope = lifecycleScope
|
||||
appRouterConfig.componentRouter = routingComponent.router
|
||||
appRouterConfig.snackbarHandler = this
|
||||
|
||||
routingComponent.stack.observe(lifecycle.asEssentyLifecycle()) { childStack ->
|
||||
appRouterConfig.stack = childStack.backStack
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package com.tangem.tap.routing
|
||||
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.tap.routing.configurator.AppRouterConfig
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
|
@ -31,37 +33,59 @@ internal class ProxyAppRouter(
|
|||
}
|
||||
|
||||
override fun push(route: AppRoute, onComplete: (isSuccess: Boolean) -> Unit) {
|
||||
routerScope.launch(dispatchers.mainImmediate) {
|
||||
Timber.i("Push route: $route")
|
||||
safeNavigate(onComplete, message = "Push $route") {
|
||||
innerRouter.push(route, onComplete)
|
||||
}
|
||||
}
|
||||
|
||||
override fun replaceAll(vararg routes: AppRoute, onComplete: (isSuccess: Boolean) -> Unit) {
|
||||
routerScope.launch(dispatchers.mainImmediate) {
|
||||
Timber.i("Replace all routes with $routes")
|
||||
safeNavigate(onComplete, message = "Replace all routes with $routes") {
|
||||
innerRouter.replaceAll(*routes, onComplete = onComplete)
|
||||
}
|
||||
}
|
||||
|
||||
override fun pop(onComplete: (isSuccess: Boolean) -> Unit) {
|
||||
routerScope.launch(dispatchers.mainImmediate) {
|
||||
Timber.i("Pop route")
|
||||
safeNavigate(onComplete, message = "Pop route") {
|
||||
innerRouter.pop(onComplete)
|
||||
}
|
||||
}
|
||||
|
||||
override fun popTo(route: AppRoute, onComplete: (isSuccess: Boolean) -> Unit) {
|
||||
routerScope.launch(dispatchers.mainImmediate) {
|
||||
Timber.i("Pop to route: $route")
|
||||
safeNavigate(onComplete, message = "Pop to $route") {
|
||||
innerRouter.popTo(route, onComplete)
|
||||
}
|
||||
}
|
||||
|
||||
override fun popTo(routeClass: KClass<out AppRoute>, onComplete: (isSuccess: Boolean) -> Unit) {
|
||||
routerScope.launch(dispatchers.mainImmediate) {
|
||||
Timber.i("Pop to route class: $routeClass")
|
||||
safeNavigate(onComplete, message = "Pop to $routeClass") {
|
||||
innerRouter.popTo(routeClass, onComplete)
|
||||
}
|
||||
}
|
||||
|
||||
private fun safeNavigate(onComplete: (isSuccess: Boolean) -> Unit, message: String, block: () -> Unit) {
|
||||
routerScope.launch(dispatchers.mainImmediate) {
|
||||
Timber.i(message)
|
||||
|
||||
try {
|
||||
block()
|
||||
} catch (e: Throwable) {
|
||||
onComplete(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun defaultCompletionHandler(isSuccess: Boolean, errorMessage: String) {
|
||||
if (!isSuccess) {
|
||||
FirebaseCrashlytics.getInstance().recordException(RuntimeException(errorMessage))
|
||||
Timber.w(errorMessage)
|
||||
|
||||
with(receiver = config.snackbarHandler ?: return) {
|
||||
showSnackbar(
|
||||
text = R.string.common_unknown_error,
|
||||
buttonTitle = R.string.common_ok,
|
||||
action = { dismissSnackbar() },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.routing.configurator
|
|||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.tap.common.SnackbarHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
internal interface AppRouterConfig {
|
||||
|
|
@ -9,4 +10,7 @@ internal interface AppRouterConfig {
|
|||
var routerScope: CoroutineScope?
|
||||
var componentRouter: Router?
|
||||
var stack: List<AppRoute>?
|
||||
|
||||
// TODO: Replace with UI message handler: [REDACTED_JIRA]
|
||||
var snackbarHandler: SnackbarHandler?
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.routing.configurator
|
|||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.tap.common.SnackbarHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
internal class MutableAppRouterConfig : AppRouterConfig {
|
||||
|
|
@ -9,4 +10,5 @@ internal class MutableAppRouterConfig : AppRouterConfig {
|
|||
override var routerScope: CoroutineScope? = null
|
||||
override var componentRouter: Router? = null
|
||||
override var stack: List<AppRoute>? = null
|
||||
override var snackbarHandler: SnackbarHandler? = null
|
||||
}
|
||||
|
|
@ -23,7 +23,12 @@ interface AppRouter {
|
|||
* @param route The route to push.
|
||||
* @param onComplete The callback to be invoked when the operation is complete.
|
||||
*/
|
||||
fun push(route: AppRoute, onComplete: (isSuccess: Boolean) -> Unit = {})
|
||||
fun push(
|
||||
route: AppRoute,
|
||||
onComplete: (isSuccess: Boolean) -> Unit = { isSuccess ->
|
||||
defaultCompletionHandler(isSuccess, errorMessage = "Unable to push $route")
|
||||
},
|
||||
)
|
||||
|
||||
/**
|
||||
* Replaces ***all*** routes in the navigation stack with the specified [routes].
|
||||
|
|
@ -31,14 +36,23 @@ interface AppRouter {
|
|||
* @param routes The routes to replace the current stack with.
|
||||
* @param onComplete The callback to be invoked when the operation is complete.
|
||||
*/
|
||||
fun replaceAll(vararg routes: AppRoute, onComplete: (isSuccess: Boolean) -> Unit = {})
|
||||
fun replaceAll(
|
||||
vararg routes: AppRoute,
|
||||
onComplete: (isSuccess: Boolean) -> Unit = { isSuccess ->
|
||||
defaultCompletionHandler(isSuccess, errorMessage = "Unable to replace routes with $routes")
|
||||
},
|
||||
)
|
||||
|
||||
/**
|
||||
* Pops the top route from the navigation stack.
|
||||
*
|
||||
* @param onComplete The callback to be invoked when the operation is complete.
|
||||
*/
|
||||
fun pop(onComplete: (isSuccess: Boolean) -> Unit = {})
|
||||
fun pop(
|
||||
onComplete: (isSuccess: Boolean) -> Unit = { isSuccess ->
|
||||
defaultCompletionHandler(isSuccess, errorMessage = "Unable to pop route")
|
||||
},
|
||||
)
|
||||
|
||||
/**
|
||||
* Pops routes from the navigation stack until the specified [route] is found.
|
||||
|
|
@ -46,7 +60,12 @@ interface AppRouter {
|
|||
* @param route The route to pop to.
|
||||
* @param onComplete The callback to be invoked when the operation is complete.
|
||||
*/
|
||||
fun popTo(route: AppRoute, onComplete: (isSuccess: Boolean) -> Unit = {})
|
||||
fun popTo(
|
||||
route: AppRoute,
|
||||
onComplete: (isSuccess: Boolean) -> Unit = { isSuccess ->
|
||||
defaultCompletionHandler(isSuccess, errorMessage = "Unable to pop to $route")
|
||||
},
|
||||
)
|
||||
|
||||
/**
|
||||
* Pops routes from the navigation stack until the ***first*** specified [routeClass] is found.
|
||||
|
|
@ -54,5 +73,12 @@ interface AppRouter {
|
|||
* @param routeClass The route class to pop to.
|
||||
* @param onComplete The callback to be invoked when the operation is complete.
|
||||
*/
|
||||
fun popTo(routeClass: KClass<out AppRoute>, onComplete: (isSuccess: Boolean) -> Unit = {})
|
||||
fun popTo(
|
||||
routeClass: KClass<out AppRoute>,
|
||||
onComplete: (isSuccess: Boolean) -> Unit = { isSuccess ->
|
||||
defaultCompletionHandler(isSuccess, errorMessage = "Unable to pop to $routeClass")
|
||||
},
|
||||
)
|
||||
|
||||
fun defaultCompletionHandler(isSuccess: Boolean, errorMessage: String)
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ package com.tangem.core.decompose.navigation
|
|||
import com.arkivanov.decompose.ExperimentalDecomposeApi
|
||||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.pop
|
||||
import com.arkivanov.decompose.router.stack.popWhile
|
||||
import com.arkivanov.decompose.router.stack.pushNew
|
||||
import com.arkivanov.essenty.instancekeeper.InstanceKeeper
|
||||
import kotlin.reflect.KClass
|
||||
|
|
@ -34,16 +33,27 @@ internal class DefaultRouter(
|
|||
}
|
||||
|
||||
override fun popTo(route: Route, onComplete: (isSuccess: Boolean) -> Unit) {
|
||||
navigation.popWhile(
|
||||
predicate = { it != route },
|
||||
popTo(
|
||||
predicate = { it == route },
|
||||
onComplete = onComplete,
|
||||
)
|
||||
}
|
||||
|
||||
override fun popTo(routeClass: KClass<out Route>, onComplete: (isSuccess: Boolean) -> Unit) {
|
||||
navigation.popWhile(
|
||||
predicate = { it::class != routeClass },
|
||||
popTo(
|
||||
predicate = { routeClass.isInstance(it) },
|
||||
onComplete = onComplete,
|
||||
)
|
||||
}
|
||||
|
||||
private fun popTo(predicate: (Route) -> Boolean, onComplete: (isSuccess: Boolean) -> Unit) {
|
||||
navigation.navigate(
|
||||
transformer = { stack ->
|
||||
stack
|
||||
.dropLastWhile(predicate)
|
||||
.ifEmpty { stack }
|
||||
},
|
||||
onComplete = { newStack, oldStack -> onComplete(newStack.size < oldStack.size) },
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue