commit 7c5195e83cc981197fe5f0c59cd74c4a636d8022
parent 5776d4411103691e0f09a2e902cb6e0591a8ccb5
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date: Fri, 1 Sep 2023 12:30:15 +0200
feat(notifications): groups
Diffstat:
4 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/core/src/main/assets/lang/en_US.json b/core/src/main/assets/lang/en_US.json
@@ -203,6 +203,14 @@
"name": "Prevent Message Sending",
"description": "Prevents sending certain types of messages"
},
+ "better_notifications": {
+ "name": "Better Notifications",
+ "description": "Adds more information in received notifications"
+ },
+ "notification_blacklist": {
+ "name": "Notification Blacklist",
+ "description": "Select the notifications to be blocked"
+ },
"message_logger": {
"name": "Message Logger",
"description": "Keeps messages when someone deletes them. This only works for messages deleted after enabling this feature"
@@ -253,14 +261,6 @@
"name": "Force Media Source Quality",
"description": "Overrides the media quality to the highest possible"
},
- "better_notifications": {
- "name": "Better Notifications",
- "description": "Adds more information in received notifications"
- },
- "notification_blacklist": {
- "name": "Notification Blacklist",
- "description": "Select the notifications to be blocked"
- },
"disable_snap_splitting": {
"name": "Disable Snap Splitting",
"description": "Prevents Snaps from being split into multiple parts. It also convert sent images into videos"
@@ -379,7 +379,8 @@
"chat": "Show chat messages",
"snap": "Show medias",
"reply_button": "Add reply button",
- "download_button": "Add download button"
+ "download_button": "Add download button",
+ "group": "Group notifications"
},
"friend_feed_menu_buttons": {
"auto_download_blacklist": "\u2B07\uFE0F Auto Download Blacklist",
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Global.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Global.kt
@@ -12,9 +12,5 @@ class Global : ConfigContainer() {
val disableVideoLengthRestrictions = boolean("disable_video_length_restrictions") { addNotices(FeatureNotice.MAY_BAN) }
val disableGooglePlayDialogs = boolean("disable_google_play_dialogs")
val forceMediaSourceQuality = boolean("force_media_source_quality")
- val betterNotifications = multiple("better_notifications", "snap", "chat", "reply_button", "download_button")
- val notificationBlacklist = multiple("notification_blacklist", *NotificationType.getIncomingValues().map { it.key }.toTypedArray()) {
- customOptionTranslationPath = "features.options.notifications"
- }
val disableSnapSplitting = boolean("disable_snap_splitting") { addNotices(FeatureNotice.MAY_BREAK_INTERNAL_BEHAVIOR) }
}
\ No newline at end of file
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/MessagingTweaks.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/MessagingTweaks.kt
@@ -19,6 +19,10 @@ class MessagingTweaks : ConfigContainer() {
val preventMessageSending = multiple("prevent_message_sending", *NotificationType.getOutgoingValues().map { it.key }.toTypedArray()) {
customOptionTranslationPath = "features.options.notifications"
}
+ val betterNotifications = multiple("better_notifications", "snap", "chat", "reply_button", "download_button", "group")
+ val notificationBlacklist = multiple("notification_blacklist", *NotificationType.getIncomingValues().map { it.key }.toTypedArray()) {
+ customOptionTranslationPath = "features.options.notifications"
+ }
val messageLogger = boolean("message_logger") { addNotices(FeatureNotice.MAY_CAUSE_CRASHES) }
val galleryMediaSendOverride = boolean("gallery_media_send_override")
val messagePreviewLength = integer("message_preview_length", defaultValue = 20)
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt
@@ -27,6 +27,7 @@ import me.rhunk.snapenhance.hook.HookStage
import me.rhunk.snapenhance.hook.Hooker
import me.rhunk.snapenhance.hook.hook
import me.rhunk.snapenhance.util.CallbackBuilder
+import me.rhunk.snapenhance.util.ktx.setObjectField
import me.rhunk.snapenhance.util.protobuf.ProtoReader
import me.rhunk.snapenhance.util.snap.EncryptionHelper
import me.rhunk.snapenhance.util.snap.MediaDownloaderHelper
@@ -37,6 +38,7 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN
companion object{
const val ACTION_REPLY = "me.rhunk.snapenhance.action.notification.REPLY"
const val ACTION_DOWNLOAD = "me.rhunk.snapenhance.action.notification.DOWNLOAD"
+ const val SNAPCHAT_NOTIFICATION_GROUP = "snapchat_notification_group"
}
private val notificationDataQueue = mutableMapOf<Long, NotificationData>() // messageId => notification
@@ -62,7 +64,7 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN
}
private val betterNotificationFilter by lazy {
- context.config.global.betterNotifications.get()
+ context.config.messaging.betterNotifications.get()
}
private fun setNotificationText(notification: Notification, conversationId: String) {
@@ -185,6 +187,25 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN
val sendNotificationData = { notificationData: NotificationData, forceCreate: Boolean ->
val notificationId = if (forceCreate) System.nanoTime().toInt() else notificationData.id
notificationIdMap.computeIfAbsent(notificationId) { conversationId }
+ if (betterNotificationFilter.contains("group")) {
+ runCatching {
+ notificationData.notification.setObjectField("mGroupKey", SNAPCHAT_NOTIFICATION_GROUP)
+
+ val summaryNotification = Notification.Builder(context.androidContext, notificationData.notification.channelId)
+ .setSmallIcon(notificationData.notification.smallIcon)
+ .setGroup(SNAPCHAT_NOTIFICATION_GROUP)
+ .setGroupSummary(true)
+ .setAutoCancel(true)
+ .setOnlyAlertOnce(true)
+ .build()
+
+ if (notificationManager.activeNotifications.firstOrNull { it.notification.flags and Notification.FLAG_GROUP_SUMMARY != 0 } == null) {
+ notificationManager.notify(notificationData.tag, notificationData.id, summaryNotification)
+ }
+ }.onFailure {
+ context.log.warn("Failed to set notification group key: ${it.stackTraceToString()}", featureKey)
+ }
+ }
XposedBridge.invokeOriginalMethod(notifyAsUserMethod, notificationManager, arrayOf(
notificationData.tag, if (forceCreate) System.nanoTime().toInt() else notificationData.id, notificationData.notification, notificationData.userHandle
@@ -317,7 +338,7 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN
}
findClass("com.google.firebase.messaging.FirebaseMessagingService").run {
- val states by context.config.global.notificationBlacklist
+ val states by context.config.messaging.notificationBlacklist
methods.first { it.declaringClass == this && it.returnType == Void::class.javaPrimitiveType && it.parameterCount == 1 && it.parameterTypes[0] == Intent::class.java }
.hook(HookStage.BEFORE) { param ->
val intent = param.argNullable<Intent>(0) ?: return@hook