From 567a9befd4480b2b2ba578e71d7ce20fdf5eda3a Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Wed, 25 May 2022 10:45:21 +1000 Subject: [PATCH] prevent call info message fires multiple notification --- Session.xcodeproj/project.pbxproj | 4 +++ Session/Meta/AppDelegate.swift | 33 +++++++++++-------- .../Database/Storage+Calls.swift | 16 +++++++++ SessionMessagingKit/Storage.swift | 5 +++ 4 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 SessionMessagingKit/Database/Storage+Calls.swift diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 32cc166db..e63d23d98 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -140,6 +140,7 @@ 7B251C3627D82D9E001A6284 /* SessionUtilitiesKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3C2A679255388CC00C340D1 /* SessionUtilitiesKit.framework */; }; 7B4C75CB26B37E0F0000AC89 /* UnsendRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4C75CA26B37E0F0000AC89 /* UnsendRequest.swift */; }; 7B4C75CD26BB92060000AC89 /* DeletedMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4C75CC26BB92060000AC89 /* DeletedMessageView.swift */; }; + 7B703747283CA919000DCF35 /* Storage+Calls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B703746283CA919000DCF35 /* Storage+Calls.swift */; }; 7B7CB189270430D20079FF93 /* CallMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB188270430D20079FF93 /* CallMessageView.swift */; }; 7B7CB18B270591630079FF93 /* ShareLogsModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB18A270591630079FF93 /* ShareLogsModal.swift */; }; 7B7CB18E270D066F0079FF93 /* IncomingCallBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB18D270D066F0079FF93 /* IncomingCallBanner.swift */; }; @@ -1129,6 +1130,7 @@ 7B2DB2AD26F1B0FF0035B509 /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/Localizable.strings; sourceTree = ""; }; 7B4C75CA26B37E0F0000AC89 /* UnsendRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsendRequest.swift; sourceTree = ""; }; 7B4C75CC26BB92060000AC89 /* DeletedMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedMessageView.swift; sourceTree = ""; }; + 7B703746283CA919000DCF35 /* Storage+Calls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+Calls.swift"; sourceTree = ""; }; 7B7CB188270430D20079FF93 /* CallMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallMessageView.swift; sourceTree = ""; }; 7B7CB18A270591630079FF93 /* ShareLogsModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareLogsModal.swift; sourceTree = ""; }; 7B7CB18D270D066F0079FF93 /* IncomingCallBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncomingCallBanner.swift; sourceTree = ""; }; @@ -2754,6 +2756,7 @@ B8D8F19225661BF80092EF10 /* Storage+Messaging.swift */, B8D8F18825661BA50092EF10 /* Storage+OpenGroups.swift */, C3F0A5FD255C988A007BE2A3 /* Storage+Shared.swift */, + 7B703746283CA919000DCF35 /* Storage+Calls.swift */, C33FDA69255A57F900E217F9 /* SSKPreferences.swift */, C33FDB25255A580900E217F9 /* TSDatabaseSecondaryIndexes.h */, C33FDB20255A580900E217F9 /* TSDatabaseSecondaryIndexes.m */, @@ -4701,6 +4704,7 @@ C300A5D32554B05A00555489 /* TypingIndicator.swift in Sources */, C3A3A156256E1B91004D228D /* ProtoUtils.m in Sources */, C3471ECB2555356A00297E91 /* MessageSender+Encryption.swift in Sources */, + 7B703747283CA919000DCF35 /* Storage+Calls.swift in Sources */, C352A32F2557549C00338F3E /* NotifyPNServerJob.swift in Sources */, 7B4C75CB26B37E0F0000AC89 /* UnsendRequest.swift in Sources */, C300A5F22554B09800555489 /* MessageSender.swift in Sources */, diff --git a/Session/Meta/AppDelegate.swift b/Session/Meta/AppDelegate.swift index 0685f19d1..540d734bd 100644 --- a/Session/Meta/AppDelegate.swift +++ b/Session/Meta/AppDelegate.swift @@ -56,10 +56,15 @@ extension AppDelegate { } } - private func insertCallInfoMessage(for message: CallMessage, using transaction: YapDatabaseReadWriteTransaction) -> TSInfoMessage { + private func insertCallInfoMessage(for message: CallMessage, using transaction: YapDatabaseReadWriteTransaction) -> TSInfoMessage? { + guard let sender = message.sender, let uuid = message.uuid else { return nil } + var receivedCalls = Storage.shared.getReceivedCalls(for: sender, using: transaction) + guard !receivedCalls.contains(uuid) else { return nil } let thread = TSContactThread.getOrCreateThread(withContactSessionID: message.sender!, transaction: transaction) let infoMessage = TSInfoMessage.from(message, associatedWith: thread) infoMessage.save(with: transaction) + receivedCalls.insert(message.uuid!) + Storage.shared.setReceivedCalls(to: receivedCalls, for: sender, using: transaction) return infoMessage } @@ -78,20 +83,22 @@ extension AppDelegate { guard CurrentAppContext().isMainApp else { return } guard let timestamp = message.sentTimestamp, TimestampUtils.isWithinOneMinute(timestamp: timestamp) else { // Add missed call message for call offer messages from more than one minute - let infoMessage = self.insertCallInfoMessage(for: message, using: transaction) - infoMessage.updateCallInfoMessage(.missed, using: transaction) - let thread = TSContactThread.getOrCreateThread(withContactSessionID: message.sender!, transaction: transaction) - SSKEnvironment.shared.notificationsManager?.notifyUser(forIncomingCall: infoMessage, in: thread, transaction: transaction) + if let infoMessage = self.insertCallInfoMessage(for: message, using: transaction) { + infoMessage.updateCallInfoMessage(.missed, using: transaction) + let thread = TSContactThread.getOrCreateThread(withContactSessionID: message.sender!, transaction: transaction) + SSKEnvironment.shared.notificationsManager?.notifyUser(forIncomingCall: infoMessage, in: thread, transaction: transaction) + } return } guard SSKPreferences.areCallsEnabled else { - let infoMessage = self.insertCallInfoMessage(for: message, using: transaction) - infoMessage.updateCallInfoMessage(.permissionDenied, using: transaction) - let thread = TSContactThread.getOrCreateThread(withContactSessionID: message.sender!, transaction: transaction) - SSKEnvironment.shared.notificationsManager?.notifyUser(forIncomingCall: infoMessage, in: thread, transaction: transaction) - let contactName = Storage.shared.getContact(with: message.sender!, using: transaction)?.displayName(for: Contact.Context.regular) ?? message.sender! - DispatchQueue.main.async { - self.showMissedCallTipsIfNeeded(caller: contactName) + if let infoMessage = self.insertCallInfoMessage(for: message, using: transaction) { + infoMessage.updateCallInfoMessage(.permissionDenied, using: transaction) + let thread = TSContactThread.getOrCreateThread(withContactSessionID: message.sender!, transaction: transaction) + SSKEnvironment.shared.notificationsManager?.notifyUser(forIncomingCall: infoMessage, in: thread, transaction: transaction) + let contactName = Storage.shared.getContact(with: message.sender!, using: transaction)?.displayName(for: Contact.Context.regular) ?? message.sender! + DispatchQueue.main.async { + self.showMissedCallTipsIfNeeded(caller: contactName) + } } return } @@ -106,7 +113,7 @@ extension AppDelegate { // Handle UI if let caller = message.sender, let uuid = message.uuid { let call = SessionCall(for: caller, uuid: uuid, mode: .answer) - call.callMessageID = infoMessage.uniqueId + call.callMessageID = infoMessage?.uniqueId self.showCallUIForCall(call) } } diff --git a/SessionMessagingKit/Database/Storage+Calls.swift b/SessionMessagingKit/Database/Storage+Calls.swift new file mode 100644 index 000000000..c1de95a9c --- /dev/null +++ b/SessionMessagingKit/Database/Storage+Calls.swift @@ -0,0 +1,16 @@ + +extension Storage { + + private static let receivedCallsCollection = "LokiReceivedCallsCollection" + + public func getReceivedCalls(for publicKey: String, using transaction: Any) -> Set { + var result: Set? + guard let transaction = transaction as? YapDatabaseReadTransaction else { return [] } + result = transaction.object(forKey: publicKey, inCollection: Storage.receivedCallsCollection) as? Set + return result ?? [] + } + + public func setReceivedCalls(to receivedCalls: Set, for publicKey: String, using transaction: Any) { + (transaction as! YapDatabaseReadWriteTransaction).setObject(receivedCalls, forKey: publicKey, inCollection: Storage.receivedCallsCollection) + } +} diff --git a/SessionMessagingKit/Storage.swift b/SessionMessagingKit/Storage.swift index 43508d40b..aba77646a 100644 --- a/SessionMessagingKit/Storage.swift +++ b/SessionMessagingKit/Storage.swift @@ -96,6 +96,11 @@ public protocol SessionMessagingKitStorageProtocol { func setAttachmentState(to state: TSAttachmentPointerState, for pointer: TSAttachmentPointer, associatedWith tsIncomingMessageID: String, using transaction: Any) /// Also touches the associated message. func persist(_ stream: TSAttachmentStream, associatedWith tsIncomingMessageID: String, using transaction: Any) + + // MARK: - Calls + + func getReceivedCalls(for publicKey: String, using transaction: Any) -> Set + func setReceivedCalls(to receivedCalls: Set, for publicKey: String, using transaction: Any) } extension Storage: SessionMessagingKitStorageProtocol, SessionSnodeKitStorageProtocol {}