Updated on 2026-08-14
This commit is contained in:
parent
3d16de3f4f
commit
d65b4039da
15 changed files with 26 additions and 945 deletions
|
|
@ -12,7 +12,6 @@ import androidx.activity.SystemBarStyle
|
|||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
|
||||
|
|
@ -20,19 +19,11 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||
import androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.flowWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import arrow.core.getOrElse
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.arkivanov.decompose.value.subscribe
|
||||
import com.arkivanov.essenty.lifecycle.asEssentyLifecycle
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.entity.SerializableIntent
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
|
|
@ -41,12 +32,6 @@ import com.tangem.core.decompose.di.RootAppComponentContext
|
|||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.core.navigation.email.EmailSender
|
||||
import com.tangem.core.ui.UiDependencies
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.message.EventMessageEffect
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.data.balancehiding.DefaultDeviceFlipDetector
|
||||
import com.tangem.data.card.sdk.CardSdkOwner
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
|
|
@ -70,11 +55,8 @@ import com.tangem.sdk.api.TangemSdkManager
|
|||
import com.tangem.tap.common.ActivityResultCallbackHolder
|
||||
import com.tangem.tap.common.DialogManager
|
||||
import com.tangem.tap.common.OnActivityResultCallback
|
||||
import com.tangem.tap.common.SnackbarHandler
|
||||
import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder
|
||||
import com.tangem.tap.common.extensions.dispatchNavigationAction
|
||||
import com.tangem.tap.common.extensions.showFragmentAllowingStateLoss
|
||||
import com.tangem.tap.common.redux.NotificationsHandler
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
|
||||
import com.tangem.tap.features.intentHandler.IntentProcessor
|
||||
import com.tangem.tap.features.intentHandler.handlers.BackgroundScanIntentHandler
|
||||
|
|
@ -85,11 +67,8 @@ import com.tangem.tap.proxy.AppStateHolder
|
|||
import com.tangem.tap.proxy.redux.DaggerGraphAction
|
||||
import com.tangem.tap.routing.component.RoutingComponent
|
||||
import com.tangem.tap.routing.configurator.AppRouterConfig
|
||||
import com.tangem.tap.routing.toggle.RoutingFeatureToggles
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.FeatureCoroutineExceptionHandler
|
||||
import com.tangem.wallet.R
|
||||
import com.tangem.wallet.databinding.ActivityMainBinding
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
|
@ -102,7 +81,6 @@ lateinit var tangemSdkManager: TangemSdkManager
|
|||
lateinit var backupService: BackupService
|
||||
internal var lockUserWalletsTimer: LockUserWalletsTimer? = null
|
||||
private set
|
||||
var notificationsHandler: NotificationsHandler? = null
|
||||
|
||||
private val coroutineContext: CoroutineContext
|
||||
get() = SupervisorJob() + Dispatchers.IO + FeatureCoroutineExceptionHandler.create("scope")
|
||||
|
|
@ -114,7 +92,7 @@ val mainScope = CoroutineScope(mainCoroutineContext)
|
|||
|
||||
@Suppress("LargeClass")
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbackHolder {
|
||||
class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
||||
|
||||
@Inject
|
||||
lateinit var appStateHolder: AppStateHolder
|
||||
|
|
@ -187,9 +165,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
@Inject
|
||||
lateinit var dispatchers: CoroutineDispatcherProvider
|
||||
|
||||
@Inject
|
||||
internal lateinit var routingFeatureToggles: RoutingFeatureToggles
|
||||
|
||||
@Inject
|
||||
internal lateinit var uiDependencies: UiDependencies
|
||||
|
||||
|
|
@ -203,9 +178,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
// TODO: fixme: inject through DI
|
||||
private val intentProcessor: IntentProcessor = IntentProcessor()
|
||||
|
||||
private var snackbar: Snackbar? = null
|
||||
private val dialogManager = DialogManager()
|
||||
private val binding: ActivityMainBinding by viewBinding(ActivityMainBinding::bind)
|
||||
|
||||
private val onActivityResultCallbacks = mutableListOf<OnActivityResultCallback>()
|
||||
|
||||
|
|
@ -242,13 +215,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
installActivityDependencies()
|
||||
observeAppThemeModeUpdates()
|
||||
|
||||
if (routingFeatureToggles.isNavigationRefactoringEnabled) {
|
||||
setRootContent()
|
||||
} else {
|
||||
setContentView(R.layout.activity_main)
|
||||
installRouting()
|
||||
installEventMessageEffect()
|
||||
}
|
||||
setRootContent()
|
||||
|
||||
initContent()
|
||||
|
||||
|
|
@ -265,33 +232,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
lifecycle.addObserver(defaultDeviceFlipDetector)
|
||||
}
|
||||
|
||||
private fun installEventMessageEffect() {
|
||||
binding.composeView.setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
binding.composeView.setContent {
|
||||
TangemTheme(
|
||||
activity = this,
|
||||
uiDependencies = uiDependencies,
|
||||
overrideSystemBarColors = false,
|
||||
) {
|
||||
EventMessageEffect(
|
||||
onShowSnackbar = { message, _ ->
|
||||
showSnackbar(
|
||||
text = message.message.resolveReference(resources),
|
||||
length = when (message.duration) {
|
||||
SnackbarMessage.Duration.Short -> Snackbar.LENGTH_SHORT
|
||||
SnackbarMessage.Duration.Long -> Snackbar.LENGTH_LONG
|
||||
SnackbarMessage.Duration.Indefinite -> Snackbar.LENGTH_INDEFINITE
|
||||
},
|
||||
buttonTitle = message.actionLabel?.resolveReference(resources),
|
||||
action = message.action,
|
||||
onDismiss = message.onDismissRequest,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setRootContent() {
|
||||
// for now activity is singleTop and after going to ChromeCustomTab it calls onCreate but onDestroy
|
||||
// doesn't calls. It lead to issue that decompose nav stack is not saved in bundle and to restore it
|
||||
|
|
@ -306,54 +246,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
}
|
||||
}
|
||||
|
||||
private fun installRouting() {
|
||||
// for now activity is singleTop and after going to ChromeCustomTab it calls onCreate but onDestroy
|
||||
// doesn't calls. It lead to issue that decompose nav stack is not saved in bundle and to restore it
|
||||
// we try to init component with previous stack
|
||||
val routingComponent = routingComponentFactory.create(
|
||||
context = rootComponentContext,
|
||||
initialStack = appRouterConfig.stack,
|
||||
)
|
||||
|
||||
appRouterConfig.routerScope = mainScope
|
||||
appRouterConfig.componentRouter = routingComponent.router
|
||||
appRouterConfig.snackbarHandler = this
|
||||
|
||||
routingComponent.stack.subscribe(lifecycle.asEssentyLifecycle()) { childStack ->
|
||||
val stack = childStack.backStack
|
||||
.plus(childStack.active)
|
||||
.map { it.configuration }
|
||||
|
||||
if (stack == appRouterConfig.stack) return@subscribe
|
||||
|
||||
appRouterConfig.stack = stack
|
||||
|
||||
if (stack.size == 1) {
|
||||
supportFragmentManager.run {
|
||||
val activeChildName = stack.first().path
|
||||
|
||||
(0 until backStackEntryCount)
|
||||
.mapNotNull { getBackStackEntryAt(it).name }
|
||||
.filter { it != activeChildName }
|
||||
.forEach {
|
||||
popBackStackImmediate(it, POP_BACK_STACK_INCLUSIVE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (val child = childStack.active.instance) {
|
||||
is RoutingComponent.Child.Initial -> Unit
|
||||
is RoutingComponent.Child.LegacyFragment -> {
|
||||
supportFragmentManager.showFragmentAllowingStateLoss(child.name, child.fragmentProvider)
|
||||
}
|
||||
is RoutingComponent.Child.LegacyIntent -> {
|
||||
startActivity(child.intent)
|
||||
}
|
||||
is RoutingComponent.Child.ComposableComponent -> error("Unsupported child: $child")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun installActivityDependencies() {
|
||||
cardSdkOwner.register(activity = this)
|
||||
tangemSdkManager = injectedTangemSdkManager
|
||||
|
|
@ -429,17 +321,10 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
if (!routingFeatureToggles.isNavigationRefactoringEnabled) {
|
||||
// TODO: RESEARCH! NotificationsHandler is created in onResume and destroyed in onStop
|
||||
notificationsHandler = NotificationsHandler(binding.fragmentContainer)
|
||||
}
|
||||
|
||||
navigateToInitialScreenIfNeeded(intent)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
notificationsHandler = null
|
||||
dialogManager.onStop()
|
||||
super.onStop()
|
||||
}
|
||||
|
|
@ -472,31 +357,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
MutableAppThemeModeHolder.isDarkThemeActive = isDarkTheme()
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
|
||||
/*
|
||||
* We need to manually change the background color of the activity when the UI mode changes to prevent
|
||||
* flickering when navigating between fragments.
|
||||
*
|
||||
|
||||
* `android:configChanges="uiMode"` is set in the manifest.
|
||||
* */
|
||||
if (routingFeatureToggles.isNavigationRefactoringEnabled.not()) {
|
||||
updateAppBackground()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateAppBackground() {
|
||||
val backgroundColor = if (isDarkTheme()) {
|
||||
TangemColorPalette.Dark6
|
||||
} else {
|
||||
TangemColorPalette.White
|
||||
}
|
||||
|
||||
findViewById<CoordinatorLayout>(R.id.fragment_container).setBackgroundColor(backgroundColor.toArgb())
|
||||
}
|
||||
|
||||
private fun isDarkTheme(): Boolean {
|
||||
return when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
|
||||
Configuration.UI_MODE_NIGHT_YES -> true
|
||||
|
|
@ -518,29 +378,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
}
|
||||
}
|
||||
|
||||
override fun showSnackbar(@StringRes text: Int, length: Int, @StringRes buttonTitle: Int?, action: (() -> Unit)?) {
|
||||
showSnackbar(
|
||||
getString(text),
|
||||
length,
|
||||
buttonTitle?.let(::getString),
|
||||
action = { action?.invoke() },
|
||||
)
|
||||
}
|
||||
|
||||
override fun showSnackbar(text: TextReference, length: Int, buttonTitle: TextReference?, action: (() -> Unit)?) {
|
||||
showSnackbar(
|
||||
text = text.resolveReference(resources),
|
||||
length = length,
|
||||
buttonTitle = buttonTitle?.resolveReference(resources),
|
||||
action = { action?.invoke() },
|
||||
)
|
||||
}
|
||||
|
||||
override fun dismissSnackbar() {
|
||||
snackbar?.dismiss()
|
||||
snackbar = null
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
|
|
@ -568,40 +405,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
return if (result) super.dispatchTouchEvent(event) else false
|
||||
}
|
||||
|
||||
private fun showSnackbar(
|
||||
text: String,
|
||||
length: Int,
|
||||
buttonTitle: String?,
|
||||
action: (() -> Unit)? = null,
|
||||
onDismiss: () -> Unit = {},
|
||||
) {
|
||||
if (snackbar != null) return
|
||||
|
||||
snackbar = Snackbar.make(binding.fragmentContainer, text, length).apply {
|
||||
val textColor = getColor(R.color.text_primary_2)
|
||||
|
||||
setBackgroundTint(getColor(R.color.button_primary))
|
||||
setActionTextColor(textColor)
|
||||
setTextColor(textColor)
|
||||
|
||||
if (buttonTitle != null && action != null) {
|
||||
setAction(buttonTitle, { action() })
|
||||
}
|
||||
|
||||
addCallback(
|
||||
object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
|
||||
override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
|
||||
onDismiss()
|
||||
snackbar = null
|
||||
removeCallback(this)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
snackbar?.show()
|
||||
}
|
||||
|
||||
private fun navigateToInitialScreenIfNeeded(intentWhichStartedActivity: Intent?) {
|
||||
val backStack = appRouterConfig.stack ?: emptyList()
|
||||
// TODO move inital navigation to navigation component ([REDACTED_JIRA])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue