Updated on 2026-08-14
This commit is contained in:
commit
e9cb936766
8 changed files with 120 additions and 25 deletions
|
|
@ -2,7 +2,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.HIDE_OVERLAY_WINDOWS" />
|
||||
<!--<uses-permission android:name="android.permission.HIDE_OVERLAY_WINDOWS" />-->
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
|
|
|||
|
|
@ -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?) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -212,6 +212,7 @@ internal class MainViewModel @Inject constructor(
|
|||
|
||||
override fun onDismissBottomSheet() {
|
||||
listenToFlipsUseCase.changeUpdateEnabled(true)
|
||||
router.pop()
|
||||
stateHolder.updateWithoutModalNotification()
|
||||
stateHolder.updateWithHiddenBalancesToast(true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<String, String> = 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 ^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue