commit a373c8fceb559147ca0fd5c9941bef7b7d00017b
parent f57d880ec82b4898b45534836ab20865a88e2dee
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sat, 30 Mar 2024 01:37:22 +0100

feat(core): crash overlay

Diffstat:
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt | 16+++++++++++-----
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/ui/InAppOverlay.kt | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 78 insertions(+), 9 deletions(-)

diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt @@ -23,11 +23,11 @@ import me.rhunk.snapenhance.core.bridge.loadFromBridge import me.rhunk.snapenhance.core.data.SnapClassCache import me.rhunk.snapenhance.core.event.events.impl.NativeUnaryCallEvent import me.rhunk.snapenhance.core.event.events.impl.SnapWidgetBroadcastReceiveEvent +import me.rhunk.snapenhance.core.ui.InAppOverlay import me.rhunk.snapenhance.core.util.LSPatchUpdater import me.rhunk.snapenhance.core.util.hook.HookAdapter import me.rhunk.snapenhance.core.util.hook.HookStage import me.rhunk.snapenhance.core.util.hook.hook -import java.lang.reflect.Modifier import kotlin.system.measureTimeMillis @@ -60,18 +60,23 @@ class SnapEnhance { bridgeClient.apply { connect( onFailure = { - crash("Snapchat can't connect to the SnapEnhance app. Please download stable version from https://github.com/rhunk/SnapEnhance/releases", it) + InAppOverlay.showCrashOverlay( + "Snapchat can't connect to the SnapEnhance app. Make sure you have the latest version installed on your device. You can download the latest stable version on github.com/rhunk/SnapEnhance", + throwable = it + ) } ) { bridgeResult -> if (!bridgeResult) { + InAppOverlay.showCrashOverlay( + "Snapchat timed out while trying to connect to the SnapEnhance app. Make sure you have disabled any battery optimizations for SnapEnhance." + ) logCritical("Cannot connect to the SnapEnhance app") - softRestartApp() return@connect } runCatching { LSPatchUpdater.onBridgeConnected(appContext, bridgeClient) }.onFailure { - logCritical("Failed to init LSPatchUpdater", it) + log.error("Failed to init LSPatchUpdater", it) } runCatching { measureTimeMillis { @@ -85,6 +90,7 @@ class SnapEnhance { isBridgeInitialized = true }.onFailure { logCritical("Failed to initialize bridge", it) + InAppOverlay.showCrashOverlay("SnapEnhance failed to initialize. Please check logs for more details.") } } } @@ -315,7 +321,7 @@ class SnapEnhance { } val stringResources = material3RString.fields.filter { - Modifier.isStatic(it.modifiers) && it.type == Int::class.javaPrimitiveType + java.lang.reflect.Modifier.isStatic(it.modifiers) && it.type == Int::class.javaPrimitiveType }.associate { it.getInt(null) to it.name } Resources::class.java.getMethod("getString", Int::class.javaPrimitiveType).hook(HookStage.BEFORE) { param -> diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/InAppOverlay.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/ui/InAppOverlay.kt @@ -1,6 +1,7 @@ package me.rhunk.snapenhance.core.ui import android.app.Activity +import android.view.View import android.widget.FrameLayout import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.LinearEasing @@ -15,10 +16,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Warning -import androidx.compose.material3.Card -import androidx.compose.material3.Icon -import androidx.compose.material3.LinearProgressIndicator -import androidx.compose.material3.Text +import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -30,13 +28,78 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import kotlinx.coroutines.delay import me.rhunk.snapenhance.common.ui.AppMaterialTheme import me.rhunk.snapenhance.common.ui.createComposeView +import me.rhunk.snapenhance.common.util.ktx.copyToClipboard +import me.rhunk.snapenhance.core.util.hook.HookStage +import me.rhunk.snapenhance.core.util.hook.Hooker import me.rhunk.snapenhance.core.util.ktx.isDarkTheme import kotlin.math.roundToInt class InAppOverlay { + companion object { + fun showCrashOverlay(content: String, throwable: Throwable? = null) { + Hooker.ephemeralHook(Activity::class.java, "onPostCreate", HookStage.AFTER) { param -> + val contentView = param.thisObject<Activity>().findViewById<FrameLayout>(android.R.id.content) + contentView.children().forEach { it.visibility = View.GONE } + lateinit var screenView: View + screenView = createComposeView(param.thisObject()) { + AppMaterialTheme(isDarkTheme = true) { + Surface( + color = MaterialTheme.colorScheme.surface + ) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "SnapEnhance", + fontSize = 28.sp + ) + Spacer(modifier = Modifier.height(40.dp)) + Text( + text = content, + fontSize = 16.sp + ) + Spacer(modifier = Modifier.height(40.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + throwable?.let { + Button(onClick = { + contentView.context.copyToClipboard(it.stackTraceToString()) + }) { + Text("Copy error to clipboard") + } + } + Button(onClick = { + contentView.children().forEach { it.visibility = View.VISIBLE } + contentView.removeView(screenView) + }) { + Text("Ignore") + } + } + } + } + } + } + }.apply { + layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT) + } + contentView.addView(screenView) + } + } + } + inner class Toast( val composable: @Composable Toast.() -> Unit, val durationMs: Int