From c5362c18899424d9c05a127b391cb916424df85c Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 20 Aug 2024 13:04:58 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 1 + .../com/tangem/tap/routing/ProxyAppRouter.kt | 44 ++++++++++++++----- .../routing/configurator/AppRouterConfig.kt | 4 ++ .../configurator/MutableAppRouterConfig.kt | 2 + .../com/tangem/common/routing/AppRouter.kt | 36 ++++++++++++--- 5 files changed, 72 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 8e0a528fca..b8830c622b 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -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 diff --git a/app/src/main/java/com/tangem/tap/routing/ProxyAppRouter.kt b/app/src/main/java/com/tangem/tap/routing/ProxyAppRouter.kt index 592656008e..d744032000 100644 --- a/app/src/main/java/com/tangem/tap/routing/ProxyAppRouter.kt +++ b/app/src/main/java/com/tangem/tap/routing/ProxyAppRouter.kt @@ -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, 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() }, + ) + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/routing/configurator/AppRouterConfig.kt b/app/src/main/java/com/tangem/tap/routing/configurator/AppRouterConfig.kt index 470c85f674..5c2c9b3843 100644 --- a/app/src/main/java/com/tangem/tap/routing/configurator/AppRouterConfig.kt +++ b/app/src/main/java/com/tangem/tap/routing/configurator/AppRouterConfig.kt @@ -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? + + // TODO: Replace with UI message handler: [REDACTED_JIRA] + var snackbarHandler: SnackbarHandler? } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/routing/configurator/MutableAppRouterConfig.kt b/app/src/main/java/com/tangem/tap/routing/configurator/MutableAppRouterConfig.kt index ae724ac04e..d1b1e93f7c 100644 --- a/app/src/main/java/com/tangem/tap/routing/configurator/MutableAppRouterConfig.kt +++ b/app/src/main/java/com/tangem/tap/routing/configurator/MutableAppRouterConfig.kt @@ -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? = null + override var snackbarHandler: SnackbarHandler? = null } \ No newline at end of file diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRouter.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRouter.kt index cb0f21a793..9f8d5f4111 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRouter.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRouter.kt @@ -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, onComplete: (isSuccess: Boolean) -> Unit = {}) + fun popTo( + routeClass: KClass, + onComplete: (isSuccess: Boolean) -> Unit = { isSuccess -> + defaultCompletionHandler(isSuccess, errorMessage = "Unable to pop to $routeClass") + }, + ) + + fun defaultCompletionHandler(isSuccess: Boolean, errorMessage: String) } \ No newline at end of file