Updated on 2026-08-14

This commit is contained in:
Tangem 2024-12-18 17:35:32 +04:00
parent 20eba62956
commit 2ab4b3a66d
6 changed files with 121 additions and 32 deletions

View file

@ -231,6 +231,7 @@ dependencies {
implementation(deps.reownCore)
implementation(deps.reownWeb3)
implementation(deps.prettyLogger)
implementation(deps.decompose.ext.compose)
/** Testing libraries */
testImplementation(deps.test.coroutine)

View file

@ -10,12 +10,15 @@ import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
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
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.coordinatorlayout.widget.CoordinatorLayout
@ -260,10 +263,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
observeAppThemeModeUpdates()
if (routingFeatureToggles.isNavigationRefactoringEnabled) {
TODO(
"Will be implemented in [REDACTED_JIRA] " +
"and in [REDACTED_JIRA]",
)
setRootContent()
} else {
setContentView(R.layout.activity_main)
installRouting()
@ -281,6 +281,16 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
}
}
private fun setRootContent() {
val routingComponent = routingComponentFactory.create(
context = rootComponentContext,
)
setContent {
routingComponent.Content(Modifier.fillMaxSize())
}
}
private fun installRouting() {
val routingComponent = routingComponentFactory.create(
context = rootComponentContext,

View file

@ -0,0 +1,47 @@
package com.tangem.tap.routing
import android.app.Activity
import android.os.Bundle
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat.startActivity
import com.arkivanov.decompose.extensions.compose.jetpack.stack.Children
import com.arkivanov.decompose.router.stack.ChildStack
import com.tangem.common.routing.AppRoute
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.routing.component.RoutingComponent
@Composable
internal fun RootContent(
stack: ChildStack<AppRoute, RoutingComponent.Child>,
uiDependencies: UiDependencies,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
TangemTheme(
activity = context as Activity,
uiDependencies = uiDependencies,
) {
Children(
modifier = modifier,
stack = stack,
) { child ->
when (val instance = child.instance) {
is RoutingComponent.Child.Initial -> Unit
is RoutingComponent.Child.ComposableComponent -> {
instance.component.Content(Modifier.fillMaxSize())
}
is RoutingComponent.Child.LegacyIntent -> {
// TODO: Remove and use it's own router: [REDACTED_JIRA]
startActivity(context, instance.intent, Bundle.EMPTY)
}
is RoutingComponent.Child.LegacyFragment,
-> error("Unsupported child: $instance")
}
}
}
}

View file

@ -2,8 +2,10 @@ package com.tangem.tap.routing.component.impl
import androidx.compose.material3.SnackbarDuration
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.extensions.compose.jetpack.subscribeAsState
import com.arkivanov.decompose.router.stack.ChildStack
import com.arkivanov.decompose.router.stack.childStack
import com.arkivanov.decompose.value.Value
@ -15,10 +17,12 @@ 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.core.ui.UiDependencies
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.SnackbarMessage
import com.tangem.tap.common.SnackbarHandler
import com.tangem.tap.routing.RootContent
import com.tangem.tap.routing.component.RoutingComponent
import com.tangem.tap.routing.component.RoutingComponent.Child
import com.tangem.tap.routing.configurator.AppRouterConfig
@ -34,6 +38,7 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
private val childFactory: ChildFactory,
private val appRouterConfig: AppRouterConfig,
private val routingFeatureToggles: RoutingFeatureToggles,
private val uiDependencies: UiDependencies,
) : RoutingComponent,
AppComponentContext by context,
SnackbarHandler {
@ -72,7 +77,13 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
@Composable
override fun Content(modifier: Modifier) {
// TODO: Implement in [REDACTED_JIRA]
val stack by this.stack.subscribeAsState()
RootContent(
modifier = modifier,
stack = stack,
uiDependencies = uiDependencies,
)
}
override fun showSnackbar(text: Int, length: Int, buttonTitle: Int?, action: (() -> Unit)?) {

View file

@ -1,5 +1,7 @@
package com.tangem.core.ui.res
import android.app.Activity
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.text.selection.LocalTextSelectionColors
import androidx.compose.foundation.text.selection.TextSelectionColors
import androidx.compose.material.Colors
@ -10,13 +12,40 @@ import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalView
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.components.TangemShimmer
import com.tangem.core.ui.haptic.DefaultHapticManager
import com.tangem.core.ui.haptic.HapticManager
import com.tangem.core.ui.haptic.VibratorHapticManager
import com.tangem.core.ui.windowsize.WindowSize
import com.tangem.core.ui.windowsize.rememberWindowSize
import com.tangem.domain.apptheme.model.AppThemeMode
import com.valentinilk.shimmer.Shimmer
@Composable
fun TangemTheme(
activity: Activity,
uiDependencies: UiDependencies,
typography: TangemTypography = TangemTheme.typography,
dimens: TangemDimens = TangemTheme.dimens,
overrideSystemBarColors: Boolean = true,
content: @Composable () -> Unit,
) {
val appThemeMode by uiDependencies.appThemeModeHolder.appThemeMode
val windowSize = rememberWindowSize(activity = activity)
TangemTheme(
isDark = shouldUseDarkTheme(appThemeMode),
windowSize = windowSize,
vibratorHapticManager = uiDependencies.vibratorHapticManager,
snackbarHostState = uiDependencies.globalSnackbarHostState,
overrideSystemBarColors = overrideSystemBarColors,
typography = typography,
dimens = dimens,
content = content,
)
}
@Composable
fun TangemTheme(
isDark: Boolean = false,
@ -266,4 +295,20 @@ val LocalTangemShimmer = staticCompositionLocalOf<Shimmer> {
val LocalMainBottomSheetColor = staticCompositionLocalOf<MutableState<Color>> {
error("No MainBottomSheetColor provided")
}
/**
* Determines whether the dark theme should be used based on the given [AppThemeMode].
*
* @param appThemeMode The application theme mode.
* @return `true` if the dark theme should be used, `false` otherwise.
*/
@Composable
@ReadOnlyComposable
private fun shouldUseDarkTheme(appThemeMode: AppThemeMode): Boolean {
return when (appThemeMode) {
AppThemeMode.FORCE_DARK -> true
AppThemeMode.FORCE_LIGHT -> false
AppThemeMode.FOLLOW_SYSTEM -> isSystemInDarkTheme()
}
}

View file

@ -2,17 +2,13 @@ package com.tangem.core.ui.screen
import android.app.Activity
import android.content.Context
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.windowsize.rememberWindowSize
import com.tangem.domain.apptheme.model.AppThemeMode
/**
* Interface representing a Compose screen with common theming and content composition properties.
@ -60,34 +56,13 @@ internal fun ComposeScreen.createComposeView(
): ComposeView {
return ComposeView(context).apply {
setContent {
val appThemeMode by uiDependencies.appThemeModeHolder.appThemeMode
val windowSize = rememberWindowSize(activity = activity)
TangemTheme(
isDark = shouldUseDarkTheme(appThemeMode),
windowSize = windowSize,
vibratorHapticManager = uiDependencies.vibratorHapticManager,
snackbarHostState = uiDependencies.globalSnackbarHostState,
activity = activity,
uiDependencies = uiDependencies,
overrideSystemBarColors = overrideSystemBarColors,
) {
ScreenContent(modifier = screenModifier)
}
}
}
}
/**
* Determines whether the dark theme should be used based on the given [AppThemeMode].
*
* @param appThemeMode The application theme mode.
* @return `true` if the dark theme should be used, `false` otherwise.
*/
@Composable
@ReadOnlyComposable
private fun shouldUseDarkTheme(appThemeMode: AppThemeMode): Boolean {
return when (appThemeMode) {
AppThemeMode.FORCE_DARK -> true
AppThemeMode.FORCE_LIGHT -> false
AppThemeMode.FOLLOW_SYSTEM -> isSystemInDarkTheme()
}
}