commit e0f6d05676cb54a59fb5319c7d16be9a304b3d65
parent 72b03085060d58d028a2e90972db72b84559587a
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sun,  8 Oct 2023 21:03:39 +0200

feat: better ff message preview

Diffstat:
Mcore/src/main/assets/lang/en_US.json | 12+++++++++---
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/UserInterfaceTweaks.kt | 8++++++--
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/FriendFeedMessagePreview.kt | 84+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
3 files changed, 69 insertions(+), 35 deletions(-)

diff --git a/core/src/main/assets/lang/en_US.json b/core/src/main/assets/lang/en_US.json @@ -220,9 +220,15 @@ "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" + "friend_feed_message_preview": { + "name": "Friend Feed Message Preview", + "description": "Shows a preview of the last messages in the Friend Feed", + "properties": { + "amount": { + "name": "Amount", + "description": "The amount of messages to get previewed" + } + } }, "bootstrap_override": { "name": "Bootstrap Override", 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 @@ -11,14 +11,18 @@ class UserInterfaceTweaks : ConfigContainer() { val homeTab = unique("home_tab", *ClientBootstrapOverride.tabs) { addNotices(FeatureNotice.UNSTABLE) } } + inner class FriendFeedMessagePreview : ConfigContainer(hasGlobalState = true) { + val amount = integer("amount", defaultValue = 1) + } + val friendFeedMenuButtons = multiple( - "friend_feed_menu_buttons","conversation_info", *MessagingRuleType.values().toList().filter { it.showInFriendMenu }.map { it.key }.toTypedArray() + "friend_feed_menu_buttons","conversation_info", *MessagingRuleType.entries.filter { it.showInFriendMenu }.map { it.key }.toTypedArray() ).apply { set(mutableListOf("conversation_info", MessagingRuleType.STEALTH.key)) } 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 friendFeedMessagePreview = container("friend_feed_message_preview", FriendFeedMessagePreview()) { 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/features/impl/ui/FriendFeedMessagePreview.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/FriendFeedMessagePreview.kt @@ -3,11 +3,12 @@ package me.rhunk.snapenhance.features.impl.ui import android.annotation.SuppressLint import android.graphics.Canvas import android.graphics.Paint +import android.graphics.Rect import android.graphics.drawable.ShapeDrawable import android.graphics.drawable.shapes.Shape +import android.text.TextPaint 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 @@ -16,64 +17,87 @@ import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.ui.addForegroundDrawable import me.rhunk.snapenhance.ui.removeForegroundDrawable +import kotlin.math.absoluteValue +@SuppressLint("DiscouragedApi") class FriendFeedMessagePreview : Feature("FriendFeedMessagePreview", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC) { - @SuppressLint("SetTextI18n", "DiscouragedApi") + private val sigColorTextPrimary by lazy { + context.mainActivity!!.theme.obtainStyledAttributes( + intArrayOf(context.resources.getIdentifier("sigColorTextPrimary", "attr", Constants.SNAPCHAT_PACKAGE_NAME)) + ).getColor(0, 0) + } + + private fun getDimens(name: String) = context.resources.getDimensionPixelSize(context.resources.getIdentifier(name, "dimen", Constants.SNAPCHAT_PACKAGE_NAME)) + override fun onActivityCreate() { - if (!context.config.userInterface.conversationPreviewInFriendFeed.get()) return + val setting = context.config.userInterface.friendFeedMessagePreview + if (setting.globalState != true) 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 secondaryTextSize = getDimens("ff_feed_cell_secondary_text_size").toFloat() + val ffSdlAvatarMargin = getDimens("ff_sdl_avatar_margin") + val ffSdlAvatarSize = getDimens("ff_sdl_avatar_size") + val ffSdlAvatarStartMargin = getDimens("ff_sdl_avatar_start_margin") + val ffSdlPrimaryTextStartMargin = getDimens("ff_sdl_primary_text_start_margin").toFloat() - 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)) + val feedEntryHeight = ffSdlAvatarSize + ffSdlAvatarMargin * 2 + ffSdlAvatarStartMargin + val separatorHeight = (context.resources.displayMetrics.density * 2).toInt() + val textPaint = TextPaint().apply { + textSize = secondaryTextSize + } context.event.subscribe(BindViewEvent::class) { param -> param.friendFeedItem { conversationId -> - val frameLayout = param.view as FrameLayout + val frameLayout = param.view as ViewGroup 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 + val stringMessages = context.database.getMessagesFromConversationId(conversationId, setting.amount.get().absoluteValue)?.mapNotNull { message -> + val messageContainer = message.messageContent ?.let { ProtoReader(it) } ?.followPath(4, 4) - ?.let { messageContainer -> - messageContainer.getString(2, 1) ?: ContentType.fromMessageContainer(messageContainer)?.name ?: return@mapNotNull null - } - } ?: return@friendFeedItem + ?: return@mapNotNull null + + val messageString = messageContainer.getString(2, 1) + ?: ContentType.fromMessageContainer(messageContainer)?.name + ?: return@mapNotNull null + + val friendName = context.database.getFriendInfo(message.senderId ?: return@mapNotNull null)?.let { it.displayName?: it.mutableUsername } ?: "Unknown" + + "$friendName: $messageString" + }?.reversed() ?: return@friendFeedItem + + var maxTextHeight = 0 + val previewContainerHeight = stringMessages.sumOf { msg -> + val rect = Rect() + textPaint.getTextBounds(msg, 0, msg.length, rect) + rect.height().also { + if (it > maxTextHeight) maxTextHeight = it + }.plus(separatorHeight) + } + + ffItem.layoutParams = ffItem.layoutParams.apply { + height = feedEntryHeight + previewContainerHeight + separatorHeight + } frameLayout.addForegroundDrawable("ffItem", ShapeDrawable(object: Shape() { override fun draw(canvas: Canvas, paint: Paint) { - val offsetY = canvas.height.toFloat() - (stringMessages.size * 30f) + val offsetY = canvas.height.toFloat() - previewContainerHeight stringMessages.forEachIndexed { index, messageString -> - paint.textSize = 30f + paint.textSize = secondaryTextSize paint.color = sigColorTextPrimary canvas.drawText(messageString, - ffSdlAvatarStartMargin.toFloat() + ffSdlAvatarMargin * 2 + ffSdlAvatarSize + ffSdlPrimaryTextStartMargin, - offsetY + (index * 30f), + feedEntryHeight + ffSdlPrimaryTextStartMargin, + offsetY + index * maxTextHeight, paint ) } - - ffItem.layoutParams = ffItem.layoutParams.apply { - height = ffSdlAvatarSize + ffSdlAvatarMargin * 2 + ffSdlAvatarStartMargin + (stringMessages.size * 30) - } } })) }