commit 2c16f41fd69c12b713b3bc1cfa3a5426b798b4e1
parent fc838fed7ab0b889d92e5d9b43863319df973fec
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sat, 23 Sep 2023 22:44:51 +0200

refactor: code cleanup

Diffstat:
Mapp/src/main/kotlin/me/rhunk/snapenhance/bridge/ForceStartActivity.kt | 3++-
Mcore/src/main/kotlin/me/rhunk/snapenhance/Constants.kt | 5-----
Dcore/src/main/kotlin/me/rhunk/snapenhance/EventDispatcher.kt | 117-------------------------------------------------------------------------------
Mcore/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt | 40++++++++++++++++++----------------------
Mcore/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt | 126++++++++++++++++++++++++++++++++++---------------------------------------------
Mcore/src/main/kotlin/me/rhunk/snapenhance/action/impl/OpenMap.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/bridge/BridgeClient.kt | 16++++++++++------
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/config/ModConfig.kt | 1-
Acore/src/main/kotlin/me/rhunk/snapenhance/core/event/EventBus.kt | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/src/main/kotlin/me/rhunk/snapenhance/core/event/EventDispatcher.kt | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/src/main/kotlin/me/rhunk/snapenhance/core/event/events/AbstractHookEvent.kt | 9+++++++++
Acore/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/AddViewEvent.kt | 13+++++++++++++
Acore/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/NetworkApiRequestEvent.kt | 10++++++++++
Acore/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/OnSnapInteractionEvent.kt | 11+++++++++++
Acore/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SendMessageWithContentEvent.kt | 24++++++++++++++++++++++++
Acore/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SnapWidgetBroadcastReceiveEvent.kt | 12++++++++++++
Acore/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/UnaryCallEvent.kt | 9+++++++++
Dcore/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/EventBus.kt | 73-------------------------------------------------------------------------
Dcore/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/AbstractHookEvent.kt | 9---------
Dcore/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/AddViewEvent.kt | 13-------------
Dcore/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/NetworkApiRequestEvent.kt | 10----------
Dcore/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/OnSnapInteractionEvent.kt | 11-----------
Dcore/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/SendMessageWithContentEvent.kt | 24------------------------
Dcore/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/SnapWidgetBroadcastReceiveEvent.kt | 12------------
Dcore/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/UnaryCallEvent.kt | 9---------
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/Messaging.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/ScopeSync.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt | 8++++----
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/ProfilePictureDownloader.kt | 4++--
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/DisableMetrics.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/AnonymousStoryViewing.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/PreventReadReceipts.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/DisableVideoLengthRestriction.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/OldBitmojiSelfie.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/SendOverride.kt | 4++--
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/ChatActionMenu.kt | 17++++++++---------
Mcore/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/FriendFeedInfoMenu.kt | 4+---
Mcore/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/MenuViewInjector.kt | 2+-
41 files changed, 392 insertions(+), 417 deletions(-)

diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/ForceStartActivity.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/ForceStartActivity.kt @@ -3,13 +3,14 @@ package me.rhunk.snapenhance.bridge import android.app.Activity import android.content.Intent import android.os.Bundle +import me.rhunk.snapenhance.Constants import me.rhunk.snapenhance.SharedContextHolder class ForceStartActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (intent.getBooleanExtra("streaks_notification_action", false)) { - packageManager.getLaunchIntentForPackage("com.snapchat.android")?.apply { + packageManager.getLaunchIntentForPackage(Constants.SNAPCHAT_PACKAGE_NAME)?.apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(this) } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/Constants.kt b/core/src/main/kotlin/me/rhunk/snapenhance/Constants.kt @@ -3,13 +3,8 @@ package me.rhunk.snapenhance object Constants { const val SNAPCHAT_PACKAGE_NAME = "com.snapchat.android" - const val VIEW_INJECTED_CODE = 0x7FFFFF02 - val ARROYO_MEDIA_CONTAINER_PROTO_PATH = intArrayOf(4, 4) val ARROYO_STRING_CHAT_MESSAGE_PROTO = ARROYO_MEDIA_CONTAINER_PROTO_PATH + intArrayOf(2, 1) - const val ENCRYPTION_PROTO_INDEX = 19 - const val ENCRYPTION_PROTO_INDEX_V2 = 4 - const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/EventDispatcher.kt b/core/src/main/kotlin/me/rhunk/snapenhance/EventDispatcher.kt @@ -1,116 +0,0 @@ -package me.rhunk.snapenhance - -import android.content.Intent -import android.view.View -import android.view.ViewGroup -import android.view.ViewGroup.LayoutParams -import me.rhunk.snapenhance.core.eventbus.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.eventbus.events.impl.NetworkApiRequestEvent -import me.rhunk.snapenhance.core.eventbus.events.impl.OnSnapInteractionEvent -import me.rhunk.snapenhance.core.eventbus.events.impl.SendMessageWithContentEvent -import me.rhunk.snapenhance.core.eventbus.events.impl.SnapWidgetBroadcastReceiveEvent -import me.rhunk.snapenhance.core.util.ktx.getObjectField -import me.rhunk.snapenhance.core.util.ktx.setObjectField -import me.rhunk.snapenhance.core.util.snap.SnapWidgetBroadcastReceiverHelper -import me.rhunk.snapenhance.data.wrapper.impl.MessageContent -import me.rhunk.snapenhance.data.wrapper.impl.MessageDestinations -import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID -import me.rhunk.snapenhance.hook.HookStage -import me.rhunk.snapenhance.hook.hook -import me.rhunk.snapenhance.manager.Manager - -class EventDispatcher( - private val context: ModContext -) : Manager { - override fun init() { - context.classCache.conversationManager.hook("sendMessageWithContent", HookStage.BEFORE) { param -> - context.event.post(SendMessageWithContentEvent( - destinations = MessageDestinations(param.arg(0)), - messageContent = MessageContent(param.arg(1)), - callback = param.arg(2) - ).apply { adapter = param })?.also { - if (it.canceled) { - param.setResult(null) - } - } - } - - context.classCache.snapManager.hook("onSnapInteraction", HookStage.BEFORE) { param -> - val interactionType = param.arg<Any>(0).toString() - val conversationId = SnapUUID(param.arg(1)) - val messageId = param.arg<Long>(2) - context.event.post( - OnSnapInteractionEvent( - interactionType = interactionType, - conversationId = conversationId, - messageId = messageId - ) - )?.also { - if (it.canceled) { - param.setResult(null) - } - } - } - - context.androidContext.classLoader.loadClass(SnapWidgetBroadcastReceiverHelper.CLASS_NAME) - .hook("onReceive", HookStage.BEFORE) { param -> - val intent = param.arg(1) as? Intent ?: return@hook - if (!SnapWidgetBroadcastReceiverHelper.isIncomingIntentValid(intent)) return@hook - val action = intent.getStringExtra("action") ?: return@hook - - context.event.post( - SnapWidgetBroadcastReceiveEvent( - androidContext = context.androidContext, - intent = intent, - action = action - ) - )?.also { - if (it.canceled) { - param.setResult(null) - } - } - } - - ViewGroup::class.java.getMethod( - "addView", - View::class.java, - Int::class.javaPrimitiveType, - LayoutParams::class.java - ).hook(HookStage.BEFORE) { param -> - context.event.post( - AddViewEvent( - parent = param.thisObject(), - view = param.arg(0), - index = param.arg(1), - layoutParams = param.arg(2) - ).apply { - adapter = param - } - )?.also { event -> - with(param) { - setArg(0, event.view) - setArg(1, event.index) - setArg(2, event.layoutParams) - } - if (event.canceled) param.setResult(null) - } - } - - context.classCache.networkApi.hook("submit", HookStage.BEFORE) { param -> - val request = param.arg<Any>(0) - - context.event.post( - NetworkApiRequestEvent( - url = request.getObjectField("mUrl") as String, - callback = param.arg(4), - request = request, - ).apply { - adapter = param - } - )?.also { event -> - event.request.setObjectField("mUrl", event.url) - if (event.canceled) param.setResult(null) - } - } - } -}- \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt @@ -10,14 +10,14 @@ import android.os.Process import android.widget.Toast import com.google.gson.Gson import com.google.gson.GsonBuilder -import kotlinx.coroutines.asCoroutineDispatcher import me.rhunk.snapenhance.core.Logger import me.rhunk.snapenhance.core.bridge.BridgeClient import me.rhunk.snapenhance.core.bridge.wrapper.LocaleWrapper import me.rhunk.snapenhance.core.bridge.wrapper.MappingsWrapper import me.rhunk.snapenhance.core.config.ModConfig import me.rhunk.snapenhance.core.database.DatabaseAccess -import me.rhunk.snapenhance.core.eventbus.EventBus +import me.rhunk.snapenhance.core.event.EventBus +import me.rhunk.snapenhance.core.event.EventDispatcher import me.rhunk.snapenhance.core.util.download.HttpServer import me.rhunk.snapenhance.data.MessageSender import me.rhunk.snapenhance.features.Feature @@ -34,32 +34,28 @@ import kotlin.system.exitProcess class ModContext { private val executorService: ExecutorService = Executors.newCachedThreadPool() - val coroutineDispatcher by lazy { - executorService.asCoroutineDispatcher() - } - lateinit var androidContext: Context - var mainActivity: Activity? = null lateinit var bridgeClient: BridgeClient + var mainActivity: Activity? = null + val classCache get() = SnapEnhance.classCache + val resources: Resources get() = androidContext.resources val gson: Gson = GsonBuilder().create() - private val modConfig = ModConfig() - val config by modConfig + private val _config = ModConfig() + val config by _config::root val log by lazy { Logger(this.bridgeClient) } - val event = EventBus(this) - val eventDispatcher = EventDispatcher(this) - val native = NativeLib() - val translation = LocaleWrapper() + val httpServer = HttpServer() + val messageSender = MessageSender(this) + val features = FeatureManager(this) val mappings = MappingsWrapper() val actionManager = ActionManager(this) val database = DatabaseAccess(this) - val httpServer = HttpServer() - val messageSender = MessageSender(this) - val classCache get() = SnapEnhance.classCache - val resources: Resources get() = androidContext.resources + val event = EventBus(this) + val eventDispatcher = EventDispatcher(this) + val native = NativeLib() val scriptRuntime by lazy { CoreScriptRuntime(log, androidContext.classLoader) } fun <T : Feature> feature(featureClass: KClass<T>): T { @@ -74,7 +70,7 @@ class ModContext { } } - fun executeAsync(runnable: () -> Unit) { + fun executeAsync(runnable: ModContext.() -> Unit) { executorService.submit { runCatching { runnable() @@ -99,7 +95,7 @@ class ModContext { fun softRestartApp(saveSettings: Boolean = false) { if (saveSettings) { - modConfig.writeConfig() + _config.writeConfig() } val intent: Intent? = androidContext.packageManager.getLaunchIntentForPackage( Constants.SNAPCHAT_PACKAGE_NAME @@ -117,7 +113,7 @@ class ModContext { delayForceCloseApp(100) } - fun delayForceCloseApp(delay: Long) = Handler(Looper.getMainLooper()).postDelayed({ + private fun delayForceCloseApp(delay: Long) = Handler(Looper.getMainLooper()).postDelayed({ forceCloseApp() }, delay) @@ -128,7 +124,7 @@ class ModContext { fun reloadConfig() { log.verbose("reloading config") - modConfig.loadFromBridge(bridgeClient) + _config.loadFromBridge(bridgeClient) native.loadNativeConfig( NativeConfig( disableBitmoji = config.experimental.nativeHooks.disableBitmoji.get(), @@ -138,6 +134,6 @@ class ModContext { } fun getConfigLocale(): String { - return modConfig.locale + return _config.locale } } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt b/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt @@ -3,118 +3,102 @@ package me.rhunk.snapenhance import android.app.Activity import android.app.Application import android.content.Context -import android.content.pm.PackageManager -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext import me.rhunk.snapenhance.bridge.SyncCallback -import me.rhunk.snapenhance.core.BuildConfig import me.rhunk.snapenhance.core.Logger import me.rhunk.snapenhance.core.bridge.BridgeClient -import me.rhunk.snapenhance.core.eventbus.events.impl.SnapWidgetBroadcastReceiveEvent -import me.rhunk.snapenhance.core.eventbus.events.impl.UnaryCallEvent +import me.rhunk.snapenhance.core.event.events.impl.SnapWidgetBroadcastReceiveEvent +import me.rhunk.snapenhance.core.event.events.impl.UnaryCallEvent import me.rhunk.snapenhance.core.messaging.MessagingFriendInfo import me.rhunk.snapenhance.core.messaging.MessagingGroupInfo -import me.rhunk.snapenhance.core.util.ktx.getApplicationInfoCompat import me.rhunk.snapenhance.data.SnapClassCache -import me.rhunk.snapenhance.hook.HookAdapter import me.rhunk.snapenhance.hook.HookStage -import me.rhunk.snapenhance.hook.Hooker import me.rhunk.snapenhance.hook.hook import kotlin.time.ExperimentalTime import kotlin.time.measureTime -private fun useMainActivity(hookAdapter: HookAdapter, block: Activity.() -> Unit) { - val activity = hookAdapter.thisObject() as Activity - if (!activity.packageName.equals(Constants.SNAPCHAT_PACKAGE_NAME)) return - block(activity) -} - class SnapEnhance { companion object { lateinit var classLoader: ClassLoader - val classCache: SnapClassCache by lazy { + private set + val classCache by lazy { SnapClassCache(classLoader) } } private val appContext = ModContext() private var isBridgeInitialized = false - init { - Hooker.hook(Application::class.java, "attach", HookStage.BEFORE) { param -> - appContext.androidContext = param.arg<Context>(0).also { - classLoader = it.classLoader - } - appContext.bridgeClient = BridgeClient(appContext) - - //for lspatch builds, we need to check if the service is correctly installed - runCatching { - appContext.androidContext.packageManager.getApplicationInfoCompat(BuildConfig.APPLICATION_ID, PackageManager.GET_META_DATA) - }.onFailure { - appContext.crash("SnapEnhance bridge service is not installed. Please download stable version from https://github.com/rhunk/SnapEnhance/releases") - return@hook - } + private fun hookMainActivity(methodName: String, stage: HookStage = HookStage.AFTER, block: Activity.() -> Unit) { + Activity::class.java.hook(methodName, stage, { isBridgeInitialized }) { param -> + val activity = param.thisObject() as Activity + if (!activity.packageName.equals(Constants.SNAPCHAT_PACKAGE_NAME)) return@hook + block(activity) + } + } - appContext.bridgeClient.apply { - start { bridgeResult -> - if (!bridgeResult) { - Logger.xposedLog("Cannot connect to bridge service") - appContext.softRestartApp() - return@start - } - runCatching { - runBlocking { + init { + Application::class.java.hook("attach", HookStage.BEFORE) { param -> + appContext.apply { + androidContext = param.arg<Context>(0).also { + classLoader = it.classLoader + } + bridgeClient = BridgeClient(appContext) + bridgeClient.apply { + connect( + timeout = { + crash("SnapEnhance bridge service is not responding. Please download stable version from https://github.com/rhunk/SnapEnhance/releases", it) + } + ) { bridgeResult -> + if (!bridgeResult) { + Logger.xposedLog("Cannot connect to bridge service") + softRestartApp() + return@connect + } + runCatching { init() + }.onSuccess { + isBridgeInitialized = true + }.onFailure { + Logger.xposedLog("Failed to initialize", it) } - }.onSuccess { - isBridgeInitialized = true - }.onFailure { - Logger.xposedLog("Failed to initialize", it) } } } } - Activity::class.java.hook( "onCreate", HookStage.AFTER, { isBridgeInitialized }) { - useMainActivity(it) { - val isMainActivityNotNull = appContext.mainActivity != null - appContext.mainActivity = this - if (isMainActivityNotNull || !appContext.mappings.isMappingsLoaded()) return@useMainActivity - onActivityCreate() - } + hookMainActivity("onCreate") { + val isMainActivityNotNull = appContext.mainActivity != null + appContext.mainActivity = this + if (isMainActivityNotNull || !appContext.mappings.isMappingsLoaded()) return@hookMainActivity + onActivityCreate() } - Activity::class.java.hook( "onPause", HookStage.AFTER, { isBridgeInitialized }) { - useMainActivity(it) { - appContext.bridgeClient.closeSettingsOverlay() - } + hookMainActivity("onPause") { + appContext.bridgeClient.closeSettingsOverlay() } var activityWasResumed = false - //we need to reload the config when the app is resumed //FIXME: called twice at first launch - Activity::class.java.hook("onResume", HookStage.AFTER, { isBridgeInitialized }) { - useMainActivity(it) { - if (!activityWasResumed) { - activityWasResumed = true - return@useMainActivity - } - - appContext.actionManager.onNewIntent(this.intent) - appContext.reloadConfig() - syncRemote() + hookMainActivity("onResume") { + if (!activityWasResumed) { + activityWasResumed = true + return@hookMainActivity } + + appContext.actionManager.onNewIntent(this.intent) + appContext.reloadConfig() + syncRemote() } } @OptIn(ExperimentalTime::class) - private suspend fun init() { + private fun init() { measureTime { with(appContext) { reloadConfig() initNative() - withContext(appContext.coroutineDispatcher) { + executeAsync { translation.userLocale = getConfigLocale() translation.loadFromBridge(bridgeClient) } @@ -162,10 +146,8 @@ class SnapEnhance { } private fun syncRemote() { - val database = appContext.database - appContext.executeAsync { - appContext.bridgeClient.sync(object : SyncCallback.Stub() { + bridgeClient.sync(object : SyncCallback.Stub() { override fun syncFriend(uuid: String): String? { return database.getFriendInfo(uuid)?.toJson() } @@ -181,7 +163,7 @@ class SnapEnhance { } }) - appContext.event.subscribe(SnapWidgetBroadcastReceiveEvent::class) { event -> + event.subscribe(SnapWidgetBroadcastReceiveEvent::class) { event -> if (event.action != BridgeClient.BRIDGE_SYNC_ACTION) return@subscribe event.canceled = true val feedEntries = appContext.database.getFeedEntries(Int.MAX_VALUE) @@ -204,7 +186,7 @@ class SnapEnhance { ) } - appContext.bridgeClient.passGroupsAndFriends( + bridgeClient.passGroupsAndFriends( groups.map { it.toJson() }, friends.map { it.toJson() } ) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/OpenMap.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/OpenMap.kt @@ -9,7 +9,7 @@ class OpenMap: AbstractAction() { override fun run() { context.runOnUiThread { val mapActivityIntent = Intent() - mapActivityIntent.setClassName(BuildConfig.APPLICATION_ID, "me.rhunk.snapenhance.ui.MapActivity") + mapActivityIntent.setClassName(BuildConfig.APPLICATION_ID, BuildConfig.APPLICATION_ID + ".ui.MapActivity") mapActivityIntent.putExtra("location", Bundle().apply { putDouble("latitude", context.config.experimental.spoof.location.latitude.get().toDouble()) putDouble("longitude", context.config.experimental.spoof.location.longitude.get().toDouble()) 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 @@ -23,6 +23,7 @@ import me.rhunk.snapenhance.core.messaging.SocialScope import me.rhunk.snapenhance.data.LocalePair import java.util.concurrent.CompletableFuture import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit import kotlin.system.exitProcess @@ -33,22 +34,21 @@ class BridgeClient( private lateinit var service: BridgeInterface companion object { - const val BRIDGE_SYNC_ACTION = "me.rhunk.snapenhance.core.bridge.SYNC" + const val BRIDGE_SYNC_ACTION = BuildConfig.APPLICATION_ID + ".core.bridge.SYNC" } - fun start(callback: (Boolean) -> Unit) { + fun connect(timeout: (Throwable) -> Unit, onResult: (Boolean) -> Unit) { this.future = CompletableFuture() - //TODO: randomize package name with(context.androidContext) { //ensure the remote process is running startActivity(Intent() - .setClassName(BuildConfig.APPLICATION_ID, "me.rhunk.snapenhance.bridge.ForceStartActivity") + .setClassName(BuildConfig.APPLICATION_ID, BuildConfig.APPLICATION_ID + ".bridge.ForceStartActivity") .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK) ) val intent = Intent() - .setClassName(BuildConfig.APPLICATION_ID, "me.rhunk.snapenhance.bridge.BridgeService") + .setClassName(BuildConfig.APPLICATION_ID, BuildConfig.APPLICATION_ID + ".bridge.BridgeService") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { bindService( intent, @@ -70,7 +70,11 @@ class BridgeClient( ) } } - callback(future.get()) + runCatching { + onResult(future.get(10, TimeUnit.SECONDS)) + }.onFailure { + timeout(it) + } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ModConfig.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ModConfig.kt @@ -19,7 +19,6 @@ class ModConfig { var wasPresent by Delegates.notNull<Boolean>() lateinit var root: RootConfig - operator fun getValue(thisRef: Any?, property: Any?) = root private fun load() { root = RootConfig() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventBus.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/EventBus.kt @@ -0,0 +1,72 @@ +package me.rhunk.snapenhance.core.event + +import me.rhunk.snapenhance.ModContext +import kotlin.reflect.KClass + +abstract class Event { + lateinit var context: ModContext + var canceled = false +} + +interface IListener<T> { + fun handle(event: T) +} + +class EventBus( + val context: ModContext +) { + private val subscribers = mutableMapOf<KClass<out Event>, MutableList<IListener<out Event>>>() + + fun <T : Event> subscribe(event: KClass<T>, listener: IListener<T>) { + if (!subscribers.containsKey(event)) { + subscribers[event] = mutableListOf() + } + subscribers[event]!!.add(listener) + } + + inline fun <T : Event> subscribe(event: KClass<T>, crossinline listener: (T) -> Unit) = subscribe(event, { true }, listener) + + inline fun <T : Event> subscribe(event: KClass<T>, crossinline filter: (T) -> Boolean, crossinline listener: (T) -> Unit): () -> Unit { + val obj = object : IListener<T> { + override fun handle(event: T) { + if (!filter(event)) return + runCatching { + listener(event) + }.onFailure { + context.log.error("Error while handling event ${event::class.simpleName}", it) + } + } + } + subscribe(event, obj) + return { unsubscribe(event, obj) } + } + + fun <T : Event> unsubscribe(event: KClass<T>, listener: IListener<T>) { + if (!subscribers.containsKey(event)) { + return + } + subscribers[event]!!.remove(listener) + } + + fun <T : Event> post(event: T): T? { + if (!subscribers.containsKey(event::class)) { + return null + } + + event.context = context + + subscribers[event::class]?.toTypedArray()?.forEach { listener -> + @Suppress("UNCHECKED_CAST") + runCatching { + (listener as IListener<T>).handle(event) + }.onFailure { t -> + context.log.error("Error while handling event ${event::class.simpleName} by ${listener::class.simpleName}", t) + } + } + return event + } + + fun clear() { + subscribers.clear() + } +}+ \ No newline at end of file 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 @@ -0,0 +1,117 @@ +package me.rhunk.snapenhance.core.event + +import android.content.Intent +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams +import me.rhunk.snapenhance.ModContext +import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent +import me.rhunk.snapenhance.core.event.events.impl.NetworkApiRequestEvent +import me.rhunk.snapenhance.core.event.events.impl.OnSnapInteractionEvent +import me.rhunk.snapenhance.core.event.events.impl.SendMessageWithContentEvent +import me.rhunk.snapenhance.core.event.events.impl.SnapWidgetBroadcastReceiveEvent +import me.rhunk.snapenhance.core.util.ktx.getObjectField +import me.rhunk.snapenhance.core.util.ktx.setObjectField +import me.rhunk.snapenhance.core.util.snap.SnapWidgetBroadcastReceiverHelper +import me.rhunk.snapenhance.data.wrapper.impl.MessageContent +import me.rhunk.snapenhance.data.wrapper.impl.MessageDestinations +import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID +import me.rhunk.snapenhance.hook.HookStage +import me.rhunk.snapenhance.hook.hook +import me.rhunk.snapenhance.manager.Manager + +class EventDispatcher( + private val context: ModContext +) : Manager { + override fun init() { + context.classCache.conversationManager.hook("sendMessageWithContent", HookStage.BEFORE) { param -> + context.event.post(SendMessageWithContentEvent( + destinations = MessageDestinations(param.arg(0)), + messageContent = MessageContent(param.arg(1)), + callback = param.arg(2) + ).apply { adapter = param })?.also { + if (it.canceled) { + param.setResult(null) + } + } + } + + context.classCache.snapManager.hook("onSnapInteraction", HookStage.BEFORE) { param -> + val interactionType = param.arg<Any>(0).toString() + val conversationId = SnapUUID(param.arg(1)) + val messageId = param.arg<Long>(2) + context.event.post( + OnSnapInteractionEvent( + interactionType = interactionType, + conversationId = conversationId, + messageId = messageId + ) + )?.also { + if (it.canceled) { + param.setResult(null) + } + } + } + + context.androidContext.classLoader.loadClass(SnapWidgetBroadcastReceiverHelper.CLASS_NAME) + .hook("onReceive", HookStage.BEFORE) { param -> + val intent = param.arg(1) as? Intent ?: return@hook + if (!SnapWidgetBroadcastReceiverHelper.isIncomingIntentValid(intent)) return@hook + val action = intent.getStringExtra("action") ?: return@hook + + context.event.post( + SnapWidgetBroadcastReceiveEvent( + androidContext = context.androidContext, + intent = intent, + action = action + ) + )?.also { + if (it.canceled) { + param.setResult(null) + } + } + } + + ViewGroup::class.java.getMethod( + "addView", + View::class.java, + Int::class.javaPrimitiveType, + LayoutParams::class.java + ).hook(HookStage.BEFORE) { param -> + context.event.post( + AddViewEvent( + parent = param.thisObject(), + view = param.arg(0), + index = param.arg(1), + layoutParams = param.arg(2) + ).apply { + adapter = param + } + )?.also { event -> + with(param) { + setArg(0, event.view) + setArg(1, event.index) + setArg(2, event.layoutParams) + } + if (event.canceled) param.setResult(null) + } + } + + context.classCache.networkApi.hook("submit", HookStage.BEFORE) { param -> + val request = param.arg<Any>(0) + + context.event.post( + NetworkApiRequestEvent( + url = request.getObjectField("mUrl") as String, + callback = param.arg(4), + request = request, + ).apply { + adapter = param + } + )?.also { event -> + event.request.setObjectField("mUrl", event.url) + if (event.canceled) param.setResult(null) + } + } + } +}+ \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/AbstractHookEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/AbstractHookEvent.kt @@ -0,0 +1,8 @@ +package me.rhunk.snapenhance.core.event.events + +import me.rhunk.snapenhance.core.event.Event +import me.rhunk.snapenhance.hook.HookAdapter + +abstract class AbstractHookEvent : Event() { + lateinit var adapter: HookAdapter +}+ \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/AddViewEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/AddViewEvent.kt @@ -0,0 +1,12 @@ +package me.rhunk.snapenhance.core.event.events.impl + +import android.view.View +import android.view.ViewGroup +import me.rhunk.snapenhance.core.event.events.AbstractHookEvent + +class AddViewEvent( + val parent: ViewGroup, + var view: View, + var index: Int, + var layoutParams: ViewGroup.LayoutParams +) : AbstractHookEvent()+ \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/NetworkApiRequestEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/NetworkApiRequestEvent.kt @@ -0,0 +1,9 @@ +package me.rhunk.snapenhance.core.event.events.impl + +import me.rhunk.snapenhance.core.event.events.AbstractHookEvent + +class NetworkApiRequestEvent( + val request: Any, + val callback: Any, + var url: String, +) : AbstractHookEvent()+ \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/OnSnapInteractionEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/OnSnapInteractionEvent.kt @@ -0,0 +1,10 @@ +package me.rhunk.snapenhance.core.event.events.impl + +import me.rhunk.snapenhance.core.event.events.AbstractHookEvent +import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID + +class OnSnapInteractionEvent( + val interactionType: String, + val conversationId: SnapUUID, + val messageId: Long +) : AbstractHookEvent()+ \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SendMessageWithContentEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SendMessageWithContentEvent.kt @@ -0,0 +1,23 @@ +package me.rhunk.snapenhance.core.event.events.impl + +import me.rhunk.snapenhance.core.event.events.AbstractHookEvent +import me.rhunk.snapenhance.data.wrapper.impl.MessageContent +import me.rhunk.snapenhance.data.wrapper.impl.MessageDestinations +import me.rhunk.snapenhance.hook.HookStage +import me.rhunk.snapenhance.hook.Hooker + +class SendMessageWithContentEvent( + val destinations: MessageDestinations, + val messageContent: MessageContent, + private val callback: Any +) : AbstractHookEvent() { + + fun addCallbackResult(methodName: String, block: (args: Array<Any?>) -> Unit) { + Hooker.ephemeralHookObjectMethod( + callback::class.java, + callback, + methodName, + HookStage.BEFORE + ) { block(it.args()) } + } +}+ \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SnapWidgetBroadcastReceiveEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/SnapWidgetBroadcastReceiveEvent.kt @@ -0,0 +1,11 @@ +package me.rhunk.snapenhance.core.event.events.impl + +import android.content.Context +import android.content.Intent +import me.rhunk.snapenhance.core.event.events.AbstractHookEvent + +class SnapWidgetBroadcastReceiveEvent( + val androidContext: Context, + val intent: Intent?, + val action: String +) : AbstractHookEvent()+ \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/UnaryCallEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/UnaryCallEvent.kt @@ -0,0 +1,8 @@ +package me.rhunk.snapenhance.core.event.events.impl + +import me.rhunk.snapenhance.core.event.events.AbstractHookEvent + +class UnaryCallEvent( + val uri: String, + var buffer: ByteArray +) : AbstractHookEvent()+ \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/EventBus.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/EventBus.kt @@ -1,72 +0,0 @@ -package me.rhunk.snapenhance.core.eventbus - -import me.rhunk.snapenhance.ModContext -import kotlin.reflect.KClass - -abstract class Event { - lateinit var context: ModContext - var canceled = false -} - -interface IListener<T> { - fun handle(event: T) -} - -class EventBus( - val context: ModContext -) { - private val subscribers = mutableMapOf<KClass<out Event>, MutableList<IListener<out Event>>>() - - fun <T : Event> subscribe(event: KClass<T>, listener: IListener<T>) { - if (!subscribers.containsKey(event)) { - subscribers[event] = mutableListOf() - } - subscribers[event]!!.add(listener) - } - - inline fun <T : Event> subscribe(event: KClass<T>, crossinline listener: (T) -> Unit) = subscribe(event, { true }, listener) - - inline fun <T : Event> subscribe(event: KClass<T>, crossinline filter: (T) -> Boolean, crossinline listener: (T) -> Unit): () -> Unit { - val obj = object : IListener<T> { - override fun handle(event: T) { - if (!filter(event)) return - runCatching { - listener(event) - }.onFailure { - context.log.error("Error while handling event ${event::class.simpleName}", it) - } - } - } - subscribe(event, obj) - return { unsubscribe(event, obj) } - } - - fun <T : Event> unsubscribe(event: KClass<T>, listener: IListener<T>) { - if (!subscribers.containsKey(event)) { - return - } - subscribers[event]!!.remove(listener) - } - - fun <T : Event> post(event: T): T? { - if (!subscribers.containsKey(event::class)) { - return null - } - - event.context = context - - subscribers[event::class]?.toTypedArray()?.forEach { listener -> - @Suppress("UNCHECKED_CAST") - runCatching { - (listener as IListener<T>).handle(event) - }.onFailure { t -> - context.log.error("Error while handling event ${event::class.simpleName} by ${listener::class.simpleName}", t) - } - } - return event - } - - fun clear() { - subscribers.clear() - } -}- \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/AbstractHookEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/AbstractHookEvent.kt @@ -1,8 +0,0 @@ -package me.rhunk.snapenhance.core.eventbus.events - -import me.rhunk.snapenhance.core.eventbus.Event -import me.rhunk.snapenhance.hook.HookAdapter - -abstract class AbstractHookEvent : Event() { - lateinit var adapter: HookAdapter -}- \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/AddViewEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/AddViewEvent.kt @@ -1,12 +0,0 @@ -package me.rhunk.snapenhance.core.eventbus.events.impl - -import android.view.View -import android.view.ViewGroup -import me.rhunk.snapenhance.core.eventbus.events.AbstractHookEvent - -class AddViewEvent( - val parent: ViewGroup, - var view: View, - var index: Int, - var layoutParams: ViewGroup.LayoutParams -) : AbstractHookEvent()- \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/NetworkApiRequestEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/NetworkApiRequestEvent.kt @@ -1,9 +0,0 @@ -package me.rhunk.snapenhance.core.eventbus.events.impl - -import me.rhunk.snapenhance.core.eventbus.events.AbstractHookEvent - -class NetworkApiRequestEvent( - val request: Any, - val callback: Any, - var url: String, -) : AbstractHookEvent()- \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/OnSnapInteractionEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/OnSnapInteractionEvent.kt @@ -1,10 +0,0 @@ -package me.rhunk.snapenhance.core.eventbus.events.impl - -import me.rhunk.snapenhance.core.eventbus.events.AbstractHookEvent -import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID - -class OnSnapInteractionEvent( - val interactionType: String, - val conversationId: SnapUUID, - val messageId: Long -) : AbstractHookEvent()- \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/SendMessageWithContentEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/SendMessageWithContentEvent.kt @@ -1,23 +0,0 @@ -package me.rhunk.snapenhance.core.eventbus.events.impl - -import me.rhunk.snapenhance.core.eventbus.events.AbstractHookEvent -import me.rhunk.snapenhance.data.wrapper.impl.MessageContent -import me.rhunk.snapenhance.data.wrapper.impl.MessageDestinations -import me.rhunk.snapenhance.hook.HookStage -import me.rhunk.snapenhance.hook.Hooker - -class SendMessageWithContentEvent( - val destinations: MessageDestinations, - val messageContent: MessageContent, - private val callback: Any -) : AbstractHookEvent() { - - fun addCallbackResult(methodName: String, block: (args: Array<Any?>) -> Unit) { - Hooker.ephemeralHookObjectMethod( - callback::class.java, - callback, - methodName, - HookStage.BEFORE - ) { block(it.args()) } - } -}- \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/SnapWidgetBroadcastReceiveEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/SnapWidgetBroadcastReceiveEvent.kt @@ -1,11 +0,0 @@ -package me.rhunk.snapenhance.core.eventbus.events.impl - -import android.content.Context -import android.content.Intent -import me.rhunk.snapenhance.core.eventbus.events.AbstractHookEvent - -class SnapWidgetBroadcastReceiveEvent( - val androidContext: Context, - val intent: Intent?, - val action: String -) : AbstractHookEvent()- \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/UnaryCallEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/eventbus/events/impl/UnaryCallEvent.kt @@ -1,8 +0,0 @@ -package me.rhunk.snapenhance.core.eventbus.events.impl - -import me.rhunk.snapenhance.core.eventbus.events.AbstractHookEvent - -class UnaryCallEvent( - val uri: String, - var buffer: ByteArray -) : AbstractHookEvent()- \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/Messaging.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/Messaging.kt @@ -1,6 +1,6 @@ package me.rhunk.snapenhance.features.impl -import me.rhunk.snapenhance.core.eventbus.events.impl.OnSnapInteractionEvent +import me.rhunk.snapenhance.core.event.events.impl.OnSnapInteractionEvent import me.rhunk.snapenhance.core.util.ktx.getObjectField import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID import me.rhunk.snapenhance.features.Feature diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ScopeSync.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ScopeSync.kt @@ -1,7 +1,7 @@ package me.rhunk.snapenhance.features.impl import kotlinx.coroutines.* -import me.rhunk.snapenhance.core.eventbus.events.impl.SendMessageWithContentEvent +import me.rhunk.snapenhance.core.event.events.impl.SendMessageWithContentEvent import me.rhunk.snapenhance.core.messaging.SocialScope import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.features.Feature diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt @@ -470,11 +470,11 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp if (!canAutoDownload()) return@onOperaViewStateCallback context.executeAsync { - try { + runCatching { handleOperaMedia(mediaParamMap, mediaInfoMap, false) - } catch (e: Throwable) { - context.log.error("Failed to handle opera media", e) - context.longToast(e.message) + }.onFailure { + context.log.error("Failed to handle opera media", it) + context.longToast(it.message) } } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/ProfilePictureDownloader.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/ProfilePictureDownloader.kt @@ -3,8 +3,8 @@ package me.rhunk.snapenhance.features.impl.downloader import android.annotation.SuppressLint import android.widget.Button import android.widget.RelativeLayout -import me.rhunk.snapenhance.core.eventbus.events.impl.AddViewEvent -import me.rhunk.snapenhance.core.eventbus.events.impl.NetworkApiRequestEvent +import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent +import me.rhunk.snapenhance.core.event.events.impl.NetworkApiRequestEvent import me.rhunk.snapenhance.core.util.protobuf.ProtoReader import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/DisableMetrics.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/DisableMetrics.kt @@ -1,6 +1,6 @@ package me.rhunk.snapenhance.features.impl.privacy -import me.rhunk.snapenhance.core.eventbus.events.impl.NetworkApiRequestEvent +import me.rhunk.snapenhance.core.event.events.impl.NetworkApiRequestEvent import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt @@ -1,6 +1,6 @@ package me.rhunk.snapenhance.features.impl.privacy -import me.rhunk.snapenhance.core.eventbus.events.impl.SendMessageWithContentEvent +import me.rhunk.snapenhance.core.event.events.impl.SendMessageWithContentEvent import me.rhunk.snapenhance.data.NotificationType import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/AnonymousStoryViewing.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/AnonymousStoryViewing.kt @@ -1,7 +1,7 @@ package me.rhunk.snapenhance.features.impl.spying import kotlinx.coroutines.runBlocking -import me.rhunk.snapenhance.core.eventbus.events.impl.NetworkApiRequestEvent +import me.rhunk.snapenhance.core.event.events.impl.NetworkApiRequestEvent import me.rhunk.snapenhance.core.util.download.HttpServer import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/PreventReadReceipts.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/PreventReadReceipts.kt @@ -1,6 +1,6 @@ package me.rhunk.snapenhance.features.impl.spying -import me.rhunk.snapenhance.core.eventbus.events.impl.OnSnapInteractionEvent +import me.rhunk.snapenhance.core.event.events.impl.OnSnapInteractionEvent import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/DisableVideoLengthRestriction.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/DisableVideoLengthRestriction.kt @@ -3,7 +3,7 @@ package me.rhunk.snapenhance.features.impl.tweaks import android.os.Build import android.os.FileObserver import com.google.gson.JsonParser -import me.rhunk.snapenhance.core.eventbus.events.impl.SendMessageWithContentEvent +import me.rhunk.snapenhance.core.event.events.impl.SendMessageWithContentEvent import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt @@ -14,7 +14,7 @@ import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers import me.rhunk.snapenhance.core.Logger import me.rhunk.snapenhance.core.download.data.SplitMediaAssetType -import me.rhunk.snapenhance.core.eventbus.events.impl.SnapWidgetBroadcastReceiveEvent +import me.rhunk.snapenhance.core.event.events.impl.SnapWidgetBroadcastReceiveEvent import me.rhunk.snapenhance.core.util.CallbackBuilder import me.rhunk.snapenhance.core.util.download.RemoteMediaResolver import me.rhunk.snapenhance.core.util.ktx.setObjectField diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/OldBitmojiSelfie.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/OldBitmojiSelfie.kt @@ -1,6 +1,6 @@ package me.rhunk.snapenhance.features.impl.tweaks -import me.rhunk.snapenhance.core.eventbus.events.impl.NetworkApiRequestEvent +import me.rhunk.snapenhance.core.event.events.impl.NetworkApiRequestEvent import me.rhunk.snapenhance.core.util.snap.BitmojiSelfie import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/SendOverride.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/SendOverride.kt @@ -1,8 +1,8 @@ package me.rhunk.snapenhance.features.impl.tweaks import me.rhunk.snapenhance.Constants -import me.rhunk.snapenhance.core.eventbus.events.impl.SendMessageWithContentEvent -import me.rhunk.snapenhance.core.eventbus.events.impl.UnaryCallEvent +import me.rhunk.snapenhance.core.event.events.impl.SendMessageWithContentEvent +import me.rhunk.snapenhance.core.event.events.impl.UnaryCallEvent import me.rhunk.snapenhance.core.util.protobuf.ProtoEditor import me.rhunk.snapenhance.core.util.protobuf.ProtoReader import me.rhunk.snapenhance.data.ContentType diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt @@ -8,7 +8,7 @@ import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import me.rhunk.snapenhance.Constants -import me.rhunk.snapenhance.core.eventbus.events.impl.AddViewEvent +import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/ChatActionMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/ChatActionMenu.kt @@ -9,7 +9,6 @@ import android.view.ViewGroup.MarginLayoutParams import android.widget.Button import android.widget.LinearLayout import me.rhunk.snapenhance.Constants -import me.rhunk.snapenhance.Constants.VIEW_INJECTED_CODE import me.rhunk.snapenhance.features.impl.Messaging import me.rhunk.snapenhance.features.impl.downloader.MediaDownloader import me.rhunk.snapenhance.features.impl.spying.MessageLogger @@ -18,9 +17,11 @@ import me.rhunk.snapenhance.ui.menu.AbstractMenu class ChatActionMenu : AbstractMenu() { + private val viewInjectedTag = 0x7FFFFF02 + private fun wasInjectedView(view: View): Boolean { - if (view.getTag(VIEW_INJECTED_CODE) != null) return true - view.setTag(VIEW_INJECTED_CODE, true) + if (view.getTag(viewInjectedTag) != null) return true + view.setTag(viewInjectedTag, true) return false } @@ -108,7 +109,7 @@ class ChatActionMenu : AbstractMenu() { text = this@ChatActionMenu.context.translation["chat_action_menu.preview_button"] setOnClickListener { closeActionMenu() - this@ChatActionMenu.context.executeAsync { this@ChatActionMenu.context.feature(MediaDownloader::class).onMessageActionMenu(true) } + this@ChatActionMenu.context.executeAsync { feature(MediaDownloader::class).onMessageActionMenu(true) } } }) @@ -117,9 +118,7 @@ class ChatActionMenu : AbstractMenu() { setOnClickListener { closeActionMenu() this@ChatActionMenu.context.executeAsync { - this@ChatActionMenu.context.feature( - MediaDownloader::class - ).onMessageActionMenu(false) + feature(MediaDownloader::class).onMessageActionMenu(false) } } }) @@ -132,8 +131,8 @@ class ChatActionMenu : AbstractMenu() { setOnClickListener { closeActionMenu() this@ChatActionMenu.context.executeAsync { - with(this@ChatActionMenu.context.feature(Messaging::class)) { - context.feature(MessageLogger::class).deleteMessage(openedConversationUUID.toString(), lastFocusedMessageId) + feature(Messaging::class).apply { + feature(MessageLogger::class).deleteMessage(openedConversationUUID.toString(), lastFocusedMessageId) } } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/FriendFeedInfoMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/FriendFeedInfoMenu.kt @@ -164,9 +164,7 @@ class FriendFeedInfoMenu : AbstractMenu() { ) { dialog: DialogInterface, _: Int -> dialog.dismiss() } targetPerson?.let { builder.setNegativeButton(context.translation["modal_option.profile_info"]) { _, _ -> - context.executeAsync { - showProfileInfo(it) - } + context.executeAsync { showProfileInfo(it) } } } builder.show() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/MenuViewInjector.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/MenuViewInjector.kt @@ -7,7 +7,7 @@ import android.view.ViewGroup import android.widget.FrameLayout import android.widget.LinearLayout import me.rhunk.snapenhance.Constants -import me.rhunk.snapenhance.core.eventbus.events.impl.AddViewEvent +import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.features.impl.Messaging