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..2bc6faa40c 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -246,9 +246,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 } @@ -267,6 +267,8 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac if (intent != null) { deepLinksRegistry.launch(intent) } + + lifecycle.addObserver(WindowObscurationObserver) } private fun installRouting() { @@ -524,20 +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) - val isFullyObscured = event.flags and MotionEvent.FLAG_WINDOW_IS_OBSCURED != 0 - - if (isPartiallyObscured || isFullyObscured) { - Timber.e("Window is partially or fully obscured") - 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) } 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, 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, diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 85cc0139a0..4e017d07de 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -88,7 +88,7 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.19-885" +tangemBlockchainSdk = "release-app_5.19-888" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.19-414" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^