mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-06-12 05:07:46 +02:00
event dispatcher
This commit is contained in:
37
core/src/main/kotlin/me/rhunk/snapenhance/EventDispatcher.kt
Normal file
37
core/src/main/kotlin/me/rhunk/snapenhance/EventDispatcher.kt
Normal file
@ -0,0 +1,37 @@
|
||||
package me.rhunk.snapenhance
|
||||
|
||||
import me.rhunk.snapenhance.core.event.impl.OnSnapInteractionEvent
|
||||
import me.rhunk.snapenhance.core.event.impl.SendMessageWithContentEvent
|
||||
import me.rhunk.snapenhance.data.wrapper.impl.MessageContent
|
||||
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 ->
|
||||
val messageContent = MessageContent(param.arg(1))
|
||||
context.event.post(SendMessageWithContentEvent(messageContent))?.let {
|
||||
if (it.canceled) {
|
||||
param.setResult(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.classCache.snapManager.hook("onSnapInteraction", HookStage.BEFORE) { param ->
|
||||
val conversationId = SnapUUID(param.arg(1))
|
||||
val messageId = param.arg<Long>(2)
|
||||
context.event.post(OnSnapInteractionEvent(
|
||||
conversationId = conversationId,
|
||||
messageId = messageId
|
||||
))?.let {
|
||||
if (it.canceled) {
|
||||
param.setResult(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import me.rhunk.snapenhance.bridge.BridgeClient
|
||||
import me.rhunk.snapenhance.bridge.wrapper.TranslationWrapper
|
||||
import me.rhunk.snapenhance.core.config.ModConfig
|
||||
import me.rhunk.snapenhance.core.event.EventBus
|
||||
import me.rhunk.snapenhance.data.MessageSender
|
||||
import me.rhunk.snapenhance.database.DatabaseAccess
|
||||
import me.rhunk.snapenhance.features.Feature
|
||||
@ -41,6 +42,8 @@ class ModContext {
|
||||
|
||||
private val modConfig = ModConfig()
|
||||
val config by modConfig
|
||||
val event = EventBus(this)
|
||||
val eventDispatcher = EventDispatcher(this)
|
||||
|
||||
val translation = TranslationWrapper()
|
||||
val features = FeatureManager(this)
|
||||
|
@ -99,6 +99,7 @@ class SnapEnhance {
|
||||
with(appContext) {
|
||||
reloadConfig()
|
||||
mappings.init()
|
||||
eventDispatcher.init()
|
||||
//if mappings aren't loaded, we can't initialize features
|
||||
if (!mappings.areMappingsLoaded) return
|
||||
features.init()
|
||||
|
@ -1,10 +1,12 @@
|
||||
package me.rhunk.snapenhance.event
|
||||
package me.rhunk.snapenhance.core.event
|
||||
|
||||
import me.rhunk.snapenhance.Logger
|
||||
import me.rhunk.snapenhance.ModContext
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
abstract class Event {
|
||||
lateinit var context: ModContext
|
||||
var canceled = false
|
||||
}
|
||||
|
||||
interface IListener<T> {
|
||||
@ -23,12 +25,14 @@ class EventBus(
|
||||
subscribers[event]!!.add(listener)
|
||||
}
|
||||
|
||||
fun <T : Event> subscribe(event: KClass<T>, listener: (T) -> Unit) {
|
||||
subscribe(event, object : IListener<T> {
|
||||
inline fun <T : Event> subscribe(event: KClass<T>, crossinline listener: (T) -> Unit): () -> Unit {
|
||||
val obj = object : IListener<T> {
|
||||
override fun handle(event: T) {
|
||||
listener(event)
|
||||
}
|
||||
})
|
||||
}
|
||||
subscribe(event, obj)
|
||||
return { unsubscribe(event, obj) }
|
||||
}
|
||||
|
||||
fun <T : Event> unsubscribe(event: KClass<T>, listener: IListener<T>) {
|
||||
@ -38,22 +42,22 @@ class EventBus(
|
||||
subscribers[event]!!.remove(listener)
|
||||
}
|
||||
|
||||
fun <T : Event> post(event: T) {
|
||||
fun <T : Event> post(event: T): T? {
|
||||
if (!subscribers.containsKey(event::class)) {
|
||||
return
|
||||
return null
|
||||
}
|
||||
|
||||
event.context = context
|
||||
|
||||
subscribers[event::class]!!.forEach { listener ->
|
||||
subscribers[event::class]?.forEach { listener ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
try {
|
||||
runCatching {
|
||||
(listener as IListener<T>).handle(event)
|
||||
} catch (t: Throwable) {
|
||||
println("Error while handling event ${event::class.simpleName} by ${listener::class.simpleName}")
|
||||
t.printStackTrace()
|
||||
}.onFailure { t ->
|
||||
Logger.error("Error while handling event ${event::class.simpleName} by ${listener::class.simpleName}", t)
|
||||
}
|
||||
}
|
||||
return event
|
||||
}
|
||||
|
||||
fun clear() {
|
@ -0,0 +1,9 @@
|
||||
package me.rhunk.snapenhance.core.event.impl
|
||||
|
||||
import me.rhunk.snapenhance.core.event.Event
|
||||
import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID
|
||||
|
||||
class OnSnapInteractionEvent(
|
||||
val conversationId: SnapUUID,
|
||||
val messageId: Long
|
||||
) : Event()
|
@ -0,0 +1,8 @@
|
||||
package me.rhunk.snapenhance.core.event.impl
|
||||
|
||||
import me.rhunk.snapenhance.core.event.Event
|
||||
import me.rhunk.snapenhance.data.wrapper.impl.MessageContent
|
||||
|
||||
class SendMessageWithContentEvent(
|
||||
val messageContent: MessageContent
|
||||
) : Event()
|
@ -1,3 +0,0 @@
|
||||
package me.rhunk.snapenhance.event
|
||||
|
||||
//TODO: addView event
|
@ -1,5 +1,6 @@
|
||||
package me.rhunk.snapenhance.features.impl
|
||||
|
||||
import me.rhunk.snapenhance.core.event.impl.OnSnapInteractionEvent
|
||||
import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID
|
||||
import me.rhunk.snapenhance.features.Feature
|
||||
import me.rhunk.snapenhance.features.FeatureLoadParams
|
||||
@ -72,9 +73,9 @@ class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_C
|
||||
}
|
||||
|
||||
//get last opened snap for media downloader
|
||||
Hooker.hook(context.classCache.snapManager, "onSnapInteraction", HookStage.BEFORE) { param ->
|
||||
openedConversationUUID = SnapUUID(param.arg(1))
|
||||
lastFocusedMessageId = param.arg(2)
|
||||
context.event.subscribe(OnSnapInteractionEvent::class) { event ->
|
||||
openedConversationUUID = event.conversationId
|
||||
lastFocusedMessageId = event.messageId
|
||||
}
|
||||
|
||||
Hooker.hook(context.classCache.conversationManager, "fetchMessage", HookStage.BEFORE) { param ->
|
||||
|
@ -1,6 +1,7 @@
|
||||
package me.rhunk.snapenhance.features.impl.privacy
|
||||
|
||||
import me.rhunk.snapenhance.Logger
|
||||
import me.rhunk.snapenhance.core.event.impl.SendMessageWithContentEvent
|
||||
import me.rhunk.snapenhance.data.NotificationType
|
||||
import me.rhunk.snapenhance.data.wrapper.impl.MessageContent
|
||||
import me.rhunk.snapenhance.features.Feature
|
||||
@ -23,14 +24,13 @@ class PreventMessageSending : Feature("Prevent message sending", loadParams = Fe
|
||||
}
|
||||
}
|
||||
|
||||
context.classCache.conversationManager.hook("sendMessageWithContent", HookStage.BEFORE) { param ->
|
||||
val message = MessageContent(param.arg(1))
|
||||
val contentType = message.contentType
|
||||
val associatedType = NotificationType.fromContentType(contentType) ?: return@hook
|
||||
context.event.subscribe(SendMessageWithContentEvent::class) { event ->
|
||||
val contentType = event.messageContent.contentType
|
||||
val associatedType = NotificationType.fromContentType(contentType) ?: return@subscribe
|
||||
|
||||
if (preventMessageSending.contains(associatedType.key)) {
|
||||
Logger.debug("Preventing message sending for $associatedType")
|
||||
param.setResult(null)
|
||||
event.canceled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package me.rhunk.snapenhance.features.impl.spying
|
||||
|
||||
import me.rhunk.snapenhance.core.event.impl.OnSnapInteractionEvent
|
||||
import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID
|
||||
import me.rhunk.snapenhance.features.Feature
|
||||
import me.rhunk.snapenhance.features.FeatureLoadParams
|
||||
@ -19,9 +20,10 @@ class PreventReadReceipts : Feature("PreventReadReceipts", loadParams = FeatureL
|
||||
it.setResult(null)
|
||||
}
|
||||
}
|
||||
Hooker.hook(context.classCache.snapManager, "onSnapInteraction", HookStage.BEFORE) {
|
||||
if (isConversationInStealthMode(SnapUUID(it.arg(1) as Any))) {
|
||||
it.setResult(null)
|
||||
|
||||
context.event.subscribe(OnSnapInteractionEvent::class) { event ->
|
||||
if (isConversationInStealthMode(event.conversationId)) {
|
||||
event.canceled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user