From 3cfee137680706dbfd2c20a5625e7323de58e5e1 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Thu, 1 Sep 2022 16:27:21 +1000 Subject: [PATCH 01/15] minor refactor to prevent fake calls --- .../Call Management/SessionCallManager.swift | 58 ++++++++++--------- .../PushRegistrationManager.swift | 10 +++- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/Session/Calls/Call Management/SessionCallManager.swift b/Session/Calls/Call Management/SessionCallManager.swift index 643268bc1..d825ba7fd 100644 --- a/Session/Calls/Call Management/SessionCallManager.swift +++ b/Session/Calls/Call Management/SessionCallManager.swift @@ -73,13 +73,19 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { // MARK: - Report calls public static func reportFakeCall(info: String) { - SessionCallManager.sharedProvider(useSystemCallLog: false) - .reportNewIncomingCall( - with: UUID(), - update: CXCallUpdate() - ) { _ in - SNLog("[Calls] Reported fake incoming call to CallKit due to: \(info)") - } + let callId = UUID() + let provider = SessionCallManager.sharedProvider(useSystemCallLog: false) + provider.reportNewIncomingCall( + with: callId, + update: CXCallUpdate() + ) { _ in + SNLog("[Calls] Reported fake incoming call to CallKit due to: \(info)") + } + provider.reportCall( + with: callId, + endedAt: nil, + reason: .failed + ) } public func reportOutgoingCall(_ call: SessionCall) { @@ -100,28 +106,22 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { public func reportIncomingCall(_ call: SessionCall, callerName: String, completion: @escaping (Error?) -> Void) { AssertIsOnMainThread() - if let provider = provider { - // Construct a CXCallUpdate describing the incoming call, including the caller. - let update = CXCallUpdate() - update.localizedCallerName = callerName - update.remoteHandle = CXHandle(type: .generic, value: call.callId.uuidString) - update.hasVideo = false + let provider = provider ?? Self.sharedProvider(useSystemCallLog: false) + // Construct a CXCallUpdate describing the incoming call, including the caller. + let update = CXCallUpdate() + update.localizedCallerName = callerName + update.remoteHandle = CXHandle(type: .generic, value: call.callId.uuidString) + update.hasVideo = false - disableUnsupportedFeatures(callUpdate: update) + disableUnsupportedFeatures(callUpdate: update) - // Report the incoming call to the system - provider.reportNewIncomingCall(with: call.callId, update: update) { error in - guard error == nil else { - self.reportCurrentCallEnded(reason: .failed) - completion(error) - return - } - UserDefaults.sharedLokiProject?.set(true, forKey: "isCallOngoing") - completion(nil) + // Report the incoming call to the system + provider.reportNewIncomingCall(with: call.callId, update: update) { error in + guard error == nil else { + self.reportCurrentCallEnded(reason: .failed) + completion(error) + return } - } - else { - SessionCallManager.reportFakeCall(info: "No CXProvider instance") UserDefaults.sharedLokiProject?.set(true, forKey: "isCallOngoing") completion(nil) } @@ -135,7 +135,11 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { return } - guard let call = currentCall else { return } + guard let call = currentCall else { + WebRTCSession.current = nil + UserDefaults.sharedLokiProject?.set(false, forKey: "isCallOngoing") + return + } if let reason = reason { self.provider?.reportCall(with: call.callId, endedAt: nil, reason: reason) diff --git a/Session/Notifications/PushRegistrationManager.swift b/Session/Notifications/PushRegistrationManager.swift index 1cd8d71cf..25bb4bb75 100644 --- a/Session/Notifications/PushRegistrationManager.swift +++ b/Session/Notifications/PushRegistrationManager.swift @@ -259,7 +259,13 @@ public enum PushRegistrationError: Error { ) ) - guard let messageInfoData: Data = try? JSONEncoder().encode(messageInfo) else { return nil } + let messageInfoString: String? = { + if let messageInfoData: Data = try? JSONEncoder().encode(messageInfo) { + return String(data: messageInfoData, encoding: .utf8) + } else { + return "Incoming call." // TODO: We can do better here. + } + }() let call: SessionCall = SessionCall(db, for: caller, uuid: uuid, mode: .answer) let thread: SessionThread = try SessionThread.fetchOrCreate(db, id: caller, variant: .contact) @@ -269,7 +275,7 @@ public enum PushRegistrationError: Error { threadId: thread.id, authorId: caller, variant: .infoCall, - body: String(data: messageInfoData, encoding: .utf8), + body: messageInfoString, timestampMs: timestampMs ).inserted(db) call.callInteractionId = interaction.id From afc862d1c1aa8335733f6c172777a121eb8dce36 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Fri, 2 Sep 2022 13:43:16 +1000 Subject: [PATCH 02/15] resume ans suspend database properly in extensions --- .../NotificationServiceExtension.swift | 14 ++++++++++---- SessionShareExtension/ThreadPickerVC.swift | 6 ++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/SessionNotificationServiceExtension/NotificationServiceExtension.swift b/SessionNotificationServiceExtension/NotificationServiceExtension.swift index 5705a4661..7cfeae747 100644 --- a/SessionNotificationServiceExtension/NotificationServiceExtension.swift +++ b/SessionNotificationServiceExtension/NotificationServiceExtension.swift @@ -25,6 +25,9 @@ public final class NotificationServiceExtension: UNNotificationServiceExtension self.contentHandler = contentHandler self.request = request + // Resume database + NotificationCenter.default.post(name: Database.resumeNotification, object: self) + guard let notificationContent = request.content.mutableCopy() as? UNMutableNotificationContent else { return self.completeSilenty() } @@ -237,6 +240,10 @@ public final class NotificationServiceExtension: UNNotificationServiceExtension private func completeSilenty() { SNLog("Complete silenty") + + // Suspend the database + NotificationCenter.default.post(name: Database.suspendNotification, object: self) + self.contentHandler!(.init()) } @@ -298,11 +305,10 @@ public final class NotificationServiceExtension: UNNotificationServiceExtension SNLog("Add remote notification request") } - private func handleSuccess(for content: UNMutableNotificationContent) { - contentHandler!(content) - } - private func handleFailure(for content: UNMutableNotificationContent) { + // Suspend the database + NotificationCenter.default.post(name: Database.suspendNotification, object: self) + content.body = "You've got a new message" content.title = "Session" let userInfo: [String:Any] = [ NotificationServiceExtension.isFromRemoteKey : true ] diff --git a/SessionShareExtension/ThreadPickerVC.swift b/SessionShareExtension/ThreadPickerVC.swift index 4d3352558..f1ea3813d 100644 --- a/SessionShareExtension/ThreadPickerVC.swift +++ b/SessionShareExtension/ThreadPickerVC.swift @@ -220,6 +220,8 @@ final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableView shareVC?.dismiss(animated: true, completion: nil) ModalActivityIndicatorViewController.present(fromViewController: shareVC!, canCancel: false, message: "vc_share_sending_message".localized()) { activityIndicator in + // Resume database + NotificationCenter.default.post(name: Database.resumeNotification, object: self) Storage.shared .writeAsync { [weak self] db -> Promise in guard let thread: SessionThread = try SessionThread.fetchOne(db, id: threadId) else { @@ -271,10 +273,14 @@ final class ThreadPickerVC: UIViewController, UITableViewDataSource, UITableView ) } .done { [weak self] _ in + // Suspend the database + NotificationCenter.default.post(name: Database.suspendNotification, object: self) activityIndicator.dismiss { } self?.shareVC?.shareViewWasCompleted() } .catch { [weak self] error in + // Suspend the database + NotificationCenter.default.post(name: Database.suspendNotification, object: self) activityIndicator.dismiss { } self?.shareVC?.shareViewFailed(error: error) } From 3d0239d31b6bde0e78ddfb677e47399a0dbbef98 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Fri, 2 Sep 2022 14:31:57 +1000 Subject: [PATCH 03/15] fix missed call notification content --- Session/Notifications/AppNotifications.swift | 23 ++++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Session/Notifications/AppNotifications.swift b/Session/Notifications/AppNotifications.swift index e0c25749b..d6d51b294 100644 --- a/Session/Notifications/AppNotifications.swift +++ b/Session/Notifications/AppNotifications.swift @@ -320,14 +320,23 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { closedGroupName: nil, // Not supported openGroupName: nil // Not supported ) - var notificationBody: String? + let notificationBody: String? = { + switch messageInfo.state { + case .permissionDenied: + return String( + format: "modal_call_missed_tips_explanation".localized(), + threadName + ) + case .missed: + return String( + format: "call_missed".localized(), + threadName + ) + default: + return nil + } + }() - if messageInfo.state == .permissionDenied { - notificationBody = String( - format: "modal_call_missed_tips_explanation".localized(), - threadName - ) - } let fallbackSound: Preferences.Sound = db[.defaultNotificationSound] .defaulting(to: Preferences.Sound.defaultNotificationSound) From 87577e9d4b75bf169bb025df0205ab8b82f61aa1 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Fri, 2 Sep 2022 16:37:48 +1000 Subject: [PATCH 04/15] resume database when there is a VoIP call notifcation --- Session/Notifications/PushRegistrationManager.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Session/Notifications/PushRegistrationManager.swift b/Session/Notifications/PushRegistrationManager.swift index 25bb4bb75..c2df1a4f9 100644 --- a/Session/Notifications/PushRegistrationManager.swift +++ b/Session/Notifications/PushRegistrationManager.swift @@ -6,7 +6,7 @@ import Foundation import PromiseKit import PushKit import SignalUtilitiesKit -import SignalUtilitiesKit +import GRDB public enum PushRegistrationError: Error { case assertionError(description: String) @@ -251,6 +251,9 @@ public enum PushRegistrationError: Error { return } + // Resume database + NotificationCenter.default.post(name: Database.resumeNotification, object: self) + let maybeCall: SessionCall? = Storage.shared.write { db in let messageInfo: CallMessage.MessageInfo = CallMessage.MessageInfo( state: (caller == getUserHexEncodedPublicKey(db) ? From a5ede8c6a285640a5ba267aceb9dab3862305cb2 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Fri, 2 Sep 2022 16:59:50 +1000 Subject: [PATCH 05/15] fix a case when the app goes into background with an ongoing call --- Session/Calls/Call Management/SessionCall.swift | 4 ++-- Session/Meta/AppDelegate.swift | 12 ++++++++++-- SessionMessagingKit/Calls/CurrentCallProtocol.swift | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Session/Calls/Call Management/SessionCall.swift b/Session/Calls/Call Management/SessionCall.swift index 1aef15a69..56a6d8140 100644 --- a/Session/Calls/Call Management/SessionCall.swift +++ b/Session/Calls/Call Management/SessionCall.swift @@ -113,12 +113,12 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate { set { connectingDate = newValue ? Date() : nil } } - var hasConnected: Bool { + public var hasConnected: Bool { get { return connectedDate != nil } set { connectedDate = newValue ? Date() : nil } } - var hasEnded: Bool { + public var hasEnded: Bool { get { return endDate != nil } set { endDate = newValue ? Date() : nil } } diff --git a/Session/Meta/AppDelegate.swift b/Session/Meta/AppDelegate.swift index 79db24db8..aeaa99275 100644 --- a/Session/Meta/AppDelegate.swift +++ b/Session/Meta/AppDelegate.swift @@ -132,11 +132,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD // NOTE: Fix an edge case where user taps on the callkit notification // but answers the call on another device - stopPollers(shouldStopUserPoller: !self.hasIncomingCallWaiting()) + stopPollers(shouldStopUserPoller: !self.hasCallOngoing()) // Stop all jobs except for message sending and when completed suspend the database JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend) { - NotificationCenter.default.post(name: Database.suspendNotification, object: self) + if !self.hasCallOngoing() { + NotificationCenter.default.post(name: Database.suspendNotification, object: self) + } } } @@ -634,6 +636,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD return !call.hasStartedConnecting } + func hasCallOngoing() -> Bool { + guard let call = AppEnvironment.shared.callManager.currentCall else { return false } + + return !call.hasEnded + } + func handleAppActivatedWithOngoingCallIfNeeded() { guard let call: SessionCall = (AppEnvironment.shared.callManager.currentCall as? SessionCall), diff --git a/SessionMessagingKit/Calls/CurrentCallProtocol.swift b/SessionMessagingKit/Calls/CurrentCallProtocol.swift index 6968116db..8cdaf7ff7 100644 --- a/SessionMessagingKit/Calls/CurrentCallProtocol.swift +++ b/SessionMessagingKit/Calls/CurrentCallProtocol.swift @@ -9,6 +9,7 @@ public protocol CurrentCallProtocol { var callId: UUID { get } var webRTCSession: WebRTCSession { get } var hasStartedConnecting: Bool { get set } + var hasEnded: Bool { get set } func updateCallMessage(mode: EndCallMode) func didReceiveRemoteSDP(sdp: RTCSessionDescription) From 80894bc198c92f912ef4af015630cb646cde1c9e Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Fri, 2 Sep 2022 17:04:15 +1000 Subject: [PATCH 06/15] suspend database when call is ended in background --- .../Calls/Call Management/SessionCallManager.swift | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Session/Calls/Call Management/SessionCallManager.swift b/Session/Calls/Call Management/SessionCallManager.swift index d825ba7fd..e6ec78ce9 100644 --- a/Session/Calls/Call Management/SessionCallManager.swift +++ b/Session/Calls/Call Management/SessionCallManager.swift @@ -135,9 +135,17 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { return } - guard let call = currentCall else { + func handleCallEnded() { WebRTCSession.current = nil UserDefaults.sharedLokiProject?.set(false, forKey: "isCallOngoing") + if CurrentAppContext().isInBackground() { + // Suspend the database + NotificationCenter.default.post(name: Database.suspendNotification, object: self) + } + } + + guard let call = currentCall else { + handleCallEnded() return } @@ -157,8 +165,7 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { call.webRTCSession.dropConnection() self.currentCall = nil - WebRTCSession.current = nil - UserDefaults.sharedLokiProject?.set(false, forKey: "isCallOngoing") + handleCallEnded() } // MARK: - Util From 31605672e24347428c2a781e05be317c7e4960ac Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 5 Sep 2022 11:27:25 +1000 Subject: [PATCH 07/15] fix call threading issues --- .../Call Management/SessionCallManager.swift | 43 +++++++++---------- .../Notifications/PushNotificationAPI.swift | 2 +- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/Session/Calls/Call Management/SessionCallManager.swift b/Session/Calls/Call Management/SessionCallManager.swift index e6ec78ce9..e7ab88431 100644 --- a/Session/Calls/Call Management/SessionCallManager.swift +++ b/Session/Calls/Call Management/SessionCallManager.swift @@ -104,8 +104,6 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { } public func reportIncomingCall(_ call: SessionCall, callerName: String, completion: @escaping (Error?) -> Void) { - AssertIsOnMainThread() - let provider = provider ?? Self.sharedProvider(useSystemCallLog: false) // Construct a CXCallUpdate describing the incoming call, including the caller. let update = CXCallUpdate() @@ -139,8 +137,10 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { WebRTCSession.current = nil UserDefaults.sharedLokiProject?.set(false, forKey: "isCallOngoing") if CurrentAppContext().isInBackground() { - // Suspend the database - NotificationCenter.default.post(name: Database.suspendNotification, object: self) + // Stop all jobs except for message sending and when completed suspend the database + JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend) { + NotificationCenter.default.post(name: Database.suspendNotification, object: self) + } } } @@ -186,12 +186,6 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { // MARK: - UI public func showCallUIForCall(caller: String, uuid: String, mode: CallMode, interactionId: Int64?) { - guard Thread.isMainThread else { - DispatchQueue.main.async { - self.showCallUIForCall(caller: caller, uuid: uuid, mode: mode, interactionId: interactionId) - } - return - } guard let call: SessionCall = Storage.shared.read({ db in SessionCall(db, for: caller, uuid: uuid, mode: mode) }) else { return } @@ -204,20 +198,23 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { } guard CurrentAppContext().isMainAppAndActive else { return } - guard let presentingVC = CurrentAppContext().frontmostViewController() else { - preconditionFailure() // FIXME: Handle more gracefully - } - if let conversationVC: ConversationVC = presentingVC as? ConversationVC, conversationVC.viewModel.threadData.threadId == call.sessionId { - let callVC = CallVC(for: call) - callVC.conversationVC = conversationVC - conversationVC.inputAccessoryView?.isHidden = true - conversationVC.inputAccessoryView?.alpha = 0 - presentingVC.present(callVC, animated: true, completion: nil) - } - else if !Preferences.isCallKitSupported { - let incomingCallBanner = IncomingCallBanner(for: call) - incomingCallBanner.show() + DispatchQueue.main.async { + guard let presentingVC = CurrentAppContext().frontmostViewController() else { + preconditionFailure() // FIXME: Handle more gracefully + } + + if let conversationVC: ConversationVC = presentingVC as? ConversationVC, conversationVC.viewModel.threadData.threadId == call.sessionId { + let callVC = CallVC(for: call) + callVC.conversationVC = conversationVC + conversationVC.inputAccessoryView?.isHidden = true + conversationVC.inputAccessoryView?.alpha = 0 + presentingVC.present(callVC, animated: true, completion: nil) + } + else if !Preferences.isCallKitSupported { + let incomingCallBanner = IncomingCallBanner(for: call) + incomingCallBanner.show() + } } } } diff --git a/SessionMessagingKit/Sending & Receiving/Notifications/PushNotificationAPI.swift b/SessionMessagingKit/Sending & Receiving/Notifications/PushNotificationAPI.swift index 11499c28f..be56e92bf 100644 --- a/SessionMessagingKit/Sending & Receiving/Notifications/PushNotificationAPI.swift +++ b/SessionMessagingKit/Sending & Receiving/Notifications/PushNotificationAPI.swift @@ -28,7 +28,7 @@ public final class PushNotificationAPI : NSObject { } // MARK: - Settings - public static let server = "https://live.apns.getsession.org" + public static let server = "https://dev.apns.getsession.org" public static let serverPublicKey = "642a6585919742e5a2d4dc51244964fbcd8bcab2b75612407de58b810740d049" private static let maxRetryCount: UInt = 4 From e3479107f3da49991aa1623c0eabbd2f1a8609e9 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 5 Sep 2022 13:31:25 +1000 Subject: [PATCH 08/15] feat: give more time for calls to connect --- Session/Calls/Call Management/SessionCall.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Session/Calls/Call Management/SessionCall.swift b/Session/Calls/Call Management/SessionCall.swift index 56a6d8140..21614e218 100644 --- a/Session/Calls/Call Management/SessionCall.swift +++ b/Session/Calls/Call Management/SessionCall.swift @@ -71,6 +71,7 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate { var connectingDate: Date? { didSet { stateDidChange?() + resetTimeoutTimerIfNeeded() hasStartedConnectingDidChange?() } } @@ -421,6 +422,11 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate { } } + public func resetTimeoutTimerIfNeeded() { + if self.timeOutTimer == nil { return } + setupTimeoutTimer() + } + public func invalidateTimeoutTimer() { timeOutTimer?.invalidate() timeOutTimer = nil From 62d730ea30320e2f1f6bafe762c6ea9ede904209 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 5 Sep 2022 15:44:42 +1000 Subject: [PATCH 09/15] fix call notification title and content --- Session/Notifications/AppNotifications.swift | 15 +++++---------- .../NSENotificationPresenter.swift | 11 ++++------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/Session/Notifications/AppNotifications.swift b/Session/Notifications/AppNotifications.swift index d6d51b294..d2e5a0829 100644 --- a/Session/Notifications/AppNotifications.swift +++ b/Session/Notifications/AppNotifications.swift @@ -313,24 +313,19 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { AppNotificationUserInfoKey.threadId: thread.id ] - let notificationTitle: String = interaction.previewText(db) - let threadName: String = SessionThread.displayName( - threadId: thread.id, - variant: thread.variant, - closedGroupName: nil, // Not supported - openGroupName: nil // Not supported - ) + let notificationTitle: String = "Session" + let senderName: String = Profile.displayName(db, id: interaction.authorId, threadVariant: thread.variant) let notificationBody: String? = { switch messageInfo.state { case .permissionDenied: return String( format: "modal_call_missed_tips_explanation".localized(), - threadName + senderName ) case .missed: return String( format: "call_missed".localized(), - threadName + senderName ) default: return nil @@ -354,7 +349,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { previewType: previewType, sound: sound, threadVariant: thread.variant, - threadName: threadName, + threadName: senderName, replacingIdentifier: UUID().uuidString ) } diff --git a/SessionNotificationServiceExtension/NSENotificationPresenter.swift b/SessionNotificationServiceExtension/NSENotificationPresenter.swift index 62956ff80..686e6109f 100644 --- a/SessionNotificationServiceExtension/NSENotificationPresenter.swift +++ b/SessionNotificationServiceExtension/NSENotificationPresenter.swift @@ -157,18 +157,15 @@ public class NSENotificationPresenter: NSObject, NotificationsProtocol { notificationContent.badge = NSNumber(value: newBadgeNumber) CurrentAppContext().appUserDefaults().set(newBadgeNumber, forKey: "currentBadgeNumber") - notificationContent.title = interaction.previewText(db) + notificationContent.title = "Session" notificationContent.body = "" + let senderName: String = Profile.displayName(db, id: interaction.authorId, threadVariant: thread.variant) + if messageInfo.state == .permissionDenied { notificationContent.body = String( format: "modal_call_missed_tips_explanation".localized(), - SessionThread.displayName( - threadId: thread.id, - variant: thread.variant, - closedGroupName: nil, // Not supported - openGroupName: nil // Not supported - ) + senderName ) } From d42088e37c6f48281ffe2386a512017e496ab3fc Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 5 Sep 2022 15:45:30 +1000 Subject: [PATCH 10/15] fix an edge case where the isCallOngoing will always be true --- Session/Meta/AppDelegate.swift | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Session/Meta/AppDelegate.swift b/Session/Meta/AppDelegate.swift index aeaa99275..740f053c3 100644 --- a/Session/Meta/AppDelegate.swift +++ b/Session/Meta/AppDelegate.swift @@ -78,6 +78,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD SNAppearance.switchToSessionAppearance() + if Environment.shared?.callManager.wrappedValue?.currentCall == nil { + UserDefaults.sharedLokiProject?.set(false, forKey: "isCallOngoing") + } + // No point continuing if we are running tests guard !CurrentAppContext().isRunningTests else { return true } @@ -142,16 +146,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } } - func applicationDidReceiveMemoryWarning(_ application: UIApplication) { - Logger.info("applicationDidReceiveMemoryWarning") - } - - func applicationWillTerminate(_ application: UIApplication) { - DDLog.flushLog() - - stopPollers() - } - func applicationDidBecomeActive(_ application: UIApplication) { guard !CurrentAppContext().isRunningTests else { return } From ae7895c18e38f4e1355690be5e5500c00b101eb0 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 5 Sep 2022 17:14:29 +1000 Subject: [PATCH 11/15] fix a issue where the call info message won't be updated --- Session/Calls/Call Management/SessionCall.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Session/Calls/Call Management/SessionCall.swift b/Session/Calls/Call Management/SessionCall.swift index 21614e218..da1324905 100644 --- a/Session/Calls/Call Management/SessionCall.swift +++ b/Session/Calls/Call Management/SessionCall.swift @@ -278,7 +278,8 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate { let duration: TimeInterval = self.duration let hasStartedConnecting: Bool = self.hasStartedConnecting - Storage.shared.writeAsync { db in + // Don't know whether there will be an impact if we don't write async + Storage.shared.write { db in guard let interaction: Interaction = try? Interaction.fetchOne(db, id: callInteractionId) else { return } From ccbf4e094576a2478d47487969c84d1d2469a2b7 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 5 Sep 2022 17:14:56 +1000 Subject: [PATCH 12/15] clean --- .../Sending & Receiving/Notifications/PushNotificationAPI.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SessionMessagingKit/Sending & Receiving/Notifications/PushNotificationAPI.swift b/SessionMessagingKit/Sending & Receiving/Notifications/PushNotificationAPI.swift index be56e92bf..11499c28f 100644 --- a/SessionMessagingKit/Sending & Receiving/Notifications/PushNotificationAPI.swift +++ b/SessionMessagingKit/Sending & Receiving/Notifications/PushNotificationAPI.swift @@ -28,7 +28,7 @@ public final class PushNotificationAPI : NSObject { } // MARK: - Settings - public static let server = "https://dev.apns.getsession.org" + public static let server = "https://live.apns.getsession.org" public static let serverPublicKey = "642a6585919742e5a2d4dc51244964fbcd8bcab2b75612407de58b810740d049" private static let maxRetryCount: UInt = 4 From 9419f83f43a927406a760142ec1d4dbe924f5814 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Tue, 6 Sep 2022 12:09:21 +1000 Subject: [PATCH 13/15] put back accidentally removed code --- Session/Meta/AppDelegate.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Session/Meta/AppDelegate.swift b/Session/Meta/AppDelegate.swift index 740f053c3..0255c03e0 100644 --- a/Session/Meta/AppDelegate.swift +++ b/Session/Meta/AppDelegate.swift @@ -146,6 +146,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } } + func applicationDidReceiveMemoryWarning(_ application: UIApplication) { + Logger.info("applicationDidReceiveMemoryWarning") + } + + func applicationWillTerminate(_ application: UIApplication) { + DDLog.flushLog() + + stopPollers() + } + func applicationDidBecomeActive(_ application: UIApplication) { guard !CurrentAppContext().isRunningTests else { return } From 7c1d3327639e55718888a9cb7789df30d4669fde Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Tue, 6 Sep 2022 12:16:58 +1000 Subject: [PATCH 14/15] move database suspending logic when handling calls in background after writeAsync --- .../Calls/Call Management/SessionCall.swift | 101 ++++++++++-------- .../Call Management/SessionCallManager.swift | 6 -- 2 files changed, 55 insertions(+), 52 deletions(-) diff --git a/Session/Calls/Call Management/SessionCall.swift b/Session/Calls/Call Management/SessionCall.swift index da1324905..7df8004a6 100644 --- a/Session/Calls/Call Management/SessionCall.swift +++ b/Session/Calls/Call Management/SessionCall.swift @@ -278,56 +278,65 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate { let duration: TimeInterval = self.duration let hasStartedConnecting: Bool = self.hasStartedConnecting - // Don't know whether there will be an impact if we don't write async - Storage.shared.write { db in - guard let interaction: Interaction = try? Interaction.fetchOne(db, id: callInteractionId) else { - return - } - - let updateToMissedIfNeeded: () throws -> () = { - let missedCallInfo: CallMessage.MessageInfo = CallMessage.MessageInfo(state: .missed) + Storage.shared.writeAsync( + updates: { db in + guard let interaction: Interaction = try? Interaction.fetchOne(db, id: callInteractionId) else { + return + } - guard - let infoMessageData: Data = (interaction.body ?? "").data(using: .utf8), - let messageInfo: CallMessage.MessageInfo = try? JSONDecoder().decode( - CallMessage.MessageInfo.self, - from: infoMessageData - ), - messageInfo.state == .incoming, - let missedCallInfoData: Data = try? JSONEncoder().encode(missedCallInfo) - else { return } + let updateToMissedIfNeeded: () throws -> () = { + let missedCallInfo: CallMessage.MessageInfo = CallMessage.MessageInfo(state: .missed) + + guard + let infoMessageData: Data = (interaction.body ?? "").data(using: .utf8), + let messageInfo: CallMessage.MessageInfo = try? JSONDecoder().decode( + CallMessage.MessageInfo.self, + from: infoMessageData + ), + messageInfo.state == .incoming, + let missedCallInfoData: Data = try? JSONEncoder().encode(missedCallInfo) + else { return } + + _ = try interaction + .with(body: String(data: missedCallInfoData, encoding: .utf8)) + .saved(db) + } + let shouldMarkAsRead: Bool = try { + if duration > 0 { return true } + if hasStartedConnecting { return true } + + switch mode { + case .local: + try updateToMissedIfNeeded() + return true + + case .remote, .unanswered: + try updateToMissedIfNeeded() + return false + + case .answeredElsewhere: return true + } + }() - _ = try interaction - .with(body: String(data: missedCallInfoData, encoding: .utf8)) - .saved(db) - } - let shouldMarkAsRead: Bool = try { - if duration > 0 { return true } - if hasStartedConnecting { return true } + guard shouldMarkAsRead else { return } - switch mode { - case .local: - try updateToMissedIfNeeded() - return true - - case .remote, .unanswered: - try updateToMissedIfNeeded() - return false - - case .answeredElsewhere: return true + try Interaction.markAsRead( + db, + interactionId: interaction.id, + threadId: interaction.threadId, + includingOlder: false, + trySendReadReceipt: false + ) + }, + completion: { _, _ in + if CurrentAppContext().isInBackground() { + // Stop all jobs except for message sending and when completed suspend the database + JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend) { + NotificationCenter.default.post(name: Database.suspendNotification, object: self) + } } - }() - - guard shouldMarkAsRead else { return } - - try Interaction.markAsRead( - db, - interactionId: interaction.id, - threadId: interaction.threadId, - includingOlder: false, - trySendReadReceipt: false - ) - } + } + ) } // MARK: - Renderer diff --git a/Session/Calls/Call Management/SessionCallManager.swift b/Session/Calls/Call Management/SessionCallManager.swift index e7ab88431..aa7e5a998 100644 --- a/Session/Calls/Call Management/SessionCallManager.swift +++ b/Session/Calls/Call Management/SessionCallManager.swift @@ -136,12 +136,6 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { func handleCallEnded() { WebRTCSession.current = nil UserDefaults.sharedLokiProject?.set(false, forKey: "isCallOngoing") - if CurrentAppContext().isInBackground() { - // Stop all jobs except for message sending and when completed suspend the database - JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend) { - NotificationCenter.default.post(name: Database.suspendNotification, object: self) - } - } } guard let call = currentCall else { From 87c2bc3700878f78900f11a62c537945c815e131 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Wed, 7 Sep 2022 10:46:39 +1000 Subject: [PATCH 15/15] tweaks on the logic to suspend database when call is ended in background --- Session/Calls/Call Management/SessionCall.swift | 7 +------ Session/Calls/Call Management/SessionCallManager.swift | 10 ++++++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Session/Calls/Call Management/SessionCall.swift b/Session/Calls/Call Management/SessionCall.swift index 7df8004a6..87a3aed2a 100644 --- a/Session/Calls/Call Management/SessionCall.swift +++ b/Session/Calls/Call Management/SessionCall.swift @@ -329,12 +329,7 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate { ) }, completion: { _, _ in - if CurrentAppContext().isInBackground() { - // Stop all jobs except for message sending and when completed suspend the database - JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend) { - NotificationCenter.default.post(name: Database.suspendNotification, object: self) - } - } + SessionCallManager.suspendDatabaseIfCallEndedInBackground() } ) } diff --git a/Session/Calls/Call Management/SessionCallManager.swift b/Session/Calls/Call Management/SessionCallManager.swift index aa7e5a998..38ecd7b75 100644 --- a/Session/Calls/Call Management/SessionCallManager.swift +++ b/Session/Calls/Call Management/SessionCallManager.swift @@ -140,6 +140,7 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { guard let call = currentCall else { handleCallEnded() + Self.suspendDatabaseIfCallEndedInBackground() return } @@ -177,6 +178,15 @@ public final class SessionCallManager: NSObject, CallManagerProtocol { callUpdate.supportsDTMF = false } + public static func suspendDatabaseIfCallEndedInBackground() { + if CurrentAppContext().isInBackground() { + // Stop all jobs except for message sending and when completed suspend the database + JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend) { + NotificationCenter.default.post(name: Database.suspendNotification, object: self) + } + } + } + // MARK: - UI public func showCallUIForCall(caller: String, uuid: String, mode: CallMode, interactionId: Int64?) {