From cff20ef5156c88000212e95b6118f0e693dfdbf7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 20 Dec 2024 15:26:39 +0300 Subject: [PATCH 1/4] Updated on 2026-08-14 --- .../onramp/selectcountry/ui/SelectCountryBottomSheet.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/ui/SelectCountryBottomSheet.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/ui/SelectCountryBottomSheet.kt index 6fbf4c8d16..b74c50c6b1 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/ui/SelectCountryBottomSheet.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selectcountry/ui/SelectCountryBottomSheet.kt @@ -185,7 +185,7 @@ private fun UnavailableCountryItem(state: CountryItemState.WithContent.Unavailab color = TangemTheme.colors.text.disabled, ) Text( - text = "Unavailable", + text = stringResource(R.string.onramp_country_unavailable), maxLines = 1, style = TangemTheme.typography.body2, color = TangemTheme.colors.text.tertiary, From 29df79b1c2d954a955f50547fd3727e9d0aafa1e Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 20 Dec 2024 16:42:36 +0400 Subject: [PATCH 2/4] Updated on 2026-08-14 --- app/src/main/AndroidManifest.xml | 2 +- .../main/java/com/tangem/tap/MainActivity.kt | 36 ++++++++++++++++--- .../models/event/TechAnalyticsEvent.kt | 26 ++++++++++++++ .../disclaimer/impl/ui/DisclaimerScreen.kt | 21 +++++++---- 4 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/TechAnalyticsEvent.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8981d0a0b1..fbb777f36c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,7 @@ - + diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index e0a2bf62d7..469ab5c092 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -32,6 +32,8 @@ 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 +import com.tangem.core.analytics.models.event.TechAnalyticsEvent +import com.tangem.core.analytics.models.event.TechAnalyticsEvent.WindowObscured.ObscuredState import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.di.RootAppComponentContext import com.tangem.core.deeplink.DeepLinksRegistry @@ -222,6 +224,9 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac private val onActivityResultCallbacks = mutableListOf() + private var isWindowPartiallyObscuredAlreadySent: Boolean = false + private var isWindowFullyObscuredAlreadySent: Boolean = false + override fun onCreate(savedInstanceState: Bundle?) { // We need to call it before onCreate to prevent unnecessary activity recreation installAppTheme() @@ -246,9 +251,9 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING) } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - window.setHideOverlayWindows(true) - } + // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + // window.setHideOverlayWindows(true) + // } splashScreen.setKeepOnScreenCondition { viewModel.isSplashScreenShown } @@ -530,10 +535,31 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac false } + if (isPartiallyObscured) { + Timber.d("Window is partially obscured") + + if (!isWindowPartiallyObscuredAlreadySent) { + analyticsEventsHandler.send( + event = TechAnalyticsEvent.WindowObscured(state = ObscuredState.PARTIALLY), + ) + + isWindowPartiallyObscuredAlreadySent = true + } + } + val isFullyObscured = event.flags and MotionEvent.FLAG_WINDOW_IS_OBSCURED != 0 - if (isPartiallyObscured || isFullyObscured) { - Timber.e("Window is partially or fully obscured") + if (isFullyObscured) { + Timber.d("Window is partially or fully obscured") + + if (!isWindowFullyObscuredAlreadySent) { + analyticsEventsHandler.send( + event = TechAnalyticsEvent.WindowObscured(state = ObscuredState.FULLY), + ) + + isWindowFullyObscuredAlreadySent = true + } + return false } diff --git a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/TechAnalyticsEvent.kt b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/TechAnalyticsEvent.kt new file mode 100644 index 0000000000..7d7460a633 --- /dev/null +++ b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/TechAnalyticsEvent.kt @@ -0,0 +1,26 @@ +package com.tangem.core.analytics.models.event + +import com.tangem.core.analytics.models.AnalyticsEvent + +/** + * Tech analytics event + * + * @param event event name + * @param params params + */ +sealed class TechAnalyticsEvent( + event: String, + params: Map = mapOf(), +) : AnalyticsEvent(category = "Tech", event = event, params = params) { + + class WindowObscured(state: ObscuredState) : TechAnalyticsEvent( + event = "Window Obscured", + params = mapOf("State" to state.name), + ) { + + enum class ObscuredState { + PARTIALLY, + FULLY, + } + } +} \ No newline at end of file diff --git a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt index 1fcc978ace..7ffb017cfa 100644 --- a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt +++ b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt @@ -47,11 +47,16 @@ import java.nio.charset.StandardCharsets @Composable internal fun DisclaimerScreen(state: DisclaimerUM) { val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } - val bottomPadding = bottomBarHeight + TangemTheme.dimens.size16 - + val bottomPadding = if (state.isTosAccepted) { + bottomBarHeight + TangemTheme.dimens.size16 + } else { + bottomBarHeight + TangemTheme.dimens.size64 + } + val backgroundColor = TangemTheme.colors.background.primary + val (textColor, iconColor) = TangemTheme.colors.text.primary1 to TangemTheme.colors.icon.primary1 Box( modifier = Modifier - .background(TangemTheme.colors.background.primary) + .background(backgroundColor) .statusBarsPadding() .testTag(DISCLAIMER_SCREEN_CONTAINER), ) { @@ -67,6 +72,8 @@ internal fun DisclaimerScreen(state: DisclaimerUM) { onIconClicked = state.popBack, ).takeIf { state.isTosAccepted }, titleAlignment = Alignment.CenterHorizontally, + textColor = textColor, + iconTint = iconColor, ) DisclaimerContent(state.url) } @@ -74,7 +81,7 @@ internal fun DisclaimerScreen(state: DisclaimerUM) { if (!state.isTosAccepted) { BottomFade( modifier = Modifier.align(Alignment.BottomCenter), - backgroundColor = TangemTheme.colors.background.primary, + backgroundColor = backgroundColor, ) DisclaimerButton(state.onAccept) } else { @@ -85,6 +92,8 @@ internal fun DisclaimerScreen(state: DisclaimerUM) { @Composable private fun DisclaimerContent(url: String) { + val backgroundColor = TangemTheme.colors.background.primary + val webViewStateUrl = rememberWebViewState(url) val webViewStateData = rememberWebViewStateWithHTMLData( data = localTermsOfServices, @@ -119,12 +128,12 @@ private fun DisclaimerContent(url: String) { exit = fadeOut(), modifier = Modifier .fillMaxSize() - .background(TangemTheme.colors.background.primary), + .background(backgroundColor), ) { Box( modifier = Modifier .fillMaxSize() - .background(TangemTheme.colors.background.primary), + .background(backgroundColor), ) { CircularProgressIndicator( color = TangemTheme.colors.icon.informative, From 525149580598632bcfb131e44c3310e24da72270 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sat, 21 Dec 2024 14:56:09 +0300 Subject: [PATCH 3/4] Updated on 2026-08-14 --- gradle/dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index b15619d568..e980a73d6b 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -87,7 +87,7 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.18-874" +tangemBlockchainSdk = "release-app_5.18-887" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.18-413" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From e13cce2cf8f2ff5b3c9222fb9d61724cb85e01e5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Dec 2024 10:58:26 +0400 Subject: [PATCH 4/4] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 43 ++---------- .../tangem/tap/WindowObscurationObserver.kt | 68 +++++++++++++++++++ .../tangem/tap/features/main/MainViewModel.kt | 1 + 3 files changed, 73 insertions(+), 39 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/WindowObscurationObserver.kt diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 469ab5c092..2bc6faa40c 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -32,8 +32,6 @@ 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 -import com.tangem.core.analytics.models.event.TechAnalyticsEvent -import com.tangem.core.analytics.models.event.TechAnalyticsEvent.WindowObscured.ObscuredState import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.di.RootAppComponentContext import com.tangem.core.deeplink.DeepLinksRegistry @@ -224,9 +222,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac private val onActivityResultCallbacks = mutableListOf() - private var isWindowPartiallyObscuredAlreadySent: Boolean = false - private var isWindowFullyObscuredAlreadySent: Boolean = false - override fun onCreate(savedInstanceState: Bundle?) { // We need to call it before onCreate to prevent unnecessary activity recreation installAppTheme() @@ -272,6 +267,8 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac if (intent != null) { deepLinksRegistry.launch(intent) } + + lifecycle.addObserver(WindowObscurationObserver) } private fun installRouting() { @@ -529,41 +526,9 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac } override fun dispatchTouchEvent(event: MotionEvent): Boolean { - val isPartiallyObscured = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - event.flags and MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED != 0 - } else { - false - } + val result = WindowObscurationObserver.dispatchTouchEvent(event, analyticsEventsHandler) - if (isPartiallyObscured) { - Timber.d("Window is partially obscured") - - if (!isWindowPartiallyObscuredAlreadySent) { - analyticsEventsHandler.send( - event = TechAnalyticsEvent.WindowObscured(state = ObscuredState.PARTIALLY), - ) - - isWindowPartiallyObscuredAlreadySent = true - } - } - - val isFullyObscured = event.flags and MotionEvent.FLAG_WINDOW_IS_OBSCURED != 0 - - if (isFullyObscured) { - Timber.d("Window is partially or fully obscured") - - if (!isWindowFullyObscuredAlreadySent) { - analyticsEventsHandler.send( - event = TechAnalyticsEvent.WindowObscured(state = ObscuredState.FULLY), - ) - - isWindowFullyObscuredAlreadySent = true - } - - return false - } - - return super.dispatchTouchEvent(event) + return if (result) super.dispatchTouchEvent(event) else false } private fun showSnackbar(text: String, length: Int, buttonTitle: String?, action: View.OnClickListener?) { diff --git a/app/src/main/java/com/tangem/tap/WindowObscurationObserver.kt b/app/src/main/java/com/tangem/tap/WindowObscurationObserver.kt new file mode 100644 index 0000000000..57f5a3fdec --- /dev/null +++ b/app/src/main/java/com/tangem/tap/WindowObscurationObserver.kt @@ -0,0 +1,68 @@ +package com.tangem.tap + +import android.os.Build +import android.view.MotionEvent +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner +import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.analytics.models.event.TechAnalyticsEvent +import com.tangem.core.analytics.models.event.TechAnalyticsEvent.WindowObscured.ObscuredState +import timber.log.Timber + +internal object WindowObscurationObserver : DefaultLifecycleObserver { + + private var isWindowPartiallyObscuredAlreadySent: Boolean = false + private var isWindowFullyObscuredAlreadySent: Boolean = false + + private var isReadyToProxy = false + + override fun onResume(owner: LifecycleOwner) { + super.onResume(owner) + isReadyToProxy = true + } + + override fun onPause(owner: LifecycleOwner) { + super.onPause(owner) + isReadyToProxy = false + } + + fun dispatchTouchEvent(event: MotionEvent, analyticsEventHandler: AnalyticsEventHandler): Boolean { + if (!isReadyToProxy) return true + + val isPartiallyObscured = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + event.flags and MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED != 0 + } else { + false + } + + if (isPartiallyObscured) { + Timber.d("Window is partially obscured") + + if (!isWindowPartiallyObscuredAlreadySent) { + analyticsEventHandler.send( + event = TechAnalyticsEvent.WindowObscured(state = ObscuredState.PARTIALLY), + ) + + isWindowPartiallyObscuredAlreadySent = true + } + } + + val isFullyObscured = event.flags and MotionEvent.FLAG_WINDOW_IS_OBSCURED != 0 + + if (isFullyObscured) { + Timber.d("Window is partially or fully obscured") + + if (!isWindowFullyObscuredAlreadySent) { + analyticsEventHandler.send( + event = TechAnalyticsEvent.WindowObscured(state = ObscuredState.FULLY), + ) + + isWindowFullyObscuredAlreadySent = true + } + + return false + } + + return true + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt index cde9a3b7df..d4f05a284a 100644 --- a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt @@ -212,6 +212,7 @@ internal class MainViewModel @Inject constructor( override fun onDismissBottomSheet() { listenToFlipsUseCase.changeUpdateEnabled(true) + router.pop() stateHolder.updateWithoutModalNotification() stateHolder.updateWithHiddenBalancesToast(true) }