feat(notifications): groups

This commit is contained in:
rhunk
2023-09-01 12:30:15 +02:00
parent 5776d44111
commit 7c5195e83c
4 changed files with 37 additions and 15 deletions

View File

@@ -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",

View File

@@ -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) }
}

View File

@@ -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)

View File

@@ -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