From 02b0d607f7138981878a631b008ee5b0f7500caf Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Tue, 14 Jun 2022 17:10:03 +1000 Subject: [PATCH] WIP: notification --- Session/Notifications/AppNotifications.swift | 36 ++++++++++++++ .../MessageReceiver+Handling.swift | 15 +++--- .../Notifications/NotificationsProtocol.h | 9 +++- .../NSENotificationPresenter.swift | 47 +++++++++---------- .../Utilities/NoopNotificationsManager.swift | 4 ++ 5 files changed, 76 insertions(+), 35 deletions(-) diff --git a/Session/Notifications/AppNotifications.swift b/Session/Notifications/AppNotifications.swift index a39574cce..1b33d1b0b 100644 --- a/Session/Notifications/AppNotifications.swift +++ b/Session/Notifications/AppNotifications.swift @@ -302,6 +302,42 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { ) } } + + public func notifyUser(forReaction reactMessage: ReactMessage, in thread: TSThread, transaction: YapDatabaseReadTransaction) { + guard !thread.isMuted else { return } + guard !thread.isGroupThread() else { return } // We do NOT notify emoji reacts in groups + guard let sender = reactMessage.sender, let emoji = reactMessage.emoji else { return } + guard let threadId = thread.uniqueId else { return } + + let context = Contact.context(for: thread) + let senderName = Storage.shared.getContact(with: sender, using: transaction)?.displayName(for: context) ?? sender + + let notificationTitle = "Sesion" + var notificationBody = "\(senderName) reacts to your message with \(emoji)." + switch previewType { + case .namePreview: break + default: notificationBody = NotificationStrings.incomingMessageBody + } + + let category = AppNotificationCategory.incomingMessage + + let userInfo = [ + AppNotificationUserInfoKey.threadId: threadId + ] + + DispatchQueue.main.async { + let sound = self.requestSound(thread: thread) + + self.adaptee.notify( + category: category, + title: notificationTitle, + body: notificationBody, + userInfo: userInfo, + sound: sound, + replacingIdentifier: UUID().uuidString + ) + } + } public func notifyForFailedSend(inThread thread: TSThread) { let notificationTitle: String? diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift index b0343fc37..5ef9b24c2 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift @@ -377,32 +377,33 @@ extension MessageReceiver { // Get or create thread guard let threadID = storage.getOrCreateThread(for: message.syncTarget ?? message.sender!, groupPublicKey: message.groupPublicKey, openGroupID: openGroupID, using: transaction) else { throw Error.noThread } // Handle emoji reacts first - if let reaction = message.reaction, proto.dataMessage?.reaction != nil, let author = reaction.publicKey, let timestamp = reaction.timestamp { + if let reaction = message.reaction, proto.dataMessage?.reaction != nil, let author = reaction.publicKey, let timestamp = reaction.timestamp, let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) { var tsMessage: TSMessage? if author == getUserHexEncodedPublicKey() { tsMessage = TSOutgoingMessage.find(withTimestamp: timestamp) } else { tsMessage = TSIncomingMessage.find(withAuthorId: author, timestamp: timestamp, transaction: transaction) } - let reactionMessage = ReactMessage(timestamp: timestamp, authorId: author, emoji: reaction.emoji) - reactionMessage.sender = message.sender + let reactMessage = ReactMessage(timestamp: timestamp, authorId: author, emoji: reaction.emoji) + reactMessage.sender = message.sender if let serverID = message.openGroupServerMessageID { - reactionMessage.messageId = "\(serverID)" + reactMessage.messageId = "\(serverID)" // Create a lookup between the openGroupServerMessageId and the tsMessage id for easy lookup // For emoji reacts, the lookup is linking emoji react message server id to the id of the tsMessage that the emoji is reacted to if let openGroup: OpenGroupV2 = storage.getV2OpenGroup(for: threadID) { storage.addOpenGroupServerIdLookup(serverID, tsMessageId: tsMessage?.uniqueId, in: openGroup.room, on: openGroup.server, using: transaction) } } - if let serverHash = message.serverHash { reactionMessage.messageId = serverHash } + if let serverHash = message.serverHash { reactMessage.messageId = serverHash } switch reaction.kind { case .react: - tsMessage?.addReaction(reactionMessage, transaction: transaction) + tsMessage?.addReaction(reactMessage, transaction: transaction) case .remove: - tsMessage?.removeReaction(reactionMessage, transaction: transaction) + tsMessage?.removeReaction(reactMessage, transaction: transaction) case .none: break } + SSKEnvironment.shared.notificationsManager?.notifyUser(forReaction: reactMessage, in: thread, transaction: transaction) return "" } // Parse quote if needed diff --git a/SessionMessagingKit/Sending & Receiving/Notifications/NotificationsProtocol.h b/SessionMessagingKit/Sending & Receiving/Notifications/NotificationsProtocol.h index 576adb737..7ec8970a7 100644 --- a/SessionMessagingKit/Sending & Receiving/Notifications/NotificationsProtocol.h +++ b/SessionMessagingKit/Sending & Receiving/Notifications/NotificationsProtocol.h @@ -6,6 +6,7 @@ NS_ASSUME_NONNULL_BEGIN +@class SNReactMessage; @class TSErrorMessage; @class TSIncomingMessage; @class TSInfoMessage; @@ -22,8 +23,12 @@ NS_ASSUME_NONNULL_BEGIN transaction:(YapDatabaseReadTransaction *)transaction; - (void)notifyUserForIncomingCall:(TSInfoMessage *)callInfoMessage - inThread:(TSThread *)thread - transaction:(YapDatabaseReadTransaction *)transaction; + inThread:(TSThread *)thread + transaction:(YapDatabaseReadTransaction *)transaction; + +- (void)notifyUserForReaction:(SNReactMessage *)reactMessage + inThread:(TSThread *)thread + transaction:(YapDatabaseReadTransaction *)transaction; - (void)cancelNotification:(NSString *)identifier; - (void)clearAllNotifications; diff --git a/SessionNotificationServiceExtension/NSENotificationPresenter.swift b/SessionNotificationServiceExtension/NSENotificationPresenter.swift index c19184a5d..b7b747db1 100644 --- a/SessionNotificationServiceExtension/NSENotificationPresenter.swift +++ b/SessionNotificationServiceExtension/NSENotificationPresenter.swift @@ -110,19 +110,8 @@ public class NSENotificationPresenter: NSObject, NotificationsProtocol { } else { trigger = nil } - - let request = UNNotificationRequest(identifier: identifier, content: notificationContent, trigger: trigger) - SNLog("Add remote notification request: \(notificationContent.body)") - let semaphore = DispatchSemaphore(value: 0) - UNUserNotificationCenter.current().add(request) { error in - if let error = error { - SNLog("Failed to add notification request due to error:\(error)") - } - self.notifications[identifier] = request - semaphore.signal() - } - semaphore.wait() - SNLog("Finish adding remote notification request") + + addNotifcationRequest(identifier: identifier, notificationContent: notificationContent, trigger: trigger) } public func notifyUser(forIncomingCall callInfoMessage: TSInfoMessage, in thread: TSThread, transaction: YapDatabaseReadTransaction) { @@ -149,19 +138,11 @@ public class NSENotificationPresenter: NSObject, NotificationsProtocol { notificationContent.body = String(format: "modal_call_missed_tips_explanation".localized(), thread.name(with: transaction)) } - // Add request - let identifier = UUID().uuidString - let request = UNNotificationRequest(identifier: identifier, content: notificationContent, trigger: nil) - SNLog("Add remote notification request: \(notificationContent.body)") - let semaphore = DispatchSemaphore(value: 0) - UNUserNotificationCenter.current().add(request) { error in - if let error = error { - SNLog("Failed to add notification request due to error:\(error)") - } - semaphore.signal() - } - semaphore.wait() - SNLog("Finish adding remote notification request") + addNotifcationRequest(identifier: UUID().uuidString, notificationContent: notificationContent, trigger: nil) + } + + public func notifyUser(forReaction reactMessage: ReactMessage, in thread: TSThread, transaction: YapDatabaseReadTransaction) { + } public func cancelNotification(_ identifier: String) { @@ -175,6 +156,20 @@ public class NSENotificationPresenter: NSObject, NotificationsProtocol { notificationCenter.removeAllPendingNotificationRequests() notificationCenter.removeAllDeliveredNotifications() } + + private func addNotifcationRequest(identifier: String, notificationContent: UNNotificationContent, trigger: UNNotificationTrigger?) { + let request = UNNotificationRequest(identifier: identifier, content: notificationContent, trigger: nil) + SNLog("Add remote notification request: \(notificationContent.body)") + let semaphore = DispatchSemaphore(value: 0) + UNUserNotificationCenter.current().add(request) { error in + if let error = error { + SNLog("Failed to add notification request due to error:\(error)") + } + semaphore.signal() + } + semaphore.wait() + SNLog("Finish adding remote notification request") + } } private extension String { diff --git a/SignalUtilitiesKit/Utilities/NoopNotificationsManager.swift b/SignalUtilitiesKit/Utilities/NoopNotificationsManager.swift index 86b11b0b9..4dab041f0 100644 --- a/SignalUtilitiesKit/Utilities/NoopNotificationsManager.swift +++ b/SignalUtilitiesKit/Utilities/NoopNotificationsManager.swift @@ -13,6 +13,10 @@ public class NoopNotificationsManager: NSObject, NotificationsProtocol { owsFailDebug("") } + public func notifyUser(forReaction reactMessage: ReactMessage, in thread: TSThread, transaction: YapDatabaseReadTransaction) { + owsFailDebug("") + } + public func cancelNotification(_ identifier: String) { owsFailDebug("") }