refactor: code cleanup

This commit is contained in:
rhunk 2023-09-23 22:44:51 +02:00
parent fc838fed7a
commit 2c16f41fd6
34 changed files with 149 additions and 174 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
package me.rhunk.snapenhance.core.eventbus
package me.rhunk.snapenhance.core.event
import me.rhunk.snapenhance.ModContext
import kotlin.reflect.KClass

View File

@ -1,14 +1,15 @@
package me.rhunk.snapenhance
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.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.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

View File

@ -1,6 +1,6 @@
package me.rhunk.snapenhance.core.eventbus.events
package me.rhunk.snapenhance.core.event.events
import me.rhunk.snapenhance.core.eventbus.Event
import me.rhunk.snapenhance.core.event.Event
import me.rhunk.snapenhance.hook.HookAdapter
abstract class AbstractHookEvent : Event() {

View File

@ -1,8 +1,8 @@
package me.rhunk.snapenhance.core.eventbus.events.impl
package me.rhunk.snapenhance.core.event.events.impl
import android.view.View
import android.view.ViewGroup
import me.rhunk.snapenhance.core.eventbus.events.AbstractHookEvent
import me.rhunk.snapenhance.core.event.events.AbstractHookEvent
class AddViewEvent(
val parent: ViewGroup,

View File

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

View File

@ -1,6 +1,6 @@
package me.rhunk.snapenhance.core.eventbus.events.impl
package me.rhunk.snapenhance.core.event.events.impl
import me.rhunk.snapenhance.core.eventbus.events.AbstractHookEvent
import me.rhunk.snapenhance.core.event.events.AbstractHookEvent
import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID
class OnSnapInteractionEvent(

View File

@ -1,6 +1,6 @@
package me.rhunk.snapenhance.core.eventbus.events.impl
package me.rhunk.snapenhance.core.event.events.impl
import me.rhunk.snapenhance.core.eventbus.events.AbstractHookEvent
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

View File

@ -1,8 +1,8 @@
package me.rhunk.snapenhance.core.eventbus.events.impl
package me.rhunk.snapenhance.core.event.events.impl
import android.content.Context
import android.content.Intent
import me.rhunk.snapenhance.core.eventbus.events.AbstractHookEvent
import me.rhunk.snapenhance.core.event.events.AbstractHookEvent
class SnapWidgetBroadcastReceiveEvent(
val androidContext: Context,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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