Updated on 2026-08-14
This commit is contained in:
commit
517628b713
6 changed files with 150 additions and 34 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
74
app/src/main/java/com/tangem/tap/routing/RootContent.kt
Normal file
74
app/src/main/java/com/tangem/tap/routing/RootContent.kt
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
package com.tangem.tap.routing
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
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.components.snackbar.TangemSnackbarHost
|
||||
import com.tangem.core.ui.message.EventMessageEffect
|
||||
import com.tangem.core.ui.res.LocalSnackbarHostState
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.WindowInsetsZero
|
||||
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,
|
||||
) {
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
containerColor = TangemTheme.colors.background.primary,
|
||||
snackbarHost = {
|
||||
TangemSnackbarHost(
|
||||
modifier = Modifier.padding(all = 16.dp),
|
||||
hostState = snackbarHostState,
|
||||
)
|
||||
},
|
||||
contentWindowInsets = WindowInsetsZero,
|
||||
content = { paddingValues ->
|
||||
Children(
|
||||
modifier = Modifier.padding(paddingValues),
|
||||
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")
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
EventMessageEffect(
|
||||
messageHandler = uiDependencies.eventMessageHandler,
|
||||
snackbarHostState = snackbarHostState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -33,7 +37,8 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
|
|||
@Assisted context: AppComponentContext,
|
||||
private val childFactory: ChildFactory,
|
||||
private val appRouterConfig: AppRouterConfig,
|
||||
private val routingFeatureToggles: RoutingFeatureToggles,
|
||||
private val uiDependencies: UiDependencies,
|
||||
routingFeatureToggles: RoutingFeatureToggles,
|
||||
) : RoutingComponent,
|
||||
AppComponentContext by context,
|
||||
SnackbarHandler {
|
||||
|
|
@ -42,7 +47,7 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
|
|||
|
||||
override val stack: Value<ChildStack<AppRoute, Child>> = childStack(
|
||||
source = navigationProvider.getOrCreateTyped(),
|
||||
serializer = AppRoute.serializer(), // TODO Maybe set this to null for AppRoute.Onboarding case. Need to check
|
||||
serializer = AppRoute.serializer(),
|
||||
initialConfiguration = getInitialRoute(),
|
||||
handleBackButton = false,
|
||||
childFactory = ::child,
|
||||
|
|
@ -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)?) {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue