commit 0ac142f46c3260a148a8799aae63c5df37cafdfb
parent 43f1a305a2bcea6ff872b34438da778e5529f9c6
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sun, 11 Aug 2024 17:42:42 +0200

feat(core): sif status
- add InAppOverlay custom composable

Diffstat:
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureManager.kt | 1+
Acore/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/SecurityFeatures.kt | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AccountSwitcher.kt | 41+++++++++++++++++++++--------------------
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ComposerHooks.kt | 60+++++++++++++-----------------------------------------------
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/ui/InAppOverlay.kt | 15+++++++++++++++
5 files changed, 125 insertions(+), 67 deletions(-)

diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureManager.kt @@ -60,6 +60,7 @@ class FeatureManager( fun init() { register( + SecurityFeatures(), EndToEndEncryption(), ScopeSync(), PreventMessageListAutoScroll(), diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/SecurityFeatures.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/SecurityFeatures.kt @@ -0,0 +1,74 @@ +package me.rhunk.snapenhance.core.features.impl + +import android.system.Os +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.withContext +import me.rhunk.snapenhance.core.features.Feature + +class SecurityFeatures : Feature("Security Features") { + private fun transact(option: Int) = Os.prctl(option, 0, 0, 0, 0) + + private val token by lazy { + runCatching { transact(0) }.getOrNull() + } + + private fun getStatus() = token?.run { + transact(this).toString(2).padStart(32, '0').count { it == '1' } + } + + override fun init() { + token // pre init token + + context.inAppOverlay.addCustomComposable { + var statusText by remember { + mutableStateOf("") + } + var textColor by remember { + mutableStateOf(Color.Red) + } + + LaunchedEffect(Unit) { + withContext(Dispatchers.IO) { + while (true) { + val status = getStatus() + withContext(Dispatchers.Main) { + if (status == null || status == 0) { + textColor = Color.Red + statusText = "sif not loaded. Can't get status" + } else { + textColor = Color.Green + statusText = "sif = $status" + } + } + delay(1000) + } + } + } + + Text( + text = statusText, + modifier = Modifier + .align(Alignment.BottomCenter) + .background(Color.Black, shape = RoundedCornerShape(5.dp)) + .padding(3.dp), + fontSize = 10.sp, + color = textColor + ) + } + } +}+ \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AccountSwitcher.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/AccountSwitcher.kt @@ -6,7 +6,6 @@ import android.content.Intent import android.database.sqlite.SQLiteDatabase import android.net.Uri import android.os.ParcelFileDescriptor -import android.widget.FrameLayout import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -26,12 +25,12 @@ import kotlinx.coroutines.withContext import me.rhunk.snapenhance.common.data.FileType import me.rhunk.snapenhance.common.ui.AppMaterialTheme import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.common.ui.createComposeView import me.rhunk.snapenhance.common.util.ktx.toParcelFileDescriptor import me.rhunk.snapenhance.common.util.snap.MediaDownloaderHelper import me.rhunk.snapenhance.core.event.events.impl.ActivityResultEvent import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent import me.rhunk.snapenhance.core.features.Feature +import me.rhunk.snapenhance.core.ui.CustomComposable import me.rhunk.snapenhance.core.util.hook.HookStage import me.rhunk.snapenhance.core.util.hook.hook import me.rhunk.snapenhance.core.util.ktx.getId @@ -507,24 +506,26 @@ class AccountSwitcher: Feature("Account Switcher") { } } - findClass("com.snap.identity.loginsignup.ui.LoginSignupActivity").apply { - hook("onPostCreate", HookStage.AFTER) { - context.mainActivity!!.findViewById<FrameLayout>(android.R.id.content).addView(createComposeView(context.mainActivity!!) { - Row( - modifier = Modifier.fillMaxWidth(), - ) { - Button( - onClick = { showManagementPopup() }, - modifier = Modifier.padding(16.dp) - ) { - Text("Switch Account") - } - } - }.apply { - layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT).apply { - gravity = android.view.Gravity.TOP or android.view.Gravity.START - } - }) + val switchButtonComposable: CustomComposable = { + Row( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.TopStart), + ) { + Button( + onClick = { showManagementPopup() }, + modifier = Modifier.padding(16.dp) + ) { + Text("Switch Account") + } + } + } + + onNextActivityCreate { activity -> + if (!activity.componentName.className.endsWith("LoginSignupActivity")) return@onNextActivityCreate + context.inAppOverlay.addCustomComposable(switchButtonComposable) + onNextActivityCreate { + context.inAppOverlay.removeCustomComposable(switchButtonComposable) } } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ComposerHooks.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/experiments/ComposerHooks.kt @@ -1,26 +1,16 @@ package me.rhunk.snapenhance.core.features.impl.experiments -import android.app.Activity -import android.view.View -import android.widget.FrameLayout -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.BugReport -import androidx.compose.material3.Button -import androidx.compose.material3.FilledIconButton -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.material3.TextField +import androidx.compose.material3.* import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight @@ -29,9 +19,7 @@ import androidx.compose.ui.unit.sp import kotlinx.coroutines.launch import me.rhunk.snapenhance.common.bridge.FileHandleScope import me.rhunk.snapenhance.common.bridge.toWrapper -import me.rhunk.snapenhance.common.ui.AppMaterialTheme import me.rhunk.snapenhance.common.ui.createComposeAlertDialog -import me.rhunk.snapenhance.common.ui.createComposeView import me.rhunk.snapenhance.core.features.Feature import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader import me.rhunk.snapenhance.core.util.hook.HookStage @@ -101,35 +89,6 @@ class ComposerHooks: Feature("ComposerHooks") { } } - private val composerConsoleTag = Random.nextLong().toString() - - private fun injectConsole(activity: Activity) { - val root = activity.findViewById<FrameLayout>(android.R.id.content) ?: run { - context.log.warn("Unable to find root view. Can't inject console.") - return - } - root.post { - if (root.findViewWithTag<View>(composerConsoleTag) != null) return@post - root.addView(createComposeView(root.context) { - AppMaterialTheme { - FilledIconButton( - onClick = { - composerConsole.show() - }, - modifier = Modifier.padding(top = 100.dp, end = 16.dp) - ) { - Icon(Icons.Default.BugReport, contentDescription = "Debug Console") - } - } - }.apply { - tag = composerConsoleTag - layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT).apply { - gravity = android.view.Gravity.TOP or android.view.Gravity.END - } - }) - } - } - private fun newComposerFunction(block: ComposerMarshaller.() -> Boolean): Any? { val composerFunctionClass = findClass("com.snap.composer.callable.ComposerFunction") return Proxy.newProxyInstance( @@ -223,9 +182,16 @@ class ComposerHooks: Feature("ComposerHooks") { loadHooks() - onNextActivityCreate { activity -> - if (config.composerConsole.get()) { - injectConsole(activity) + if (config.composerConsole.get()) { + context.inAppOverlay.addCustomComposable { + FilledIconButton( + onClick = { + composerConsole.show() + }, + modifier = Modifier.align(Alignment.TopEnd).padding(top = 100.dp, end = 16.dp) + ) { + Icon(Icons.Default.BugReport, contentDescription = "Debug Console") + } } } 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 @@ -40,6 +40,8 @@ import me.rhunk.snapenhance.core.util.ktx.isDarkTheme import kotlin.math.roundToInt import kotlin.random.Random +typealias CustomComposable = @Composable BoxScope.() -> Unit + class InAppOverlay( private val context: ModContext ) { @@ -113,6 +115,7 @@ class InAppOverlay( } private val toasts = mutableStateListOf<Toast>() + private val customComposables = mutableStateListOf<CustomComposable>() @OptIn(ExperimentalFoundationApi::class) @Composable @@ -180,6 +183,10 @@ class InAppOverlay( } } } + + customComposables.forEach { + it() + } } } @@ -204,6 +211,14 @@ class InAppOverlay( injectOverlay(activity) } + fun addCustomComposable(composable: CustomComposable) { + customComposables.add(composable) + } + + fun removeCustomComposable(composable: CustomComposable) { + customComposables.remove(composable) + } + @Composable private fun DurationProgress( duration: Int,