From b98b66ff9f2eb14ecea50765a7e2b85a3372a94f Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 22 Sep 2025 14:24:06 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/tap/routing/RootContent.kt | 59 +++++++++--------- .../core/ui/security/DisableScreenshots.kt | 60 +++++++++++++++---- .../accesscode/AccessCodeComponent.kt | 5 +- .../port/AddExistingWalletImportComponent.kt | 2 + .../check/ManualBackupCheckComponent.kt | 2 + .../entry/WalletActivationModel.kt | 2 +- 6 files changed, 84 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/routing/RootContent.kt b/app/src/main/java/com/tangem/tap/routing/RootContent.kt index 2d158062cb..66b66199d4 100644 --- a/app/src/main/java/com/tangem/tap/routing/RootContent.kt +++ b/app/src/main/java/com/tangem/tap/routing/RootContent.kt @@ -31,6 +31,7 @@ import com.tangem.core.ui.message.EventMessageEffect import com.tangem.core.ui.res.LocalRootBackgroundColor import com.tangem.core.ui.res.LocalSnackbarHostState import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.security.ProvideSecureFlagController import com.tangem.tap.routing.component.RoutingComponent import com.tangem.tap.routing.transitions.RoutingTransitionAnimationFactory @@ -52,39 +53,41 @@ internal fun RootContent( activity = context as Activity, uiDependencies = uiDependencies, ) { - val snackbarHostState = LocalSnackbarHostState.current + ProvideSecureFlagController { + val snackbarHostState = LocalSnackbarHostState.current - Box(Modifier.background(LocalRootBackgroundColor.current.value)) { - Children( - modifier = modifier, - animation = childrenAnimation(backHandler = backHandler, onBack = onBack), - 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] - LaunchedEffect(instance) { - startActivity(context, instance.intent, Bundle.EMPTY) + Box(Modifier.background(LocalRootBackgroundColor.current.value)) { + Children( + modifier = modifier, + animation = childrenAnimation(backHandler = backHandler, onBack = onBack), + 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] + LaunchedEffect(instance) { + startActivity(context, instance.intent, Bundle.EMPTY) + } } } } + + wcContent(Modifier.fillMaxSize()) + + hotAccessCodeContent(Modifier.fillMaxSize()) + + TangemSnackbarHost( + modifier = Modifier + .align(Alignment.BottomCenter) + .navigationBarsPadding() + .padding(all = 16.dp), + hostState = snackbarHostState, + ) } - - wcContent(Modifier.fillMaxSize()) - - hotAccessCodeContent(Modifier.fillMaxSize()) - - TangemSnackbarHost( - modifier = Modifier - .align(Alignment.BottomCenter) - .navigationBarsPadding() - .padding(all = 16.dp), - hostState = snackbarHostState, - ) } EventMessageEffect() } diff --git a/core/ui/src/main/java/com/tangem/core/ui/security/DisableScreenshots.kt b/core/ui/src/main/java/com/tangem/core/ui/security/DisableScreenshots.kt index 58466d1140..dcb5b64ee2 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/security/DisableScreenshots.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/security/DisableScreenshots.kt @@ -1,11 +1,53 @@ package com.tangem.core.ui.security +import android.app.Activity import android.view.WindowManager import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.platform.LocalContext import com.tangem.core.ui.utils.findActivity -import timber.log.Timber + +private val LocalSecureFlagController = staticCompositionLocalOf { + error("No SecureFlagController provided") +} + +private class SecureFlagController(private val activity: Activity) { + private var count by mutableIntStateOf(0) + + fun enable() { + if (count == 0) { + activity.window.setFlags( + WindowManager.LayoutParams.FLAG_SECURE, + WindowManager.LayoutParams.FLAG_SECURE, + ) + } + count++ + } + + fun disable() { + count-- + if (count == 0) { + activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) + } + } +} + +@Composable +fun ProvideSecureFlagController(content: @Composable () -> Unit) { + val activity = LocalContext.current.findActivity() + val controller = remember(activity) { SecureFlagController(activity) } + + CompositionLocalProvider( + LocalSecureFlagController provides controller, + content = content, + ) +} /** * Disables screenshots for the current composition. @@ -14,18 +56,10 @@ import timber.log.Timber */ @Composable fun DisableScreenshotsDisposableEffect() { - val activity = LocalContext.current.findActivity() + val secureFlagController = LocalSecureFlagController.current - DisposableEffect(activity) { - Timber.d("Security mode: enabled") - activity.window.setFlags( - WindowManager.LayoutParams.FLAG_SECURE, - WindowManager.LayoutParams.FLAG_SECURE, - ) - - onDispose { - Timber.d("Security mode: disabled") - activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) - } + DisposableEffect(secureFlagController) { + secureFlagController.enable() + onDispose { secureFlagController.disable() } } } \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/accesscode/AccessCodeComponent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/accesscode/AccessCodeComponent.kt index 62fdd324b1..b3f1b8afa4 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/accesscode/AccessCodeComponent.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/accesscode/AccessCodeComponent.kt @@ -25,10 +25,7 @@ internal class AccessCodeComponent @AssistedInject constructor( override fun Content(modifier: Modifier) { val state by model.uiState.collectAsStateWithLifecycle() - if (!state.isConfirmMode) { - DisableScreenshotsDisposableEffect() - } - + DisableScreenshotsDisposableEffect() AccessCode( modifier = modifier, state = state, diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/AddExistingWalletImportComponent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/AddExistingWalletImportComponent.kt index 096bd395a0..0cc5ea65a8 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/AddExistingWalletImportComponent.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/AddExistingWalletImportComponent.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.core.ui.security.DisableScreenshotsDisposableEffect import com.tangem.domain.models.wallet.UserWalletId import com.tangem.features.hotwallet.addexistingwallet.im.port.model.AddExistingWalletImportModel import com.tangem.features.hotwallet.addexistingwallet.im.port.ui.AddExistingWalletImportContent @@ -22,6 +23,7 @@ internal class AddExistingWalletImportComponent @AssistedInject constructor( @Composable override fun Content(modifier: Modifier) { val state by model.uiState.collectAsStateWithLifecycle() + DisableScreenshotsDisposableEffect() AddExistingWalletImportContent( state = state, modifier = modifier, diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/manualbackup/check/ManualBackupCheckComponent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/manualbackup/check/ManualBackupCheckComponent.kt index 7f25916f2d..10d919bad7 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/manualbackup/check/ManualBackupCheckComponent.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/manualbackup/check/ManualBackupCheckComponent.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.core.ui.security.DisableScreenshotsDisposableEffect import com.tangem.domain.models.wallet.UserWalletId import com.tangem.features.hotwallet.manualbackup.check.model.ManualBackupCheckModel import com.tangem.features.hotwallet.manualbackup.check.ui.ManualBackupCheckContent @@ -22,6 +23,7 @@ internal class ManualBackupCheckComponent @AssistedInject constructor( @Composable override fun Content(modifier: Modifier) { val state by model.uiState.collectAsStateWithLifecycle() + DisableScreenshotsDisposableEffect() ManualBackupCheckContent( state = state, modifier = modifier, diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletactivation/entry/WalletActivationModel.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletactivation/entry/WalletActivationModel.kt index e5cd76ac2f..3d889f2034 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletactivation/entry/WalletActivationModel.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletactivation/entry/WalletActivationModel.kt @@ -63,7 +63,7 @@ internal class WalletActivationModel @Inject constructor( is WalletActivationRoute.ManualBackupCheck -> stackNavigation.pop() is WalletActivationRoute.ManualBackupCompleted -> Unit is WalletActivationRoute.SetAccessCode -> Unit - is WalletActivationRoute.ConfirmAccessCode -> Unit + is WalletActivationRoute.ConfirmAccessCode -> stackNavigation.pop() is WalletActivationRoute.PushNotifications -> Unit is WalletActivationRoute.SetupFinished -> Unit }