commit 4a7c7d71bc6a7b66396899625661ac86c0543ee0
parent 4b49d669b7ec8ee0599f621b64b3e8ad674a5dfe
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date: Sun, 15 Oct 2023 19:53:48 +0200
feat: hide from friend feed
Diffstat:
5 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/common/src/main/assets/lang/en_US.json b/common/src/main/assets/lang/en_US.json
@@ -97,8 +97,8 @@
"whitelist": "Auto save"
}
},
- "hide_chat_feed": {
- "name": "Hide from Chat feed"
+ "hide_friend_feed": {
+ "name": "Hide from Friend Feed"
},
"e2e_encryption": {
"name": "Use E2E Encryption"
@@ -254,6 +254,10 @@
"name": "Show Streak Expiration Info",
"description": "Shows a Streak Expiration timer next to the Streaks counter"
},
+ "hide_friend_feed_entry": {
+ "name": "Hide Friend Feed Entry",
+ "description": "Hides a specific friend from the Friend Feed\nUse the social tab to manage this feature"
+ },
"hide_streak_restore": {
"name": "Hide Streak Restore",
"description": "Hides the Restore button in the friend feed"
diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/UserInterfaceTweaks.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/UserInterfaceTweaks.kt
@@ -29,6 +29,7 @@ class UserInterfaceTweaks : ConfigContainer() {
val bootstrapOverride = container("bootstrap_override", BootstrapOverride()) { requireRestart() }
val mapFriendNameTags = boolean("map_friend_nametags") { requireRestart() }
val streakExpirationInfo = boolean("streak_expiration_info") { requireRestart() }
+ val hideFriendFeedEntry = boolean("hide_friend_feed_entry") { requireRestart() }
val hideStreakRestore = boolean("hide_streak_restore") { requireRestart() }
val hideStorySections = multiple("hide_story_sections",
"hide_friend_suggestions", "hide_friends", "hide_suggested", "hide_for_you") { requireRestart() }
diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/data/MessagingCoreObjects.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/data/MessagingCoreObjects.kt
@@ -34,7 +34,7 @@ enum class MessagingRuleType(
AUTO_DOWNLOAD("auto_download", true),
STEALTH("stealth", true),
AUTO_SAVE("auto_save", true),
- HIDE_CHAT_FEED("hide_chat_feed", false, showInFriendMenu = false),
+ HIDE_FRIEND_FEED("hide_friend_feed", false, showInFriendMenu = false),
E2E_ENCRYPTION("e2e_encryption", false),
PIN_CONVERSATION("pin_conversation", false, showInFriendMenu = false);
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/HideFriendFeedEntry.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/ui/HideFriendFeedEntry.kt
@@ -0,0 +1,71 @@
+package me.rhunk.snapenhance.core.features.impl.ui
+
+import me.rhunk.snapenhance.common.data.MessagingRuleType
+import me.rhunk.snapenhance.common.data.RuleState
+import me.rhunk.snapenhance.core.features.FeatureLoadParams
+import me.rhunk.snapenhance.core.features.MessagingRuleFeature
+import me.rhunk.snapenhance.core.util.hook.HookStage
+import me.rhunk.snapenhance.core.util.hook.hook
+import me.rhunk.snapenhance.core.util.ktx.getObjectField
+import me.rhunk.snapenhance.core.util.ktx.setObjectField
+import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID
+
+class HideFriendFeedEntry : MessagingRuleFeature("HideFriendFeedEntry", ruleType = MessagingRuleType.HIDE_FRIEND_FEED, loadParams = FeatureLoadParams.INIT_SYNC) {
+ private fun createDeletedFeedEntry(conversationId: String) = context.gson.fromJson(
+ """
+ {
+ "mFeedEntryIdentifier": {
+ "mConversationId": null
+ },
+ "mReason": "CLEAR_CONVERSATION"
+ }
+ """.trimIndent(),
+ findClass("com.snapchat.client.messaging.DeletedFeedEntry")
+ ).also {
+ it.getObjectField("mFeedEntryIdentifier")?.setObjectField("mConversationId", SnapUUID.fromString(conversationId).instanceNonNull())
+ }
+
+ private fun filterFriendFeed(entries: ArrayList<Any>, deletedEntries: ArrayList<Any>? = null) {
+ entries.removeIf { feedEntry ->
+ val conversationId = SnapUUID(feedEntry.getObjectField("mConversationId")).toString()
+
+ if (canUseRule(conversationId)) {
+ deletedEntries?.add(createDeletedFeedEntry(conversationId))
+ true
+ } else {
+ false
+ }
+ }
+ }
+
+ override fun init() {
+ if (!context.config.userInterface.hideFriendFeedEntry.get()) return
+
+ arrayOf(
+ "QueryFeedCallback" to "onQueryFeedComplete",
+ "FeedManagerDelegate" to "onFeedEntriesUpdated",
+ "FeedManagerDelegate" to "onInternalSyncFeed",
+ "SyncFeedCallback" to "onSyncFeedComplete",
+ ).forEach { (callbackName, methodName) ->
+ context.mappings.getMappedClass("callbacks", callbackName)
+ .hook(methodName, HookStage.BEFORE) { param ->
+ filterFriendFeed(param.arg(0))
+ }
+ }
+
+ context.mappings.getMappedClass("callbacks", "FetchAndSyncFeedCallback")
+ .hook("onFetchAndSyncFeedComplete", HookStage.BEFORE) { param ->
+ val deletedConversations: ArrayList<Any> = param.arg(2)
+ filterFriendFeed(param.arg(0), deletedConversations)
+
+ if (deletedConversations.any {
+ val uuid = SnapUUID(it.getObjectField("mFeedEntryIdentifier")?.getObjectField("mConversationId")).toString()
+ context.database.getFeedEntryByConversationId(uuid) != null
+ }) {
+ param.setArg(4, true)
+ }
+ }
+ }
+
+ override fun getRuleState() = RuleState.WHITELIST
+}+
\ No newline at end of file
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/manager/impl/FeatureManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/manager/impl/FeatureManager.kt
@@ -99,6 +99,7 @@ class FeatureManager(
SnapToChatMedia::class,
FriendFeedMessagePreview::class,
HideStreakRestore::class,
+ HideFriendFeedEntry::class,
)
initializeFeatures()