commit 3fbe5ef121190e2bd39b849c46cdf6ca91db8dc8
parent c29a5b7761623270a94edb88b9306be09784ad0e
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sat,  7 Oct 2023 19:18:23 +0200

feat: preview conversations in friend feed

Diffstat:
Mcore/src/main/assets/lang/en_US.json | 4++++
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/UserInterfaceTweaks.kt | 1+
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/BindViewEvent.kt | 16++++++++--------
Acore/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/FriendFeedMessagePreview.kt | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcore/src/main/kotlin/me/rhunk/snapenhance/manager/impl/FeatureManager.kt | 2++
5 files changed, 98 insertions(+), 8 deletions(-)

diff --git a/core/src/main/assets/lang/en_US.json b/core/src/main/assets/lang/en_US.json @@ -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", diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/UserInterfaceTweaks.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/UserInterfaceTweaks.kt @@ -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() } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/BindViewEvent.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/event/events/impl/BindViewEvent.kt @@ -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) } } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/FriendFeedMessagePreview.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/FriendFeedMessagePreview.kt @@ -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) + } + } + })) + } + } + } +}+ \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/FeatureManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/FeatureManager.kt @@ -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()