diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 1c1c3e684..666761018 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -16,8 +16,6 @@ dependencies = ( ); name = Periphery; - packageProductDependencies = ( - ); productName = Periphery; }; /* End PBXAggregateTarget section */ @@ -765,6 +763,7 @@ 93AC1E8418D8C827671FB3A9 /* IdentityConfirmedScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 595EC503DA5517BBE6D39406 /* IdentityConfirmedScreenCoordinator.swift */; }; 93BA4A81B6D893271101F9F0 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = A7CA6F33C553805035C3B114 /* DeviceKit */; }; 93BAF04D9CCBC0A8841414D0 /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D67E616BCA82D8A1258D488 /* NetworkMonitor.swift */; }; + 93DC8297B8287B50B2A4B57D /* ExpiringTaskRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B25F959A434BB9923A3223F /* ExpiringTaskRunner.swift */; }; 9408CE8B8865C0C8DD4C9869 /* NoticeRoomTimelineItemContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD51B4D5173F7FC886F5360 /* NoticeRoomTimelineItemContent.swift */; }; 9462C62798F47E39DCC182D2 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA89A2DD51B6BBE1DA55E263 /* Application.swift */; }; 94A65DD8A353DF112EBEF67A /* SessionVerificationControllerProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D56469A9EE0CFA2B7BA9760 /* SessionVerificationControllerProxyProtocol.swift */; }; @@ -6411,7 +6410,6 @@ "zh-Hant-TW", ); mainGroup = 405B00F139AEE3994601B36A; - minimizedProjectReferenceProxies = 1; packageReferences = ( E025F19D013D9BA6C58B37F4 /* XCRemoteSwiftPackageReference "swift-algorithms" */, AC3475112CA40C2C6E78D1EB /* XCRemoteSwiftPackageReference "matrix-analytics-events" */, @@ -6438,7 +6436,6 @@ EC6D0C817B1C21D9D096505A /* XCRemoteSwiftPackageReference "Version" */, EE40B0E16A55BD23ECBFFD22 /* XCRemoteSwiftPackageReference "matrix-rich-text-editor-swift" */, ); - preferredProjectObjectVersion = 54; projectDirPath = ""; projectRoot = ""; targets = ( @@ -6694,6 +6691,7 @@ 24A75F72EEB7561B82D726FD /* Date.swift in Sources */, 9F11B9F347F9E2D236799FB3 /* ElementCallServiceConstants.swift in Sources */, CFEC53440C572CEEABC4A6A0 /* ElementXAttributeScope.swift in Sources */, + 93DC8297B8287B50B2A4B57D /* ExpiringTaskRunner.swift in Sources */, 89198AE2649DD77673D5793B /* ExtensionLogger.swift in Sources */, A33784831AD880A670CAA9F9 /* FileManager.swift in Sources */, 59F940FCBE6BC343AECEF75E /* ImageCache.swift in Sources */, diff --git a/NSE/Sources/NotificationHandler.swift b/NSE/Sources/NotificationHandler.swift index bf80da5d6..024566287 100644 --- a/NSE/Sources/NotificationHandler.swift +++ b/NSE/Sources/NotificationHandler.swift @@ -10,6 +10,7 @@ import MatrixRustSDK import UserNotifications class NotificationHandler { + private let userSession: NSEUserSession private let settings: CommonSettingsProtocol private let contentHandler: (UNNotificationContent) -> Void private var notificationContent: UNMutableNotificationContent @@ -17,10 +18,15 @@ class NotificationHandler { private let notificationContentBuilder: NotificationContentBuilder - init(settings: CommonSettingsProtocol, + // periphery:ignore - required for instance retention in the rust codebase + private var roomInfoObservationToken: TaskHandle? + + init(userSession: NSEUserSession, + settings: CommonSettingsProtocol, contentHandler: @escaping (UNNotificationContent) -> Void, notificationContent: UNMutableNotificationContent, tag: String) { + self.userSession = userSession self.settings = settings self.contentHandler = contentHandler self.notificationContent = notificationContent @@ -33,9 +39,7 @@ class NotificationHandler { settings: settings) } - func processEvent(_ eventID: String, - roomID: String, - userSession: NSEUserSession) async { + func processEvent(_ eventID: String, roomID: String) async { MXLog.info("\(tag) Processing event: \(eventID) in room: \(roomID)") guard let notificationItemProxy = await userSession.notificationItemProxy(roomID: roomID, eventID: eventID) else { @@ -163,10 +167,31 @@ class NotificationHandler { return .shouldDisplay } - let timestamp = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000)) - guard abs(timestamp.timeIntervalSinceNow) < ElementCallServiceNotificationDiscardDelta else { - MXLog.info("Call notification is too old, handling as push notification") - return .shouldDisplay + // Check to see if a call is still ongoing + if let room = userSession.roomForIdentifier(roomID) { // Try to get call details from the room info + if !room.hasActiveRoomCall() { // If I don't have an active call wait a bit and make sure + let runner = ExpiringTaskRunner { + await withCheckedContinuation { [weak self] continuation in + self?.roomInfoObservationToken = room.subscribeToRoomInfoUpdates(listener: RoomInfoUpdateListener { _ in + MXLog.info("Received room info update") + continuation.resume() + }) + } + } + + try? await runner.run(timeout: .seconds(5)) // Wait 5 seconds or just use whatever is available + + guard room.hasActiveRoomCall() else { + return .shouldDisplay + } + } + } else { // Otherwise fallback to the old timeout mechanism + let timestamp = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000)) + + guard abs(timestamp.timeIntervalSinceNow) < ElementCallServiceNotificationDiscardDelta else { + MXLog.info("Call notification is too old, handling as push notification") + return .shouldDisplay + } } let payload = [ElementCallServiceNotificationKey.roomID.rawValue: roomID, @@ -189,3 +214,15 @@ class NotificationHandler { case unsupportedShouldDiscard } } + +private final class RoomInfoUpdateListener: RoomInfoListener { + private let onUpdateClosure: (RoomInfo) -> Void + + init(_ onUpdateClosure: @escaping (RoomInfo) -> Void) { + self.onUpdateClosure = onUpdateClosure + } + + func call(roomInfo: RoomInfo) { + onUpdateClosure(roomInfo) + } +} diff --git a/NSE/Sources/NotificationServiceExtension.swift b/NSE/Sources/NotificationServiceExtension.swift index a90498ca6..338bb6553 100644 --- a/NSE/Sources/NotificationServiceExtension.swift +++ b/NSE/Sources/NotificationServiceExtension.swift @@ -63,11 +63,6 @@ class NotificationServiceExtension: UNNotificationServiceExtension { Target.nse.configure(logLevel: settings.logLevel, traceLogPacks: settings.traceLogPacks) - notificationHandler = NotificationHandler(settings: settings, - contentHandler: contentHandler, - notificationContent: mutableContent, - tag: tag) - MXLog.info("\(tag) #########################################") ExtensionLogger.logMemory(with: tag) @@ -82,12 +77,16 @@ class NotificationServiceExtension: UNNotificationServiceExtension { appHooks: appHooks, appSettings: settings) + notificationHandler = NotificationHandler(userSession: userSession, + settings: settings, + contentHandler: contentHandler, + notificationContent: mutableContent, + tag: tag) + ExtensionLogger.logMemory(with: tag) MXLog.info("\(tag) Configured user session") - await notificationHandler?.processEvent(eventID, - roomID: roomID, - userSession: userSession) + await notificationHandler?.processEvent(eventID, roomID: roomID) } catch { MXLog.error("Failed creating user session with error: \(error)") } diff --git a/NSE/Sources/Other/NSEUserSession.swift b/NSE/Sources/Other/NSEUserSession.swift index b723bab58..ce620444f 100644 --- a/NSE/Sources/Other/NSEUserSession.swift +++ b/NSE/Sources/Other/NSEUserSession.swift @@ -68,11 +68,20 @@ final class NSEUserSession { receiverID: userID, roomID: roomID) } catch { - MXLog.error("NSE: Could not get notification's content creating an empty notification instead, error: \(error)") + MXLog.error("Could not get notification's content creating an empty notification instead, error: \(error)") return EmptyNotificationItemProxy(eventID: eventID, roomID: roomID, receiverID: userID) } } + func roomForIdentifier(_ roomID: String) -> Room? { + do { + return try baseClient.getRoom(roomId: roomID) + } catch { + MXLog.error("Failed retrieving room with error: \(error)") + return nil + } + } + deinit { delegateHandle?.cancel() } diff --git a/NSE/SupportingFiles/target.yml b/NSE/SupportingFiles/target.yml index da35d2d6a..21a68a238 100644 --- a/NSE/SupportingFiles/target.yml +++ b/NSE/SupportingFiles/target.yml @@ -88,6 +88,7 @@ targets: - path: ../../ElementX/Sources/Generated/Strings.swift - path: ../../ElementX/Sources/Other/Avatars.swift - path: ../../ElementX/Sources/Other/CurrentValuePublisher.swift + - path: ../../ElementX/Sources/Other/ExpiringTaskRunner.swift - path: ../../ElementX/Sources/Other/Extensions/AttributedString.swift - path: ../../ElementX/Sources/Other/Extensions/Bundle.swift - path: ../../ElementX/Sources/Other/Extensions/ClientBuilder.swift