commit 202638841a23b5a2d25d11398c9dd934658ac291
parent c04b99434a7389d28128d66d5fb51c8345eb8c41
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Fri,  1 Dec 2023 18:50:11 +0100

feat(core/notifications): save in chat when marking as read

Diffstat:
Mcommon/src/main/assets/lang/en_US.json | 1+
Mcommon/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/MessagingTweaks.kt | 2+-
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/AutoSave.kt | 20++++++++++----------
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt | 26++++++++++++++++++++++++++
4 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/common/src/main/assets/lang/en_US.json b/common/src/main/assets/lang/en_US.json @@ -671,6 +671,7 @@ "reply_button": "Add reply button", "download_button": "Add download button", "mark_as_read_button": "Mark as Read button", + "mark_as_read_and_save_in_chat": "Save in Chat when marking as read (depends on Auto Save)", "group": "Group notifications" }, "friend_feed_menu_buttons": { diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/MessagingTweaks.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/config/impl/MessagingTweaks.kt @@ -28,7 +28,7 @@ class MessagingTweaks : ConfigContainer() { nativeHooks() } val instantDelete = boolean("instant_delete") { requireRestart() } - val betterNotifications = multiple("better_notifications", "chat_preview", "media_preview", "reply_button", "download_button", "mark_as_read_button", "group") { requireRestart() } + val betterNotifications = multiple("better_notifications", "chat_preview", "media_preview", "reply_button", "download_button", "mark_as_read_button", "mark_as_read_and_save_in_chat", "group") { requireRestart() } val notificationBlacklist = multiple("notification_blacklist", *NotificationType.getIncomingValues().map { it.key }.toTypedArray()) { customOptionTranslationPath = "features.options.notifications" } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/AutoSave.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/AutoSave.kt @@ -15,7 +15,7 @@ import me.rhunk.snapenhance.core.wrapper.impl.Message import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID import java.util.concurrent.Executors -class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE, loadParams = FeatureLoadParams.ACTIVITY_CREATE_ASYNC) { +class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE, loadParams = FeatureLoadParams.INIT_SYNC) { private val asyncSaveExecutorService = Executors.newSingleThreadExecutor() private val messageLogger by lazy { context.feature(MessageLogger::class) } @@ -25,7 +25,7 @@ class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE, context.config.messaging.autoSaveMessagesInConversations.get() } - private fun saveMessage(conversationId: SnapUUID, message: Message) { + fun saveMessage(conversationId: SnapUUID, message: Message) { val messageId = message.messageDescriptor!!.messageId!! if (messageLogger.takeIf { it.isEnabled }?.isMessageDeleted(conversationId.toString(), messageId) == true) return if (message.messageState != MessageState.COMMITTED) return @@ -48,22 +48,22 @@ class AutoSave : MessagingRuleFeature("Auto Save", MessagingRuleType.AUTO_SAVE, Thread.sleep(100L) } - private fun canSaveMessage(message: Message): Boolean { - if (context.mainActivity == null || context.isMainActivityPaused) return false + fun canSaveMessage(message: Message, headless: Boolean = false): Boolean { + if (!headless && (context.mainActivity == null || context.isMainActivityPaused)) return false if (message.messageMetadata!!.savedBy!!.any { uuid -> uuid.toString() == context.database.myUserId }) return false val contentType = message.messageContent!!.contentType.toString() return autoSaveFilter.any { it == contentType } } - private fun canSaveInConversation(targetConversationId: String): Boolean { + fun canSaveInConversation(targetConversationId: String, headless: Boolean = false): Boolean { val messaging = context.feature(Messaging::class) - val openedConversationId = messaging.openedConversationUUID?.toString() ?: return false - - if (openedConversationId != targetConversationId) return false + if (!headless) { + if (messaging.openedConversationUUID?.toString() != targetConversationId) return false + } - if (context.feature(StealthMode::class).canUseRule(openedConversationId)) return false - if (!canUseRule(openedConversationId)) return false + if (context.feature(StealthMode::class).canUseRule(targetConversationId)) return false + if (!canUseRule(targetConversationId)) return false return true } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/messaging/Notifications.kt @@ -37,6 +37,7 @@ import me.rhunk.snapenhance.core.util.ktx.setObjectField import me.rhunk.snapenhance.core.util.media.PreviewUtils import me.rhunk.snapenhance.core.wrapper.impl.Message import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID +import me.rhunk.snapenhance.core.wrapper.impl.toSnapUUID import kotlin.coroutines.suspendCoroutine class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.INIT_SYNC) { @@ -231,6 +232,31 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN } ) + if (betterNotificationFilter.contains("mark_as_read_and_save_in_chat")) { + val messaging = context.feature(Messaging::class) + val autoSave = context.feature(AutoSave::class) + + if (autoSave.canSaveInConversation(conversationId, headless = true)) { + messaging.conversationManager?.fetchConversationWithMessagesPaginated( + conversationId, + Long.MAX_VALUE, + 20, + onSuccess = { messages -> + messages.reversed().forEach { message -> + if (!autoSave.canSaveMessage(message, headless = true)) return@forEach + context.coroutineScope.launch(coroutineDispatcher) { + autoSave.saveMessage(conversationId.toSnapUUID(), message) + } + } + }, + onError = { + context.log.error("Failed to fetch conversation: $it") + context.shortToast("Failed to fetch conversation") + } + ) + } + } + val conversationMessage = context.database.getConversationMessageFromId(clientMessageId) ?: return@subscribe if (conversationMessage.contentType == ContentType.SNAP.id) {