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:
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()