mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-06-12 05:07:46 +02:00
refactor: wrappers
This commit is contained in:
@ -176,7 +176,7 @@ class ExportChatMessages : AbstractAction() {
|
||||
}
|
||||
|
||||
fetchedMessages.firstOrNull()?.let {
|
||||
lastMessageId = it.messageDescriptor.messageId
|
||||
lastMessageId = it.messageDescriptor!!.messageId!!
|
||||
}
|
||||
setStatus("Exporting (${foundMessages.size} / ${foundMessages.firstOrNull()?.orderKey})")
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class ScopeSync : Feature("Scope Sync", loadParams = FeatureLoadParams.INIT_SYNC
|
||||
if (event.messageContent.contentType != ContentType.SNAP) return@subscribe
|
||||
|
||||
event.addCallbackResult("onSuccess") {
|
||||
event.destinations.conversations.map { it.toString() }.forEach { conversationId ->
|
||||
event.destinations.conversations!!.map { it.toString() }.forEach { conversationId ->
|
||||
updateJobs[conversationId]?.also { it.cancel() }
|
||||
|
||||
updateJobs[conversationId] = (context.coroutineScope.launch {
|
||||
|
@ -77,7 +77,7 @@ object MessageDecoder {
|
||||
|
||||
fun decode(messageContent: MessageContent): List<DecodedAttachment> {
|
||||
return decode(
|
||||
ProtoReader(messageContent.content),
|
||||
ProtoReader(messageContent.content!!),
|
||||
customMediaReferences = getEncodedMediaReferences(gson.toJsonTree(messageContent.instanceNonNull()))
|
||||
)
|
||||
}
|
||||
|
@ -12,10 +12,10 @@ class SnapToChatMedia : Feature("SnapToChatMedia", loadParams = FeatureLoadParam
|
||||
if (!context.config.experimental.snapToChatMedia.get()) return
|
||||
|
||||
context.event.subscribe(BuildMessageEvent::class, priority = 100) { event ->
|
||||
if (event.message.messageContent.contentType != ContentType.SNAP) return@subscribe
|
||||
if (event.message.messageContent!!.contentType != ContentType.SNAP) return@subscribe
|
||||
|
||||
val snapMessageContent = ProtoReader(event.message.messageContent.content).followPath(11)?.getBuffer() ?: return@subscribe
|
||||
event.message.messageContent.content = ProtoWriter().apply {
|
||||
val snapMessageContent = ProtoReader(event.message.messageContent!!.content!!).followPath(11)?.getBuffer() ?: return@subscribe
|
||||
event.message.messageContent!!.content = ProtoWriter().apply {
|
||||
from(3) {
|
||||
addBuffer(3, snapMessageContent)
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class BypassVideoLengthRestriction :
|
||||
})
|
||||
|
||||
context.event.subscribe(SendMessageWithContentEvent::class) { event ->
|
||||
if (event.destinations.stories.isEmpty()) return@subscribe
|
||||
if (event.destinations.stories!!.isEmpty()) return@subscribe
|
||||
fileObserver.startWatching()
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE,
|
||||
}
|
||||
|
||||
private fun saveMessage(conversationId: SnapUUID, message: Message) {
|
||||
val messageId = message.messageDescriptor.messageId
|
||||
if (messageLogger.takeIf { it.isEnabled }?.isMessageDeleted(conversationId.toString(), message.messageDescriptor.messageId) == true) return
|
||||
val messageId = message.messageDescriptor!!.messageId!!
|
||||
if (messageLogger.takeIf { it.isEnabled }?.isMessageDeleted(conversationId.toString(), messageId) == true) return
|
||||
if (message.messageState != MessageState.COMMITTED) return
|
||||
|
||||
runCatching {
|
||||
@ -50,8 +50,8 @@ class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE,
|
||||
|
||||
private fun canSaveMessage(message: Message): Boolean {
|
||||
if (context.mainActivity == null || context.isMainActivityPaused) return false
|
||||
if (message.messageMetadata.savedBy.any { uuid -> uuid.toString() == context.database.myUserId }) return false
|
||||
val contentType = message.messageContent.contentType.toString()
|
||||
if (message.messageMetadata!!.savedBy!!.any { uuid -> uuid.toString() == context.database.myUserId }) return false
|
||||
val contentType = message.messageContent!!.contentType.toString()
|
||||
|
||||
return autoSaveFilter.any { it == contentType }
|
||||
}
|
||||
@ -96,7 +96,7 @@ class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE,
|
||||
{ autoSaveFilter.isNotEmpty() }
|
||||
) { param ->
|
||||
val message = Message(param.arg(0))
|
||||
val conversationId = message.messageDescriptor.conversationId
|
||||
val conversationId = message.messageDescriptor!!.conversationId!!
|
||||
if (!canSaveInConversation(conversationId.toString())) return@hook
|
||||
if (!canSaveMessage(message)) return@hook
|
||||
|
||||
|
@ -68,11 +68,11 @@ class InstantDelete : Feature("InstantDelete", loadParams = FeatureLoadParams.AC
|
||||
|
||||
if (chatActionMenuOptions["chat_action_menu_erase_quote"] == menuOptionText.text) {
|
||||
conversationManager.fetchMessage(conversationId, messageId.toLong(), onSuccess = { message ->
|
||||
val quotedMessage = message.messageContent.quotedMessage.takeIf { it.isPresent() }!!
|
||||
val quotedMessage = message.messageContent!!.quotedMessage!!.takeIf { it.isPresent() }!!
|
||||
|
||||
conversationManager.updateMessage(
|
||||
conversationId,
|
||||
quotedMessage.content.messageId,
|
||||
quotedMessage.content!!.messageId!!,
|
||||
MessageUpdate.ERASE,
|
||||
onResult = onCallbackResult
|
||||
)
|
||||
|
@ -27,7 +27,6 @@ import me.rhunk.snapenhance.core.features.FeatureLoadParams
|
||||
import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader
|
||||
import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder
|
||||
import me.rhunk.snapenhance.core.features.impl.spying.StealthMode
|
||||
import me.rhunk.snapenhance.core.util.CallbackBuilder
|
||||
import me.rhunk.snapenhance.core.util.hook.HookStage
|
||||
import me.rhunk.snapenhance.core.util.hook.hook
|
||||
import me.rhunk.snapenhance.core.util.ktx.setObjectField
|
||||
@ -264,14 +263,14 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN
|
||||
}
|
||||
}
|
||||
|
||||
val contentType = snapMessage.messageContent.contentType ?: return@onEach
|
||||
val contentData = snapMessage.messageContent.content
|
||||
val contentType = snapMessage.messageContent!!.contentType ?: return@onEach
|
||||
val contentData = snapMessage.messageContent!!.content!!
|
||||
|
||||
val formatUsername: (String) -> String = { "$senderUsername: $it" }
|
||||
val notificationCache = cachedMessages.let { it.computeIfAbsent(conversationId) { mutableListOf() } }
|
||||
val appendNotifications: () -> Unit = { setNotificationText(notificationData.notification, conversationId)}
|
||||
|
||||
setupNotificationActionButtons(contentType, conversationId, snapMessage.messageDescriptor.messageId, notificationData)
|
||||
setupNotificationActionButtons(contentType, conversationId, snapMessage.messageDescriptor!!.messageId!!, notificationData)
|
||||
|
||||
when (contentType) {
|
||||
ContentType.NOTE -> {
|
||||
@ -286,14 +285,14 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN
|
||||
}
|
||||
ContentType.SNAP, ContentType.EXTERNAL_MEDIA -> {
|
||||
val mediaReferences = MessageDecoder.getMediaReferences(
|
||||
messageContent = context.gson.toJsonTree(snapMessage.messageContent.instanceNonNull())
|
||||
messageContent = context.gson.toJsonTree(snapMessage.messageContent!!.instanceNonNull())
|
||||
)
|
||||
|
||||
val mediaReferenceKeys = mediaReferences.map { reference ->
|
||||
reference.asJsonObject.getAsJsonArray("mContentObject").map { it.asByte }.toByteArray()
|
||||
}
|
||||
|
||||
MessageDecoder.decode(snapMessage.messageContent).firstOrNull()?.also { media ->
|
||||
MessageDecoder.decode(snapMessage.messageContent!!).firstOrNull()?.also { media ->
|
||||
val mediaType = MediaReferenceType.valueOf(mediaReferences.first().asJsonObject["mMediaType"].asString)
|
||||
|
||||
runCatching {
|
||||
|
@ -58,7 +58,7 @@ class SendOverride : Feature("Send Override", loadParams = FeatureLoadParams.INI
|
||||
if (localMessageContent.contentType != ContentType.EXTERNAL_MEDIA) return@subscribe
|
||||
|
||||
//prevent story replies
|
||||
val messageProtoReader = ProtoReader(localMessageContent.content)
|
||||
val messageProtoReader = ProtoReader(localMessageContent.content!!)
|
||||
if (messageProtoReader.contains(7)) return@subscribe
|
||||
|
||||
event.canceled = true
|
||||
|
@ -15,13 +15,13 @@ class UnlimitedSnapViewTime :
|
||||
|
||||
context.event.subscribe(BuildMessageEvent::class, { state }, priority = 101) { event ->
|
||||
if (event.message.messageState != MessageState.COMMITTED) return@subscribe
|
||||
if (event.message.messageContent.contentType != ContentType.SNAP) return@subscribe
|
||||
if (event.message.messageContent!!.contentType != ContentType.SNAP) return@subscribe
|
||||
|
||||
val messageContent = event.message.messageContent
|
||||
|
||||
val mediaAttributes = ProtoReader(messageContent.content).followPath(11, 5, 2) ?: return@subscribe
|
||||
val mediaAttributes = ProtoReader(messageContent!!.content!!).followPath(11, 5, 2) ?: return@subscribe
|
||||
if (mediaAttributes.contains(6)) return@subscribe
|
||||
messageContent.content = ProtoEditor(messageContent.content).apply {
|
||||
messageContent.content = ProtoEditor(messageContent.content!!).apply {
|
||||
edit(11, 5, 2) {
|
||||
remove(8)
|
||||
addBuffer(6, byteArrayOf())
|
||||
|
@ -101,14 +101,14 @@ class MessageLogger : Feature("MessageLogger",
|
||||
val messageInstance = event.message.instanceNonNull()
|
||||
if (event.message.messageState != MessageState.COMMITTED) return@subscribe
|
||||
|
||||
cachedIdLinks[event.message.messageDescriptor.messageId] = event.message.orderKey
|
||||
val conversationId = event.message.messageDescriptor.conversationId.toString()
|
||||
cachedIdLinks[event.message.messageDescriptor!!.messageId!!] = event.message.orderKey!!
|
||||
val conversationId = event.message.messageDescriptor!!.conversationId.toString()
|
||||
//exclude messages sent by me
|
||||
if (event.message.senderId.toString() == context.database.myUserId) return@subscribe
|
||||
|
||||
val uniqueMessageIdentifier = computeMessageIdentifier(conversationId, event.message.orderKey)
|
||||
val uniqueMessageIdentifier = computeMessageIdentifier(conversationId, event.message.orderKey!!)
|
||||
|
||||
if (event.message.messageContent.contentType != ContentType.STATUS) {
|
||||
if (event.message.messageContent!!.contentType != ContentType.STATUS) {
|
||||
if (fetchedMessages.contains(uniqueMessageIdentifier)) return@subscribe
|
||||
fetchedMessages.add(uniqueMessageIdentifier)
|
||||
|
||||
|
@ -13,13 +13,13 @@ import me.rhunk.snapenhance.core.features.impl.messaging.Messaging
|
||||
|
||||
fun me.rhunk.snapenhance.core.wrapper.impl.Message.toBridge(): Message {
|
||||
return Message().also { output ->
|
||||
output.conversationId = this.messageDescriptor.conversationId.toString()
|
||||
output.conversationId = this.messageDescriptor!!.conversationId.toString()
|
||||
output.senderId = this.senderId.toString()
|
||||
output.clientMessageId = this.messageDescriptor.messageId
|
||||
output.serverMessageId = this.orderKey
|
||||
output.contentType = this.messageContent.contentType?.id ?: -1
|
||||
output.content = this.messageContent.content
|
||||
output.mediaReferences = MessageDecoder.getEncodedMediaReferences(this.messageContent)
|
||||
output.clientMessageId = this.messageDescriptor!!.messageId!!
|
||||
output.serverMessageId = this.orderKey!!
|
||||
output.contentType = this.messageContent?.contentType?.id ?: -1
|
||||
output.content = this.messageContent?.content
|
||||
output.mediaReferences = MessageDecoder.getEncodedMediaReferences(this.messageContent!!)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,8 +74,8 @@ class MessageExporter(
|
||||
}
|
||||
|
||||
private fun serializeMessageContent(message: Message): String? {
|
||||
return if (message.messageContent.contentType == ContentType.CHAT) {
|
||||
ProtoReader(message.messageContent.content).getString(2, 1) ?: "Failed to parse message"
|
||||
return if (message.messageContent!!.contentType == ContentType.CHAT) {
|
||||
ProtoReader(message.messageContent!!.content!!).getString(2, 1) ?: "Failed to parse message"
|
||||
} else null
|
||||
}
|
||||
|
||||
@ -93,8 +93,8 @@ class MessageExporter(
|
||||
val sender = conversationParticipants[message.senderId.toString()]
|
||||
val senderUsername = sender?.usernameForSorting ?: message.senderId.toString()
|
||||
val senderDisplayName = sender?.displayName ?: message.senderId.toString()
|
||||
val messageContent = serializeMessageContent(message) ?: message.messageContent.contentType?.name
|
||||
val date = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH).format(Date(message.messageMetadata.createdAt))
|
||||
val messageContent = serializeMessageContent(message) ?: message.messageContent!!.contentType?.name
|
||||
val date = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH).format(Date(message.messageMetadata!!.createdAt!!))
|
||||
writer.write("[$date] - $senderDisplayName (${senderUsername}): $messageContent\n")
|
||||
}
|
||||
writer.flush()
|
||||
@ -110,17 +110,17 @@ class MessageExporter(
|
||||
|
||||
fun updateProgress(type: String) {
|
||||
val total = messages.filter {
|
||||
mediaToDownload?.contains(it.messageContent.contentType) ?: false
|
||||
mediaToDownload?.contains(it.messageContent!!.contentType) ?: false
|
||||
}.size
|
||||
processCount++
|
||||
printLog("$type $processCount/$total")
|
||||
}
|
||||
|
||||
messages.filter {
|
||||
mediaToDownload?.contains(it.messageContent.contentType) ?: false
|
||||
mediaToDownload?.contains(it.messageContent!!.contentType) ?: false
|
||||
}.forEach { message ->
|
||||
threadPool.execute {
|
||||
MessageDecoder.decode(message.messageContent).forEach decode@{ attachment ->
|
||||
MessageDecoder.decode(message.messageContent!!).forEach decode@{ attachment ->
|
||||
val protoMediaReference = Base64.UrlSafe.decode(attachment.mediaUrlKey ?: return@decode)
|
||||
|
||||
runCatching {
|
||||
@ -145,8 +145,8 @@ class MessageExporter(
|
||||
|
||||
updateProgress("downloaded")
|
||||
}.onFailure {
|
||||
printLog("failed to download media for ${message.messageDescriptor.conversationId}_${message.orderKey}")
|
||||
context.log.error("failed to download media for ${message.messageDescriptor.conversationId}_${message.orderKey}", it)
|
||||
printLog("failed to download media for ${message.messageDescriptor!!.conversationId}_${message.orderKey}")
|
||||
context.log.error("failed to download media for ${message.messageDescriptor!!.conversationId}_${message.orderKey}", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -270,7 +270,7 @@ class MessageExporter(
|
||||
add(JsonObject().apply {
|
||||
addProperty("orderKey", message.orderKey)
|
||||
addProperty("senderId", participants.getOrDefault(message.senderId.toString(), -1))
|
||||
addProperty("type", message.messageContent.contentType.toString())
|
||||
addProperty("type", message.messageContent!!.contentType.toString())
|
||||
|
||||
fun addUUIDList(name: String, list: List<SnapUUID>) {
|
||||
add(name, JsonArray().apply {
|
||||
@ -278,12 +278,12 @@ class MessageExporter(
|
||||
})
|
||||
}
|
||||
|
||||
addUUIDList("savedBy", message.messageMetadata.savedBy)
|
||||
addUUIDList("seenBy", message.messageMetadata.seenBy)
|
||||
addUUIDList("openedBy", message.messageMetadata.openedBy)
|
||||
addUUIDList("savedBy", message.messageMetadata!!.savedBy!!)
|
||||
addUUIDList("seenBy", message.messageMetadata!!.seenBy!!)
|
||||
addUUIDList("openedBy", message.messageMetadata!!.openedBy!!)
|
||||
|
||||
add("reactions", JsonObject().apply {
|
||||
message.messageMetadata.reactions.forEach { reaction ->
|
||||
message.messageMetadata!!.reactions!!.forEach { reaction ->
|
||||
addProperty(
|
||||
participants.getOrDefault(reaction.userId.toString(), -1L).toString(),
|
||||
reaction.reactionId
|
||||
@ -291,13 +291,13 @@ class MessageExporter(
|
||||
}
|
||||
})
|
||||
|
||||
addProperty("createdTimestamp", message.messageMetadata.createdAt)
|
||||
addProperty("readTimestamp", message.messageMetadata.readAt)
|
||||
addProperty("createdTimestamp", message.messageMetadata!!.createdAt)
|
||||
addProperty("readTimestamp", message.messageMetadata!!.readAt)
|
||||
addProperty("serializedContent", serializeMessageContent(message))
|
||||
addProperty("rawContent", Base64.UrlSafe.encode(message.messageContent.content))
|
||||
addProperty("rawContent", Base64.UrlSafe.encode(message.messageContent!!.content!!))
|
||||
|
||||
add("attachments", JsonArray().apply {
|
||||
MessageDecoder.decode(message.messageContent)
|
||||
MessageDecoder.decode(message.messageContent!!)
|
||||
.forEach attachments@{ attachments ->
|
||||
if (attachments.type == AttachmentType.STICKER) //TODO: implement stickers
|
||||
return@attachments
|
||||
|
@ -94,12 +94,12 @@ class MessageSender(
|
||||
|
||||
val localMessageContent = context.gson.fromJson(localMessageContentTemplate, context.classCache.localMessageContent)
|
||||
val messageDestinations = MessageDestinations(AbstractWrapper.newEmptyInstance(context.classCache.messageDestinations)).also {
|
||||
it.conversations = conversations
|
||||
it.mPhoneNumbers = arrayListOf()
|
||||
it.stories = arrayListOf()
|
||||
it.conversations = conversations.toCollection(ArrayList())
|
||||
it.mPhoneNumbers = arrayListOf<Any>()
|
||||
it.stories = arrayListOf<Any>()
|
||||
}
|
||||
|
||||
sendMessageWithContentMethod.invoke(context.feature(Messaging::class).conversationManager, messageDestinations.instanceNonNull(), localMessageContent, callback)
|
||||
sendMessageWithContentMethod.invoke(context.feature(Messaging::class).conversationManager?.instanceNonNull(), messageDestinations.instanceNonNull(), localMessageContent, callback)
|
||||
}
|
||||
|
||||
fun sendChatMessage(conversations: List<SnapUUID>, message: String, onError: (Any) -> Unit = {}, onSuccess: () -> Unit = {}) {
|
||||
|
@ -2,24 +2,47 @@ package me.rhunk.snapenhance.core.wrapper
|
||||
|
||||
import de.robv.android.xposed.XposedHelpers
|
||||
import me.rhunk.snapenhance.core.util.CallbackBuilder
|
||||
import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
abstract class AbstractWrapper(
|
||||
protected var instance: Any?
|
||||
) {
|
||||
protected val uuidArrayListMapper: (Any?) -> ArrayList<SnapUUID> get() = { (it as ArrayList<*>).map { i -> SnapUUID(i) }.toCollection(ArrayList()) }
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inner class EnumAccessor<T>(private val fieldName: String, private val defaultValue: T) {
|
||||
operator fun getValue(obj: Any, property: KProperty<*>): T? = getEnumValue(fieldName, defaultValue as Enum<*>) as? T
|
||||
operator fun setValue(obj: Any, property: KProperty<*>, value: Any?) = setEnumValue(fieldName, value as Enum<*>)
|
||||
}
|
||||
|
||||
inner class FieldAccessor<T>(private val fieldName: String, private val mapper: ((Any?) -> T?)? = null) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
operator fun getValue(obj: Any, property: KProperty<*>): T? {
|
||||
val value = XposedHelpers.getObjectField(instance, fieldName)
|
||||
return if (mapper != null) {
|
||||
mapper.invoke(value)
|
||||
} else {
|
||||
value as? T
|
||||
}
|
||||
}
|
||||
|
||||
operator fun setValue(obj: Any, property: KProperty<*>, value: Any?) {
|
||||
XposedHelpers.setObjectField(instance, fieldName, when (value) {
|
||||
is AbstractWrapper -> value.instance
|
||||
is ArrayList<*> -> value.map { if (it is AbstractWrapper) it.instance else it }.toMutableList()
|
||||
else -> value
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newEmptyInstance(clazz: Class<*>): Any {
|
||||
return CallbackBuilder.createEmptyObject(clazz.constructors[0]) ?: throw NullPointerException()
|
||||
}
|
||||
}
|
||||
|
||||
fun instanceNonNull(): Any = instance!!
|
||||
fun instanceNonNull(): Any = instance ?: throw NullPointerException("Instance of ${this::class.simpleName} is null")
|
||||
fun isPresent(): Boolean = instance != null
|
||||
|
||||
override fun hashCode(): Int {
|
||||
@ -31,6 +54,7 @@ abstract class AbstractWrapper(
|
||||
}
|
||||
|
||||
protected fun <T> enum(fieldName: String, defaultValue: T) = EnumAccessor(fieldName, defaultValue)
|
||||
protected fun <T> field(fieldName: String, mapper: ((Any?) -> T?)? = null) = FieldAccessor(fieldName, mapper)
|
||||
|
||||
fun <T : Enum<*>> getEnumValue(fieldName: String, defaultValue: T?): T? {
|
||||
if (defaultValue == null) return null
|
||||
|
@ -7,7 +7,10 @@ import me.rhunk.snapenhance.core.wrapper.AbstractWrapper
|
||||
|
||||
typealias CallbackResult = (error: String?) -> Unit
|
||||
|
||||
class ConversationManager(val context: ModContext, obj: Any) : AbstractWrapper(obj) {
|
||||
class ConversationManager(
|
||||
val context: ModContext,
|
||||
obj: Any
|
||||
) : AbstractWrapper(obj) {
|
||||
private fun findMethodByName(name: String) = context.classCache.conversationManager.declaredMethods.find { it.name == name } ?: throw RuntimeException("Could not find method $name")
|
||||
|
||||
private val updateMessageMethod by lazy { findMethodByName("updateMessage") }
|
||||
|
@ -1,38 +0,0 @@
|
||||
package me.rhunk.snapenhance.core.wrapper.impl
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import me.rhunk.snapenhance.core.SnapEnhance
|
||||
import me.rhunk.snapenhance.core.wrapper.AbstractWrapper
|
||||
|
||||
class FriendActionButton(
|
||||
obj: View
|
||||
) : AbstractWrapper(obj) {
|
||||
private val iconDrawableContainer by lazy {
|
||||
instanceNonNull().javaClass.declaredFields.first { it.type != Int::class.javaPrimitiveType }[instanceNonNull()]
|
||||
}
|
||||
|
||||
private val setIconDrawableMethod by lazy {
|
||||
iconDrawableContainer.javaClass.declaredMethods.first {
|
||||
it.parameterTypes.size == 1 &&
|
||||
it.parameterTypes[0] == Drawable::class.java &&
|
||||
it.name != "invalidateDrawable" &&
|
||||
it.returnType == Void::class.javaPrimitiveType
|
||||
}
|
||||
}
|
||||
|
||||
fun setIconDrawable(drawable: Drawable) {
|
||||
setIconDrawableMethod.invoke(iconDrawableContainer, drawable)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun new(context: Context): FriendActionButton {
|
||||
val instance = SnapEnhance.classLoader.loadClass("com.snap.profile.shared.view.FriendActionButton")
|
||||
.getConstructor(Context::class.java, AttributeSet::class.java)
|
||||
.newInstance(context, null) as View
|
||||
return FriendActionButton(instance)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,21 @@
|
||||
package me.rhunk.snapenhance.core.wrapper.impl
|
||||
|
||||
import me.rhunk.snapenhance.common.data.MessageState
|
||||
import me.rhunk.snapenhance.core.util.ktx.getObjectField
|
||||
import me.rhunk.snapenhance.core.wrapper.AbstractWrapper
|
||||
import org.mozilla.javascript.annotations.JSGetter
|
||||
import org.mozilla.javascript.annotations.JSSetter
|
||||
|
||||
class Message(obj: Any?) : AbstractWrapper(obj) {
|
||||
val orderKey get() = instanceNonNull().getObjectField("mOrderKey") as Long
|
||||
val senderId get() = SnapUUID(instanceNonNull().getObjectField("mSenderId"))
|
||||
val messageContent get() = MessageContent(instanceNonNull().getObjectField("mMessageContent"))
|
||||
val messageDescriptor get() = MessageDescriptor(instanceNonNull().getObjectField("mDescriptor"))
|
||||
val messageMetadata get() = MessageMetadata(instanceNonNull().getObjectField("mMetadata"))
|
||||
@get:JSGetter @set:JSSetter
|
||||
var orderKey by field<Long>("mOrderKey")
|
||||
@get:JSGetter @set:JSSetter
|
||||
var senderId by field("mSenderId") { SnapUUID(it) }
|
||||
@get:JSGetter @set:JSSetter
|
||||
var messageContent by field("mMessageContent") { MessageContent(it) }
|
||||
@get:JSGetter @set:JSSetter
|
||||
var messageDescriptor by field("mDescriptor") { MessageDescriptor(it) }
|
||||
@get:JSGetter @set:JSSetter
|
||||
var messageMetadata by field("mMetadata") { MessageMetadata(it) }
|
||||
@get:JSGetter @set:JSSetter
|
||||
var messageState by enum("mState", MessageState.COMMITTED)
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
package me.rhunk.snapenhance.core.wrapper.impl
|
||||
|
||||
import me.rhunk.snapenhance.common.data.ContentType
|
||||
import me.rhunk.snapenhance.core.util.ktx.getObjectField
|
||||
import me.rhunk.snapenhance.core.util.ktx.setObjectField
|
||||
import me.rhunk.snapenhance.core.wrapper.AbstractWrapper
|
||||
import org.mozilla.javascript.annotations.JSGetter
|
||||
import org.mozilla.javascript.annotations.JSSetter
|
||||
|
||||
class MessageContent(obj: Any?) : AbstractWrapper(obj) {
|
||||
var content
|
||||
get() = instanceNonNull().getObjectField("mContent") as ByteArray
|
||||
set(value) = instanceNonNull().setObjectField("mContent", value)
|
||||
val quotedMessage
|
||||
get() = QuotedMessage(instanceNonNull().getObjectField("mQuotedMessage"))
|
||||
@get:JSGetter @set:JSSetter
|
||||
var content by field<ByteArray>("mContent")
|
||||
@get:JSGetter @set:JSSetter
|
||||
var quotedMessage by field("mQuotedMessage") { QuotedMessage(it) }
|
||||
@get:JSGetter @set:JSSetter
|
||||
var contentType by enum("mContentType", ContentType.UNKNOWN)
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
package me.rhunk.snapenhance.core.wrapper.impl
|
||||
|
||||
import me.rhunk.snapenhance.core.util.ktx.getObjectField
|
||||
import me.rhunk.snapenhance.core.wrapper.AbstractWrapper
|
||||
import org.mozilla.javascript.annotations.JSGetter
|
||||
import org.mozilla.javascript.annotations.JSSetter
|
||||
|
||||
class MessageDescriptor(obj: Any?) : AbstractWrapper(obj) {
|
||||
val messageId: Long get() = instanceNonNull().getObjectField("mMessageId") as Long
|
||||
val conversationId: SnapUUID get() = SnapUUID(instanceNonNull().getObjectField("mConversationId")!!)
|
||||
@get:JSGetter @set:JSSetter
|
||||
var messageId by field<Long>("mMessageId")
|
||||
val conversationId by field("mConversationId") { SnapUUID(it) }
|
||||
}
|
@ -1,15 +1,10 @@
|
||||
package me.rhunk.snapenhance.core.wrapper.impl
|
||||
|
||||
import me.rhunk.snapenhance.core.util.ktx.getObjectField
|
||||
import me.rhunk.snapenhance.core.util.ktx.setObjectField
|
||||
import me.rhunk.snapenhance.core.wrapper.AbstractWrapper
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class MessageDestinations(obj: Any) : AbstractWrapper(obj){
|
||||
var conversations get() = (instanceNonNull().getObjectField("mConversations") as ArrayList<*>).map { SnapUUID(it) }
|
||||
set(value) = instanceNonNull().setObjectField("mConversations", value.map { it.instanceNonNull() }.toCollection(ArrayList()))
|
||||
var stories get() = instanceNonNull().getObjectField("mStories") as ArrayList<Any>
|
||||
set(value) = instanceNonNull().setObjectField("mStories", value)
|
||||
var mPhoneNumbers get() = instanceNonNull().getObjectField("mPhoneNumbers") as ArrayList<Any>
|
||||
set(value) = instanceNonNull().setObjectField("mPhoneNumbers", value)
|
||||
var conversations by field("mConversations", uuidArrayListMapper)
|
||||
var stories by field<ArrayList<*>>("mStories")
|
||||
var mPhoneNumbers by field<ArrayList<*>>("mPhoneNumbers")
|
||||
}
|
@ -1,28 +1,26 @@
|
||||
package me.rhunk.snapenhance.core.wrapper.impl
|
||||
|
||||
import me.rhunk.snapenhance.common.data.PlayableSnapState
|
||||
import me.rhunk.snapenhance.core.util.ktx.getObjectField
|
||||
import me.rhunk.snapenhance.core.wrapper.AbstractWrapper
|
||||
import org.mozilla.javascript.annotations.JSGetter
|
||||
import org.mozilla.javascript.annotations.JSSetter
|
||||
|
||||
class MessageMetadata(obj: Any?) : AbstractWrapper(obj){
|
||||
val createdAt: Long get() = instanceNonNull().getObjectField("mCreatedAt") as Long
|
||||
val readAt: Long get() = instanceNonNull().getObjectField("mReadAt") as Long
|
||||
@get:JSGetter @set:JSSetter
|
||||
var createdAt by field<Long>("mCreatedAt")
|
||||
@get:JSGetter @set:JSSetter
|
||||
var readAt by field<Long>("mReadAt")
|
||||
@get:JSGetter @set:JSSetter
|
||||
var playableSnapState by enum("mPlayableSnapState", PlayableSnapState.PLAYABLE)
|
||||
|
||||
private fun getUUIDList(name: String): List<SnapUUID> {
|
||||
return (instanceNonNull().getObjectField(name) as List<*>).map { SnapUUID(it!!) }
|
||||
}
|
||||
|
||||
val savedBy: List<SnapUUID> by lazy {
|
||||
getUUIDList("mSavedBy")
|
||||
}
|
||||
val openedBy: List<SnapUUID> by lazy {
|
||||
getUUIDList("mOpenedBy")
|
||||
}
|
||||
val seenBy: List<SnapUUID> by lazy {
|
||||
getUUIDList("mSeenBy")
|
||||
}
|
||||
val reactions: List<UserIdToReaction> by lazy {
|
||||
(instanceNonNull().getObjectField("mReactions") as List<*>).map { UserIdToReaction(it!!) }
|
||||
@get:JSGetter @set:JSSetter
|
||||
var savedBy by field("mSavedBy", uuidArrayListMapper)
|
||||
@get:JSGetter @set:JSSetter
|
||||
var openedBy by field("mOpenedBy", uuidArrayListMapper)
|
||||
@get:JSGetter @set:JSSetter
|
||||
var seenBy by field("mSeenBy", uuidArrayListMapper)
|
||||
@get:JSGetter @set:JSSetter
|
||||
var reactions by field("mReactions") {
|
||||
(it as ArrayList<*>).map { i -> UserIdToReaction(i) }.toMutableList()
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
package me.rhunk.snapenhance.core.wrapper.impl
|
||||
|
||||
import me.rhunk.snapenhance.core.util.ktx.getObjectField
|
||||
import me.rhunk.snapenhance.core.wrapper.AbstractWrapper
|
||||
import org.mozilla.javascript.annotations.JSGetter
|
||||
import org.mozilla.javascript.annotations.JSSetter
|
||||
|
||||
class QuotedMessage(obj: Any?) : AbstractWrapper(obj) {
|
||||
val content get() = QuotedMessageContent(instanceNonNull().getObjectField("mContent"))
|
||||
@get:JSGetter @set:JSSetter
|
||||
var content by field("mContent") { QuotedMessageContent(it) }
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
package me.rhunk.snapenhance.core.wrapper.impl
|
||||
|
||||
import me.rhunk.snapenhance.core.util.ktx.getObjectField
|
||||
import me.rhunk.snapenhance.core.util.ktx.setObjectField
|
||||
import me.rhunk.snapenhance.core.wrapper.AbstractWrapper
|
||||
import org.mozilla.javascript.annotations.JSGetter
|
||||
import org.mozilla.javascript.annotations.JSSetter
|
||||
|
||||
class QuotedMessageContent(obj: Any?) : AbstractWrapper(obj) {
|
||||
var messageId get() = instanceNonNull().getObjectField("mMessageId") as Long
|
||||
set(value) = instanceNonNull().setObjectField("mMessageId", value)
|
||||
@get:JSGetter @set:JSSetter
|
||||
var messageId by field<Long>("mMessageId")
|
||||
}
|
@ -1,11 +1,21 @@
|
||||
package me.rhunk.snapenhance.core.wrapper.impl
|
||||
|
||||
import me.rhunk.snapenhance.core.util.ktx.getObjectField
|
||||
import me.rhunk.snapenhance.core.util.ktx.setObjectField
|
||||
import me.rhunk.snapenhance.core.wrapper.AbstractWrapper
|
||||
import org.mozilla.javascript.annotations.JSGetter
|
||||
import org.mozilla.javascript.annotations.JSSetter
|
||||
|
||||
class UserIdToReaction(obj: Any?) : AbstractWrapper(obj) {
|
||||
val userId = SnapUUID(instanceNonNull().getObjectField("mUserId"))
|
||||
val reactionId = (instanceNonNull().getObjectField("mReaction")
|
||||
@get:JSGetter @set:JSSetter
|
||||
var userId by field("mUserId") { SnapUUID(it) }
|
||||
@get:JSGetter @set:JSSetter
|
||||
var reactionId get() = (instanceNonNull().getObjectField("mReaction")
|
||||
?.getObjectField("mReactionContent")
|
||||
?.getObjectField("mIntentionType") as Long?) ?: 0
|
||||
?.getObjectField("mIntentionType") as Long?) ?: -1
|
||||
set(value) {
|
||||
instanceNonNull().getObjectField("mReaction")
|
||||
?.getObjectField("mReactionContent")
|
||||
?.setObjectField("mIntentionType", value)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user