mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-31 22:10:18 +02:00
feat(ui/new_chat_action_menu): debug view
This commit is contained in:
parent
7619cc0b8e
commit
72cfd7a8bc
@ -40,6 +40,7 @@ class MenuViewInjector : Feature("MenuViewInjector", loadParams = FeatureLoadPar
|
|||||||
val componentsHolder = context.resources.getIdentifier("components_holder", "id")
|
val componentsHolder = context.resources.getIdentifier("components_holder", "id")
|
||||||
val feedNewChat = context.resources.getIdentifier("feed_new_chat", "id")
|
val feedNewChat = context.resources.getIdentifier("feed_new_chat", "id")
|
||||||
val contextMenuButtonIconView = context.resources.getIdentifier("context_menu_button_icon_view", "id")
|
val contextMenuButtonIconView = context.resources.getIdentifier("context_menu_button_icon_view", "id")
|
||||||
|
val chatActionMenu = context.resources.getIdentifier("chat_action_menu", "id")
|
||||||
|
|
||||||
context.event.subscribe(AddViewEvent::class) { event ->
|
context.event.subscribe(AddViewEvent::class) { event ->
|
||||||
val originalAddView: (View) -> Unit = {
|
val originalAddView: (View) -> Unit = {
|
||||||
@ -75,6 +76,16 @@ class MenuViewInjector : Feature("MenuViewInjector", loadParams = FeatureLoadPar
|
|||||||
return@subscribe
|
return@subscribe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (viewGroup !is LinearLayout && childView.id == chatActionMenu && context.config.experimental.newChatActionMenu.get() && context.isDeveloper) {
|
||||||
|
event.view = LinearLayout(childView.context).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
addView(
|
||||||
|
(menuMap[NewChatActionMenu::class]!! as NewChatActionMenu).createDebugInfoView(childView.context)
|
||||||
|
)
|
||||||
|
addView(event.view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (childView.javaClass.name.endsWith("ChatActionMenuComponent") && context.config.experimental.newChatActionMenu.get()) {
|
if (childView.javaClass.name.endsWith("ChatActionMenuComponent") && context.config.experimental.newChatActionMenu.get()) {
|
||||||
(menuMap[NewChatActionMenu::class]!! as NewChatActionMenu).handle(event)
|
(menuMap[NewChatActionMenu::class]!! as NewChatActionMenu).handle(event)
|
||||||
return@subscribe
|
return@subscribe
|
||||||
|
@ -1,56 +1,28 @@
|
|||||||
package me.rhunk.snapenhance.core.ui.menu.impl
|
package me.rhunk.snapenhance.core.ui.menu.impl
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
|
||||||
import android.text.format.Formatter
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.ViewGroup.MarginLayoutParams
|
import android.view.ViewGroup.MarginLayoutParams
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
|
||||||
import androidx.compose.foundation.layout.FlowRow
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import me.rhunk.snapenhance.common.data.ContentType
|
|
||||||
import me.rhunk.snapenhance.common.ui.createComposeView
|
|
||||||
import me.rhunk.snapenhance.common.util.ktx.copyToClipboard
|
|
||||||
import me.rhunk.snapenhance.common.util.protobuf.ProtoReader
|
|
||||||
import me.rhunk.snapenhance.common.util.snap.RemoteMediaResolver
|
|
||||||
import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader
|
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.experiments.ConvertMessageLocally
|
import me.rhunk.snapenhance.core.features.impl.experiments.ConvertMessageLocally
|
||||||
import me.rhunk.snapenhance.core.features.impl.messaging.Messaging
|
import me.rhunk.snapenhance.core.features.impl.messaging.Messaging
|
||||||
import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger
|
import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger
|
||||||
import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper
|
|
||||||
import me.rhunk.snapenhance.core.ui.ViewTagState
|
import me.rhunk.snapenhance.core.ui.ViewTagState
|
||||||
import me.rhunk.snapenhance.core.ui.applyTheme
|
import me.rhunk.snapenhance.core.ui.applyTheme
|
||||||
import me.rhunk.snapenhance.core.ui.debugEditText
|
|
||||||
import me.rhunk.snapenhance.core.ui.menu.AbstractMenu
|
import me.rhunk.snapenhance.core.ui.menu.AbstractMenu
|
||||||
import me.rhunk.snapenhance.core.ui.triggerCloseTouchEvent
|
import me.rhunk.snapenhance.core.ui.triggerCloseTouchEvent
|
||||||
import me.rhunk.snapenhance.core.util.hook.HookStage
|
import me.rhunk.snapenhance.core.util.hook.HookStage
|
||||||
import me.rhunk.snapenhance.core.util.hook.hook
|
import me.rhunk.snapenhance.core.util.hook.hook
|
||||||
import me.rhunk.snapenhance.core.util.ktx.getDimens
|
import me.rhunk.snapenhance.core.util.ktx.getDimens
|
||||||
import me.rhunk.snapenhance.core.util.ktx.vibrateLongPress
|
import me.rhunk.snapenhance.core.util.ktx.vibrateLongPress
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Date
|
|
||||||
import kotlin.io.encoding.Base64
|
|
||||||
import kotlin.io.encoding.ExperimentalEncodingApi
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("DiscouragedApi")
|
|
||||||
class ChatActionMenu : AbstractMenu() {
|
class ChatActionMenu : AbstractMenu() {
|
||||||
private val viewTagState = ViewTagState()
|
private val viewTagState = ViewTagState()
|
||||||
|
|
||||||
private val defaultGap by lazy { context.resources.getDimens("default_gap") }
|
private val defaultGap by lazy { context.resources.getDimens("default_gap") }
|
||||||
|
|
||||||
private val chatActionMenuItemMargin by lazy { context.resources.getDimens("chat_action_menu_item_margin") }
|
private val chatActionMenuItemMargin by lazy { context.resources.getDimens("chat_action_menu_item_margin") }
|
||||||
|
|
||||||
private val actionMenuItemHeight by lazy { context.resources.getDimens("action_menu_item_height") }
|
private val actionMenuItemHeight by lazy { context.resources.getDimens("action_menu_item_height") }
|
||||||
|
|
||||||
private fun createContainer(viewGroup: ViewGroup): LinearLayout {
|
private fun createContainer(viewGroup: ViewGroup): LinearLayout {
|
||||||
@ -68,29 +40,13 @@ class ChatActionMenu : AbstractMenu() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun debugAlertDialog(context: Context, title: String, text: String) {
|
|
||||||
this@ChatActionMenu.context.runOnUiThread {
|
|
||||||
ViewAppearanceHelper.newAlertDialogBuilder(context).apply {
|
|
||||||
setTitle(title)
|
|
||||||
setView(debugEditText(context, text))
|
|
||||||
setPositiveButton("OK") { dialog, _ -> dialog.dismiss() }
|
|
||||||
setNegativeButton("Copy") { _, _ ->
|
|
||||||
context.copyToClipboard(text, title)
|
|
||||||
}
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val lastFocusedMessage
|
|
||||||
get() = context.database.getConversationMessageFromId(context.feature(Messaging::class).lastFocusedMessageId)
|
|
||||||
|
|
||||||
override fun init() {
|
override fun init() {
|
||||||
runCatching {
|
runCatching {
|
||||||
if (!context.config.downloader.downloadContextMenu.get() && context.config.messaging.messageLogger.globalState != true && !context.isDeveloper) return
|
if (!context.config.downloader.downloadContextMenu.get() && context.config.messaging.messageLogger.globalState != true && !context.isDeveloper) return
|
||||||
context.androidContext.classLoader.loadClass("com.snap.messaging.chat.features.actionmenu.ActionMenuChatItemContainer")
|
context.androidContext.classLoader.loadClass("com.snap.messaging.chat.features.actionmenu.ActionMenuChatItemContainer")
|
||||||
.hook("onMeasure", HookStage.BEFORE) { param ->
|
.hook("onMeasure", HookStage.BEFORE) { param ->
|
||||||
param.setArg(1,
|
param.setArg(1,
|
||||||
View.MeasureSpec.makeMeasureSpec((context.resources.displayMetrics.heightPixels * 0.35).toInt(), View.MeasureSpec.AT_MOST)
|
View.MeasureSpec.makeMeasureSpec((context.resources.displayMetrics.heightPixels * 0.25).toInt(), View.MeasureSpec.AT_MOST)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
@ -98,8 +54,6 @@ class ChatActionMenu : AbstractMenu() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class, ExperimentalEncodingApi::class)
|
|
||||||
@SuppressLint("SetTextI18n", "DiscouragedApi", "ClickableViewAccessibility")
|
|
||||||
override fun inject(parent: ViewGroup, view: View, viewConsumer: (View) -> Unit) {
|
override fun inject(parent: ViewGroup, view: View, viewConsumer: (View) -> Unit) {
|
||||||
val viewGroup = parent.parent.parent as? ViewGroup ?: return
|
val viewGroup = parent.parent.parent as? ViewGroup ?: return
|
||||||
if (viewTagState[viewGroup]) return
|
if (viewTagState[viewGroup]) return
|
||||||
@ -202,108 +156,6 @@ class ChatActionMenu : AbstractMenu() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.isDeveloper) {
|
|
||||||
val composeDebugView = createComposeView(viewGroup.context) {
|
|
||||||
FlowRow(
|
|
||||||
modifier = Modifier.fillMaxWidth().padding(5.dp),
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(3.dp)
|
|
||||||
) {
|
|
||||||
Button(onClick = {
|
|
||||||
val arroyoMessage = lastFocusedMessage ?: return@Button
|
|
||||||
debugAlertDialog(viewGroup.context,
|
|
||||||
"Message Info",
|
|
||||||
StringBuilder().apply {
|
|
||||||
runCatching {
|
|
||||||
append("conversation_id: ${arroyoMessage.clientConversationId}\n")
|
|
||||||
append("sender_id: ${arroyoMessage.senderId}\n")
|
|
||||||
append("client_id: ${arroyoMessage.clientMessageId}, server_id: ${arroyoMessage.serverMessageId}\n")
|
|
||||||
append("content_type: ${ContentType.fromId(arroyoMessage.contentType)} (${arroyoMessage.contentType})\n")
|
|
||||||
append("parsed_content_type: ${
|
|
||||||
ContentType.fromMessageContainer(
|
|
||||||
ProtoReader(arroyoMessage.messageContent!!).followPath(4, 4)
|
|
||||||
).let { "$it (${it?.id})" }}\n")
|
|
||||||
append("creation_timestamp: ${
|
|
||||||
SimpleDateFormat.getDateTimeInstance().format(
|
|
||||||
Date(arroyoMessage.creationTimestamp)
|
|
||||||
)} (${arroyoMessage.creationTimestamp})\n")
|
|
||||||
append("read_timestamp: ${SimpleDateFormat.getDateTimeInstance().format(
|
|
||||||
Date(arroyoMessage.readTimestamp)
|
|
||||||
)} (${arroyoMessage.readTimestamp})\n")
|
|
||||||
append("ml_deleted: ${messageLogger.isMessageDeleted(arroyoMessage.clientConversationId!!, arroyoMessage.clientMessageId.toLong())}, ")
|
|
||||||
append("ml_stored: ${messageLogger.getMessageObject(arroyoMessage.clientConversationId!!, arroyoMessage.clientMessageId.toLong()) != null}\n")
|
|
||||||
}
|
|
||||||
}.toString()
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
Text("Info")
|
|
||||||
}
|
|
||||||
Button(onClick = {
|
|
||||||
val arroyoMessage = lastFocusedMessage ?: return@Button
|
|
||||||
messaging.conversationManager?.fetchMessage(arroyoMessage.clientConversationId!!, arroyoMessage.clientMessageId.toLong(), onSuccess = { message ->
|
|
||||||
val decodedAttachments = MessageDecoder.decode(message.messageContent!!)
|
|
||||||
|
|
||||||
debugAlertDialog(
|
|
||||||
viewGroup.context,
|
|
||||||
"Media References",
|
|
||||||
decodedAttachments.mapIndexed { index, attachment ->
|
|
||||||
StringBuilder().apply {
|
|
||||||
append("---- media $index ----\n")
|
|
||||||
append("resolveProto: ${attachment.mediaUrlKey}\n")
|
|
||||||
append("type: ${attachment.type}\n")
|
|
||||||
attachment.attachmentInfo?.apply {
|
|
||||||
encryption?.let {
|
|
||||||
append("encryption:\n - key: ${it.key}\n - iv: ${it.iv}\n")
|
|
||||||
}
|
|
||||||
resolution?.let {
|
|
||||||
append("resolution: ${it.first}x${it.second}\n")
|
|
||||||
}
|
|
||||||
duration?.let {
|
|
||||||
append("duration: $it\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
runCatching {
|
|
||||||
val mediaHeaders = RemoteMediaResolver.getMediaHeaders(Base64.UrlSafe.decode(attachment.mediaUrlKey ?: return@runCatching))
|
|
||||||
append("content-type: ${mediaHeaders["content-type"]}\n")
|
|
||||||
append("content-length: ${Formatter.formatShortFileSize(context.androidContext, mediaHeaders["content-length"]?.toLongOrNull() ?: 0)}\n")
|
|
||||||
append("creation-date: ${mediaHeaders["last-modified"]}\n")
|
|
||||||
}
|
|
||||||
}.toString()
|
|
||||||
}.joinToString("\n\n")
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}) {
|
|
||||||
Text("Refs")
|
|
||||||
}
|
|
||||||
Button(onClick = {
|
|
||||||
val message = lastFocusedMessage ?: return@Button
|
|
||||||
debugAlertDialog(
|
|
||||||
viewGroup.context,
|
|
||||||
"Arroyo proto",
|
|
||||||
message.messageContent?.let { ProtoReader(it) }?.toString() ?: "empty"
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
Text("Arroyo proto")
|
|
||||||
}
|
|
||||||
Button(onClick = {
|
|
||||||
val arroyoMessage = lastFocusedMessage ?: return@Button
|
|
||||||
messaging.conversationManager?.fetchMessage(arroyoMessage.clientConversationId!!, arroyoMessage.clientMessageId.toLong(), onSuccess = { message ->
|
|
||||||
debugAlertDialog(
|
|
||||||
viewGroup.context,
|
|
||||||
"Message proto",
|
|
||||||
message.messageContent?.content?.let { ProtoReader(it) }?.toString() ?: "empty"
|
|
||||||
)
|
|
||||||
}, onError = {
|
|
||||||
this@ChatActionMenu.context.shortToast("Failed to fetch message: $it")
|
|
||||||
})
|
|
||||||
}) {
|
|
||||||
Text("Message proto")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
viewGroup.addView(createContainer(viewGroup).apply {
|
|
||||||
addView(composeDebugView)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
viewGroup.addView(buttonContainer)
|
viewGroup.addView(buttonContainer)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package me.rhunk.snapenhance.core.ui.menu.impl
|
package me.rhunk.snapenhance.core.ui.menu.impl
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.text.format.Formatter
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.ScrollView
|
import android.widget.ScrollView
|
||||||
@ -12,6 +14,8 @@ import androidx.compose.material.icons.filled.Download
|
|||||||
import androidx.compose.material.icons.filled.RemoveRedEye
|
import androidx.compose.material.icons.filled.RemoveRedEye
|
||||||
import androidx.compose.material.icons.outlined.Image
|
import androidx.compose.material.icons.outlined.Image
|
||||||
import androidx.compose.material.icons.rounded.BookmarkRemove
|
import androidx.compose.material.icons.rounded.BookmarkRemove
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@ -21,21 +25,160 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import me.rhunk.snapenhance.common.data.ContentType
|
||||||
import me.rhunk.snapenhance.common.ui.createComposeView
|
import me.rhunk.snapenhance.common.ui.createComposeView
|
||||||
|
import me.rhunk.snapenhance.common.util.ktx.copyToClipboard
|
||||||
|
import me.rhunk.snapenhance.common.util.protobuf.ProtoReader
|
||||||
|
import me.rhunk.snapenhance.common.util.snap.RemoteMediaResolver
|
||||||
import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent
|
import me.rhunk.snapenhance.core.event.events.impl.AddViewEvent
|
||||||
import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader
|
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.experiments.ConvertMessageLocally
|
import me.rhunk.snapenhance.core.features.impl.experiments.ConvertMessageLocally
|
||||||
import me.rhunk.snapenhance.core.features.impl.messaging.Messaging
|
import me.rhunk.snapenhance.core.features.impl.messaging.Messaging
|
||||||
import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger
|
import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger
|
||||||
|
import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper
|
||||||
|
import me.rhunk.snapenhance.core.ui.debugEditText
|
||||||
import me.rhunk.snapenhance.core.ui.iterateParent
|
import me.rhunk.snapenhance.core.ui.iterateParent
|
||||||
import me.rhunk.snapenhance.core.ui.menu.AbstractMenu
|
import me.rhunk.snapenhance.core.ui.menu.AbstractMenu
|
||||||
import me.rhunk.snapenhance.core.ui.triggerCloseTouchEvent
|
import me.rhunk.snapenhance.core.ui.triggerCloseTouchEvent
|
||||||
import me.rhunk.snapenhance.core.util.ktx.isDarkTheme
|
import me.rhunk.snapenhance.core.util.ktx.isDarkTheme
|
||||||
import me.rhunk.snapenhance.core.util.ktx.setObjectField
|
import me.rhunk.snapenhance.core.util.ktx.setObjectField
|
||||||
import me.rhunk.snapenhance.core.util.ktx.vibrateLongPress
|
import me.rhunk.snapenhance.core.util.ktx.vibrateLongPress
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import kotlin.io.encoding.Base64
|
||||||
|
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||||
|
|
||||||
class NewChatActionMenu : AbstractMenu() {
|
class NewChatActionMenu : AbstractMenu() {
|
||||||
|
private fun debugAlertDialog(context: Context, title: String, text: String) {
|
||||||
|
this@NewChatActionMenu.context.runOnUiThread {
|
||||||
|
ViewAppearanceHelper.newAlertDialogBuilder(context).apply {
|
||||||
|
setTitle(title)
|
||||||
|
setView(debugEditText(context, text))
|
||||||
|
setPositiveButton("OK") { dialog, _ -> dialog.dismiss() }
|
||||||
|
setNegativeButton("Copy") { _, _ ->
|
||||||
|
context.copyToClipboard(text, title)
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val lastFocusedMessage
|
||||||
|
get() = context.database.getConversationMessageFromId(context.feature(Messaging::class).lastFocusedMessageId)
|
||||||
|
|
||||||
|
@OptIn(ExperimentalLayoutApi::class, ExperimentalEncodingApi::class)
|
||||||
|
fun createDebugInfoView(context: Context): ComposeView {
|
||||||
|
val messageLogger = this@NewChatActionMenu.context.feature(MessageLogger::class)
|
||||||
|
val messaging = this@NewChatActionMenu.context.feature(Messaging::class)
|
||||||
|
|
||||||
|
return createComposeView(context) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 0.dp, bottom = 0.dp)
|
||||||
|
) {
|
||||||
|
FlowRow(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(5.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
|
) {
|
||||||
|
Button(onClick = {
|
||||||
|
val arroyoMessage = lastFocusedMessage ?: return@Button
|
||||||
|
debugAlertDialog(context,
|
||||||
|
"Message Info",
|
||||||
|
StringBuilder().apply {
|
||||||
|
runCatching {
|
||||||
|
append("conversation_id: ${arroyoMessage.clientConversationId}\n")
|
||||||
|
append("sender_id: ${arroyoMessage.senderId}\n")
|
||||||
|
append("client_id: ${arroyoMessage.clientMessageId}, server_id: ${arroyoMessage.serverMessageId}\n")
|
||||||
|
append("content_type: ${ContentType.fromId(arroyoMessage.contentType)} (${arroyoMessage.contentType})\n")
|
||||||
|
append("parsed_content_type: ${
|
||||||
|
ContentType.fromMessageContainer(
|
||||||
|
ProtoReader(arroyoMessage.messageContent!!).followPath(4, 4)
|
||||||
|
).let { "$it (${it?.id})" }}\n")
|
||||||
|
append("creation_timestamp: ${
|
||||||
|
SimpleDateFormat.getDateTimeInstance().format(
|
||||||
|
Date(arroyoMessage.creationTimestamp)
|
||||||
|
)} (${arroyoMessage.creationTimestamp})\n")
|
||||||
|
append("read_timestamp: ${
|
||||||
|
SimpleDateFormat.getDateTimeInstance().format(
|
||||||
|
Date(arroyoMessage.readTimestamp)
|
||||||
|
)} (${arroyoMessage.readTimestamp})\n")
|
||||||
|
append("ml_deleted: ${messageLogger.isMessageDeleted(arroyoMessage.clientConversationId!!, arroyoMessage.clientMessageId.toLong())}, ")
|
||||||
|
append("ml_stored: ${messageLogger.getMessageObject(arroyoMessage.clientConversationId!!, arroyoMessage.clientMessageId.toLong()) != null}\n")
|
||||||
|
}
|
||||||
|
}.toString()
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
Text("Info")
|
||||||
|
}
|
||||||
|
Button(onClick = {
|
||||||
|
val arroyoMessage = lastFocusedMessage ?: return@Button
|
||||||
|
messaging.conversationManager?.fetchMessage(arroyoMessage.clientConversationId!!, arroyoMessage.clientMessageId.toLong(), onSuccess = { message ->
|
||||||
|
val decodedAttachments = MessageDecoder.decode(message.messageContent!!)
|
||||||
|
debugAlertDialog(
|
||||||
|
context,
|
||||||
|
"Media References",
|
||||||
|
decodedAttachments.mapIndexed { index, attachment ->
|
||||||
|
StringBuilder().apply {
|
||||||
|
append("---- media $index ----\n")
|
||||||
|
append("resolveProto: ${attachment.mediaUrlKey}\n")
|
||||||
|
append("type: ${attachment.type}\n")
|
||||||
|
attachment.attachmentInfo?.apply {
|
||||||
|
encryption?.let {
|
||||||
|
append("encryption:\n - key: ${it.key}\n - iv: ${it.iv}\n")
|
||||||
|
}
|
||||||
|
resolution?.let {
|
||||||
|
append("resolution: ${it.first}x${it.second}\n")
|
||||||
|
}
|
||||||
|
duration?.let {
|
||||||
|
append("duration: $it\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runCatching {
|
||||||
|
val mediaHeaders = RemoteMediaResolver.getMediaHeaders(
|
||||||
|
Base64.UrlSafe.decode(attachment.mediaUrlKey ?: return@runCatching))
|
||||||
|
append("content-type: ${mediaHeaders["content-type"]}\n")
|
||||||
|
append("content-length: ${Formatter.formatShortFileSize(context, mediaHeaders["content-length"]?.toLongOrNull() ?: 0)}\n")
|
||||||
|
append("creation-date: ${mediaHeaders["last-modified"]}\n")
|
||||||
|
}
|
||||||
|
}.toString()
|
||||||
|
}.joinToString("\n\n")
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}) {
|
||||||
|
Text("Refs")
|
||||||
|
}
|
||||||
|
Button(onClick = {
|
||||||
|
val message = lastFocusedMessage ?: return@Button
|
||||||
|
debugAlertDialog(
|
||||||
|
context,
|
||||||
|
"Arroyo proto",
|
||||||
|
message.messageContent?.let { ProtoReader(it) }?.toString() ?: "empty"
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
Text("Arroyo")
|
||||||
|
}
|
||||||
|
Button(onClick = {
|
||||||
|
val arroyoMessage = lastFocusedMessage ?: return@Button
|
||||||
|
messaging.conversationManager?.fetchMessage(arroyoMessage.clientConversationId!!, arroyoMessage.clientMessageId.toLong(), onSuccess = { message ->
|
||||||
|
debugAlertDialog(
|
||||||
|
context,
|
||||||
|
"Message proto",
|
||||||
|
message.messageContent?.content?.let { ProtoReader(it) }?.toString() ?: "empty"
|
||||||
|
)
|
||||||
|
}, onError = {
|
||||||
|
this@NewChatActionMenu.context.shortToast("Failed to fetch message: $it")
|
||||||
|
})
|
||||||
|
}) {
|
||||||
|
Text("Message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun handle(event: AddViewEvent) {
|
fun handle(event: AddViewEvent) {
|
||||||
if (event.parent is LinearLayout) return
|
if (event.parent is LinearLayout) return
|
||||||
val closeActionMenu = { event.parent.iterateParent {
|
val closeActionMenu = { event.parent.iterateParent {
|
||||||
@ -149,9 +292,10 @@ class NewChatActionMenu : AbstractMenu() {
|
|||||||
addView(composeView)
|
addView(composeView)
|
||||||
composeView.post {
|
composeView.post {
|
||||||
(event.parent.layoutParams as ViewGroup.MarginLayoutParams).apply {
|
(event.parent.layoutParams as ViewGroup.MarginLayoutParams).apply {
|
||||||
setObjectField("a", null) // remove drag callback
|
|
||||||
if (height < composeView.measuredHeight) {
|
if (height < composeView.measuredHeight) {
|
||||||
height += composeView.measuredHeight
|
height += composeView.measuredHeight
|
||||||
|
} else {
|
||||||
|
setObjectField("a", null) // remove drag callback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
event.parent.requestLayout()
|
event.parent.requestLayout()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user