feat(core): sif status

- add InAppOverlay custom composable
This commit is contained in:
rhunk 2024-08-11 17:42:42 +02:00
parent 43f1a305a2
commit 0ac142f46c
5 changed files with 124 additions and 67 deletions

View File

@ -60,6 +60,7 @@ class FeatureManager(
fun init() {
register(
SecurityFeatures(),
EndToEndEncryption(),
ScopeSync(),
PreventMessageListAutoScroll(),

View File

@ -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
)
}
}
}

View File

@ -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)
}
}
}

View File

@ -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")
}
}
}

View File

@ -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,