feat: preview conversations in friend feed

This commit is contained in:
rhunk 2023-10-07 19:18:23 +02:00
parent c29a5b7761
commit 3fbe5ef121
5 changed files with 97 additions and 8 deletions

View File

@ -220,6 +220,10 @@
"name": "AMOLED Dark Mode",
"description": "Enables AMOLED dark mode\nMake sure Snapchats Dark mode is enabled"
},
"conversation_preview_in_friend_feed": {
"name": "Preview in FF",
"description": "Shows a preview of the last messages in the Friend Feed"
},
"bootstrap_override": {
"name": "Bootstrap Override",
"description": "Overrides user interface bootstrap settings",

View File

@ -18,6 +18,7 @@ class UserInterfaceTweaks : ConfigContainer() {
}
val friendFeedMenuPosition = integer("friend_feed_menu_position", defaultValue = 1)
val amoledDarkMode = boolean("amoled_dark_mode") { addNotices(FeatureNotice.UNSTABLE); requireRestart() }
val conversationPreviewInFriendFeed = boolean("conversation_preview_in_friend_feed") { requireRestart() }
val bootstrapOverride = container("bootstrap_override", BootstrapOverride()) { requireRestart() }
val mapFriendNameTags = boolean("map_friend_nametags") { requireRestart() }
val streakExpirationInfo = boolean("streak_expiration_info") { requireRestart() }

View File

@ -8,19 +8,19 @@ class BindViewEvent(
val nextModel: Any?,
val view: View
): Event() {
fun chatMessage(block: (conversationId: String, messageId: String) -> Unit) {
val prevModelToString = prevModel.toString()
if (!prevModelToString.startsWith("ChatViewModel")) return
prevModelToString.substringAfter("messageId=").substringBefore(",").split(":").apply {
inline fun chatMessage(block: (conversationId: String, messageId: String) -> Unit) {
val modelToString = prevModel.toString()
if (!modelToString.startsWith("ChatViewModel")) return
modelToString.substringAfter("messageId=").substringBefore(",").split(":").apply {
if (size != 3) return
block(this[0], this[2])
}
}
fun friendFeedItem(block: (conversationId: String) -> Unit) {
val prevModelToString = nextModel.toString()
if (!prevModelToString.startsWith("FriendFeedItemViewModel")) return
val conversationId = prevModelToString.substringAfter("conversationId: ").substringBefore("\n")
inline fun friendFeedItem(block: (conversationId: String) -> Unit) {
val modelToString = prevModel.toString()
if (!modelToString.startsWith("FriendFeedItemViewModel")) return
val conversationId = modelToString.substringAfter("conversationId: ").substringBefore("\n")
block(conversationId)
}
}

View File

@ -0,0 +1,82 @@
package me.rhunk.snapenhance.features.impl.ui
import android.annotation.SuppressLint
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.Shape
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import me.rhunk.snapenhance.Constants
import me.rhunk.snapenhance.core.event.events.impl.BindViewEvent
import me.rhunk.snapenhance.core.util.protobuf.ProtoReader
import me.rhunk.snapenhance.data.ContentType
import me.rhunk.snapenhance.features.Feature
import me.rhunk.snapenhance.features.FeatureLoadParams
import me.rhunk.snapenhance.ui.addForegroundDrawable
import me.rhunk.snapenhance.ui.removeForegroundDrawable
class FriendFeedMessagePreview : Feature("FriendFeedMessagePreview", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC) {
@SuppressLint("SetTextI18n", "DiscouragedApi")
override fun onActivityCreate() {
if (!context.config.userInterface.conversationPreviewInFriendFeed.get()) return
val ffItemId = context.resources.getIdentifier("ff_item", "id", Constants.SNAPCHAT_PACKAGE_NAME)
val sigColorTextPrimary by lazy {
context.mainActivity!!.theme.obtainStyledAttributes(
intArrayOf(context.resources.getIdentifier("sigColorTextPrimary", "attr", Constants.SNAPCHAT_PACKAGE_NAME))
).getColor(0, 0)
}
val ffSdlAvatarMargin = context.resources.getDimensionPixelSize(context.resources.getIdentifier("ff_sdl_avatar_margin", "dimen", Constants.SNAPCHAT_PACKAGE_NAME))
val ffSdlAvatarSize = context.resources.getDimensionPixelSize(context.resources.getIdentifier("ff_sdl_avatar_size", "dimen", Constants.SNAPCHAT_PACKAGE_NAME))
val ffSdlAvatarStartMargin = context.resources.getDimensionPixelSize(context.resources.getIdentifier("ff_sdl_avatar_start_margin", "dimen", Constants.SNAPCHAT_PACKAGE_NAME))
val ffSdlPrimaryTextStartMargin = context.resources.getDimensionPixelSize(context.resources.getIdentifier("ff_sdl_primary_text_start_margin", "dimen", Constants.SNAPCHAT_PACKAGE_NAME))
context.event.subscribe(BindViewEvent::class) { param ->
param.friendFeedItem { conversationId ->
val frameLayout = param.view as FrameLayout
val ffItem = frameLayout.findViewById<View>(ffItemId)
context.log.verbose("updated $conversationId")
ffItem.layoutParams = ffItem.layoutParams.apply {
height = ViewGroup.LayoutParams.MATCH_PARENT
}
frameLayout.removeForegroundDrawable("ffItem")
val stringMessages = context.database.getMessagesFromConversationId(conversationId, 5)?.mapNotNull { message ->
message.messageContent
?.let { ProtoReader(it) }
?.followPath(4, 4)
?.let { messageContainer ->
messageContainer.getString(2, 1) ?: ContentType.fromMessageContainer(messageContainer)?.name ?: return@mapNotNull null
}
} ?: return@friendFeedItem
frameLayout.addForegroundDrawable("ffItem", ShapeDrawable(object: Shape() {
override fun draw(canvas: Canvas, paint: Paint) {
val offsetY = canvas.height.toFloat() - (stringMessages.size * 30f)
stringMessages.forEachIndexed { index, messageString ->
paint.textSize = 30f
paint.color = sigColorTextPrimary
canvas.drawText(messageString,
ffSdlAvatarStartMargin.toFloat() + ffSdlAvatarMargin * 2 + ffSdlAvatarSize + ffSdlPrimaryTextStartMargin,
offsetY + (index * 30f),
paint
)
}
ffItem.layoutParams = ffItem.layoutParams.apply {
height = ffSdlAvatarSize + ffSdlAvatarMargin * 2 + ffSdlAvatarStartMargin + (stringMessages.size * 30)
}
}
}))
}
}
}
}

View File

@ -23,6 +23,7 @@ import me.rhunk.snapenhance.features.impl.spying.SnapToChatMedia
import me.rhunk.snapenhance.features.impl.spying.StealthMode
import me.rhunk.snapenhance.features.impl.tweaks.*
import me.rhunk.snapenhance.features.impl.ui.ClientBootstrapOverride
import me.rhunk.snapenhance.features.impl.ui.FriendFeedMessagePreview
import me.rhunk.snapenhance.features.impl.ui.PinConversations
import me.rhunk.snapenhance.features.impl.ui.UITweaks
import me.rhunk.snapenhance.manager.Manager
@ -102,6 +103,7 @@ class FeatureManager(
DisableReplayInFF::class,
OldBitmojiSelfie::class,
SnapToChatMedia::class,
FriendFeedMessagePreview::class,
)
initializeFeatures()