diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt b/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt index 80aff4d6..fc1ab24c 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/RemoteSideContext.kt @@ -198,7 +198,7 @@ class RemoteSideContext( } } - if (mappings.isMappingsOutdated() || !mappings.isMappingsLoaded) { + if (!sharedPreferences.getBoolean("debug_disable_mapper", false) && (mappings.isMappingsOutdated() || !mappings.isMappingsLoaded)) { requirements = requirements or Requirements.MAPPINGS } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeService.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeService.kt index 5bf7c5c8..8fbb8645 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeService.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeService.kt @@ -202,5 +202,9 @@ class BridgeService : Service() { override fun registerConfigStateListener(listener: ConfigStateListener) { remoteSideContext.config.configStateListener = listener } + + override fun getDebugProp(key: String, defaultValue: String?): String? { + return remoteSideContext.sharedPreferences.all["debug_$key"]?.toString() ?: defaultValue + } } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeSettings.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeSettings.kt index 7431a580..c1d73737 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeSettings.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/pages/home/HomeSettings.kt @@ -1,5 +1,6 @@ package me.rhunk.snapenhance.ui.manager.pages.home +import android.content.SharedPreferences import androidx.compose.foundation.ScrollState import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -40,6 +41,30 @@ class HomeSettings : Routes.Route() { Text(text = title, modifier = Modifier.padding(16.dp), fontSize = 20.sp, fontWeight = FontWeight.Bold) } + @Composable + private fun PreferenceToggle(sharedPreferences: SharedPreferences, key: String, text: String) { + val realKey = "debug_$key" + var value by remember { mutableStateOf(sharedPreferences.getBoolean(realKey, false)) } + + Row( + modifier = Modifier + .fillMaxWidth() + .height(55.dp) + .clickable { + value = !value + sharedPreferences.edit().putBoolean(realKey, value).apply() + }, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text(text = text) + Switch(checked = value, onCheckedChange = { + value = it + sharedPreferences.edit().putBoolean(realKey, it).apply() + }, modifier = Modifier.padding(end = 26.dp)) + } + } + @Composable private fun RowAction(title: String, requireConfirmation: Boolean = false, action: () -> Unit) { var confirmationDialog by remember { @@ -184,7 +209,9 @@ class HomeSettings : Routes.Route() { } } OutlinedButton( - modifier = Modifier.fillMaxWidth().padding(5.dp), + modifier = Modifier + .fillMaxWidth() + .padding(5.dp), onClick = { routes.loggerHistory.navigate() } @@ -194,7 +221,7 @@ class HomeSettings : Routes.Route() { } } - RowTitle(title = "Clear App Files") + RowTitle(title = "Debug") Row( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, @@ -210,7 +237,7 @@ class HomeSettings : Routes.Route() { ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = it }, - modifier = Modifier.fillMaxWidth(0.8f) + modifier = Modifier.fillMaxWidth(0.7f) ) { TextField( value = selectedFileType.displayName, @@ -241,7 +268,16 @@ class HomeSettings : Routes.Route() { context.shortToast("Done!") } }) { - Text(text = "Clear") + Text(text = "Clear File") + } + } + ShiftedRow { + Column( + verticalArrangement = Arrangement.spacedBy(4.dp), + ) { + PreferenceToggle(context.sharedPreferences, key = "disable_feature_loading", text = "Disable Feature Loading") + PreferenceToggle(context.sharedPreferences, key = "disable_mapper", text = "Disable Auto Mapper") + PreferenceToggle(context.sharedPreferences, key = "force_native_load", text = "Force Native Load") } } Spacer(modifier = Modifier.height(50.dp)) diff --git a/common/src/main/aidl/me/rhunk/snapenhance/bridge/BridgeInterface.aidl b/common/src/main/aidl/me/rhunk/snapenhance/bridge/BridgeInterface.aidl index fa4e3591..55a7f440 100644 --- a/common/src/main/aidl/me/rhunk/snapenhance/bridge/BridgeInterface.aidl +++ b/common/src/main/aidl/me/rhunk/snapenhance/bridge/BridgeInterface.aidl @@ -94,4 +94,6 @@ interface BridgeInterface { oneway void closeSettingsOverlay(); oneway void registerConfigStateListener(in ConfigStateListener listener); + + @nullable String getDebugProp(String key, @nullable String defaultValue); } \ No newline at end of file diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendInfo.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendInfo.kt index 8712172a..9a1a0bd8 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendInfo.kt +++ b/common/src/main/kotlin/me/rhunk/snapenhance/common/database/impl/FriendInfo.kt @@ -59,7 +59,7 @@ data class FriendInfo( serverDisplayName = getStringOrNull("serverDisplayName") streakLength = getInteger("streakLength") streakExpirationTimestamp = getLong("streakExpiration") - reverseBestFriendRanking = getInteger("reverseBestFriendRanking") + reverseBestFriendRanking = getIntOrNull("reverseBestFriendRanking") ?: 0 usernameForSorting = getStringOrNull("usernameForSorting") friendLinkType = getInteger("friendLinkType") postViewEmoji = getStringOrNull("postViewEmoji") @@ -68,5 +68,4 @@ data class FriendInfo( plusBadgeVisibility = getIntOrNull("plusBadgeVisibility") ?: 0 } } - } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/ModContext.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/ModContext.kt index f88b4dd1..dd2e0624 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/ModContext.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/ModContext.kt @@ -24,8 +24,8 @@ import me.rhunk.snapenhance.core.event.EventBus import me.rhunk.snapenhance.core.event.EventDispatcher import me.rhunk.snapenhance.core.features.Feature import me.rhunk.snapenhance.core.logger.CoreLogger -import me.rhunk.snapenhance.core.manager.impl.ActionManager -import me.rhunk.snapenhance.core.manager.impl.FeatureManager +import me.rhunk.snapenhance.core.action.ActionManager +import me.rhunk.snapenhance.core.features.FeatureManager import me.rhunk.snapenhance.core.messaging.CoreMessagingBridge import me.rhunk.snapenhance.core.messaging.MessageSender import me.rhunk.snapenhance.core.scripting.CoreScriptRuntime diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt index 6560b443..7f4f3eef 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/SnapEnhance.kt @@ -132,7 +132,6 @@ class SnapEnhance { } reloadConfig() - actionManager.init() initConfigListener() initWidgetListener() initNative() @@ -175,7 +174,10 @@ class SnapEnhance { private fun initNative() { // don't initialize native when not logged in - if (appContext.androidContext.getSharedPreferences("user_session_shared_pref", 0).getString("key_user_id", null) == null) return + if ( + appContext.androidContext.getSharedPreferences("user_session_shared_pref", 0).getString("key_user_id", null) == null && + appContext.bridgeClient.getDebugProp("force_native_load", null) != "true" + ) return if (appContext.config.experimental.nativeHooks.globalState != true) return lateinit var unhook: () -> Unit diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/manager/impl/ActionManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/action/ActionManager.kt similarity index 90% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/manager/impl/ActionManager.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/action/ActionManager.kt index 037e0ddb..4d6ddeb3 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/manager/impl/ActionManager.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/action/ActionManager.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.core.manager.impl +package me.rhunk.snapenhance.core.action import android.content.Intent import me.rhunk.snapenhance.common.action.EnumAction @@ -7,11 +7,10 @@ import me.rhunk.snapenhance.core.action.impl.BulkMessagingAction import me.rhunk.snapenhance.core.action.impl.CleanCache import me.rhunk.snapenhance.core.action.impl.ExportChatMessages import me.rhunk.snapenhance.core.action.impl.ExportMemories -import me.rhunk.snapenhance.core.manager.Manager class ActionManager( private val modContext: ModContext, -) : Manager { +) { private val actions by lazy { mapOf( @@ -26,9 +25,6 @@ class ActionManager( }.toMap().toMutableMap() } - override fun init() { - } - fun onNewIntent(intent: Intent?) { val action = intent?.getStringExtra(EnumAction.ACTION_PARAMETER) ?: return intent.removeExtra(EnumAction.ACTION_PARAMETER) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/BridgeClient.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/BridgeClient.kt index d4df71d0..bd3810db 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/BridgeClient.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/bridge/BridgeClient.kt @@ -209,4 +209,6 @@ class BridgeClient( fun closeSettingsOverlay() = safeServiceCall { service.closeSettingsOverlay() } fun registerConfigStateListener(listener: ConfigStateListener) = safeServiceCall { service.registerConfigStateListener(listener) } + + fun getDebugProp(name: String, defaultValue: String? = null) = safeServiceCall { service.getDebugProp(name, defaultValue) } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt index 582c116a..9719c661 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/database/DatabaseAccess.kt @@ -17,7 +17,6 @@ import me.rhunk.snapenhance.common.util.ktx.getInteger import me.rhunk.snapenhance.common.util.ktx.getStringOrNull import me.rhunk.snapenhance.common.util.protobuf.ProtoReader import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.manager.Manager import me.rhunk.snapenhance.nativelib.NativeLib @@ -30,7 +29,7 @@ enum class DatabaseType( class DatabaseAccess( private val context: ModContext -) : Manager { +) { private val openedDatabases = mutableMapOf() private fun useDatabase(database: DatabaseType, writeMode: Boolean = false): SQLiteDatabase? { @@ -118,7 +117,7 @@ class DatabaseAccess( fun hasMain(): Boolean = useDatabase(DatabaseType.MAIN)?.isOpen == true fun hasArroyo(): Boolean = useDatabase(DatabaseType.ARROYO)?.isOpen == true - override fun init() { + fun init() { // perform integrity check on databases DatabaseType.entries.forEach { type -> useDatabase(type, writeMode = true)?.apply { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventDispatcher.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventDispatcher.kt index 2c748929..64618f1f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventDispatcher.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventDispatcher.kt @@ -7,7 +7,6 @@ import android.view.ViewGroup.LayoutParams import me.rhunk.snapenhance.common.util.snap.SnapWidgetBroadcastReceiverHelper import me.rhunk.snapenhance.core.ModContext import me.rhunk.snapenhance.core.event.events.impl.* -import me.rhunk.snapenhance.core.manager.Manager import me.rhunk.snapenhance.core.util.hook.HookStage import me.rhunk.snapenhance.core.util.hook.Hooker import me.rhunk.snapenhance.core.util.hook.hook @@ -23,7 +22,7 @@ import java.nio.ByteBuffer class EventDispatcher( private val context: ModContext -) : Manager { +) { private fun hookViewBinder() { context.mappings.useMapper(ViewBinderMapper::class) { val cachedHooks = mutableListOf() @@ -60,8 +59,7 @@ class EventDispatcher( } - - override fun init() { + fun init() { context.classCache.conversationManager.hook("sendMessageWithContent", HookStage.BEFORE) { param -> context.event.post(SendMessageWithContentEvent( destinations = MessageDestinations(param.arg(0)), diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/manager/impl/FeatureManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureManager.kt similarity index 93% rename from core/src/main/kotlin/me/rhunk/snapenhance/core/manager/impl/FeatureManager.kt rename to core/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureManager.kt index a4de1a1e..78b65fe8 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/manager/impl/FeatureManager.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/FeatureManager.kt @@ -1,12 +1,9 @@ -package me.rhunk.snapenhance.core.manager.impl +package me.rhunk.snapenhance.core.features import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import me.rhunk.snapenhance.core.ModContext -import me.rhunk.snapenhance.core.features.Feature -import me.rhunk.snapenhance.core.features.FeatureLoadParams -import me.rhunk.snapenhance.core.features.MessagingRuleFeature import me.rhunk.snapenhance.core.features.impl.ConfigurationOverride import me.rhunk.snapenhance.core.features.impl.MixerStories import me.rhunk.snapenhance.core.features.impl.OperaViewerParamsOverride @@ -16,7 +13,9 @@ import me.rhunk.snapenhance.core.features.impl.downloader.ProfilePictureDownload import me.rhunk.snapenhance.core.features.impl.experiments.* import me.rhunk.snapenhance.core.features.impl.global.* import me.rhunk.snapenhance.core.features.impl.messaging.* -import me.rhunk.snapenhance.core.features.impl.spying.* +import me.rhunk.snapenhance.core.features.impl.spying.HalfSwipeNotifier +import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger +import me.rhunk.snapenhance.core.features.impl.spying.StealthMode import me.rhunk.snapenhance.core.features.impl.tweaks.BypassScreenshotDetection import me.rhunk.snapenhance.core.features.impl.tweaks.CameraTweaks import me.rhunk.snapenhance.core.features.impl.tweaks.DisablePermissionRequests @@ -24,17 +23,21 @@ import me.rhunk.snapenhance.core.features.impl.tweaks.PreventMessageListAutoScro import me.rhunk.snapenhance.core.features.impl.tweaks.UnsaveableMessages import me.rhunk.snapenhance.core.features.impl.ui.* import me.rhunk.snapenhance.core.logger.CoreLogger -import me.rhunk.snapenhance.core.manager.Manager import me.rhunk.snapenhance.core.ui.menu.MenuViewInjector import kotlin.reflect.KClass import kotlin.system.measureTimeMillis class FeatureManager( private val context: ModContext -) : Manager { +) { private val features = mutableMapOf, Feature>() private fun register(vararg featureList: Feature) { + if (context.bridgeClient.getDebugProp("disable_feature_loading") == "true") { + context.log.warn("Feature loading is disabled") + return + } + runBlocking { featureList.forEach { feature -> launch(Dispatchers.IO) { @@ -58,7 +61,7 @@ class FeatureManager( fun getRuleFeatures() = features.values.filterIsInstance().sortedBy { it.ruleType.ordinal } - override fun init() { + fun init() { register( EndToEndEncryption(), ScopeSync(), @@ -174,7 +177,7 @@ class FeatureManager( } } - override fun onActivityCreate() { + fun onActivityCreate() { measureTimeMillis { initFeatures( FeatureLoadParams.ACTIVITY_CREATE_SYNC, diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/manager/Manager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/manager/Manager.kt deleted file mode 100644 index cc11e083..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/manager/Manager.kt +++ /dev/null @@ -1,6 +0,0 @@ -package me.rhunk.snapenhance.core.manager - -interface Manager { - fun init() {} - fun onActivityCreate() {} -} \ No newline at end of file