From 0fe935a16fa419e56acbf7e22ab75959fffee116 Mon Sep 17 00:00:00 2001 From: QuentinA Date: Mon, 16 Mar 2026 15:22:31 +0100 Subject: [PATCH] Use core.stopAsync with a looping iterate in app extension. This will allow the app extension to wait for the necessary data to be able to send IMDNs, and then exit cleanely as soon as it is done. If used with a flexisip 2.4 or older, there will always be a delay configured by the config section: 'misc', key: 'delay_message_send_s' before the IMDN gets sent and the notification is displayed --- .../NotificationService.swift | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/msgNotificationService/NotificationService.swift b/msgNotificationService/NotificationService.swift index a6437fac1..c5360f791 100644 --- a/msgNotificationService/NotificationService.swift +++ b/msgNotificationService/NotificationService.swift @@ -21,6 +21,7 @@ import UserNotifications import linphonesw +import Combine #if USE_CRASHLYTICS import Firebase #endif @@ -80,6 +81,8 @@ class NotificationService: UNNotificationServiceExtension { var bestAttemptContent: UNMutableNotificationContent? var lc: Core? + var coreDelegate: CoreDelegate? + private var mIteratePublisher: AnyCancellable? override init() { super.init() @@ -89,7 +92,6 @@ class NotificationService: UNNotificationServiceExtension { } override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { - let timeStart = Date.now self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) @@ -173,6 +175,12 @@ class NotificationService: UNNotificationServiceExtension { if let message = message { + if message.reactionContent == " " { + // Do not display notification if it was a reaction being removed + contentHandler(UNNotificationContent()) + return + } + let nilParams: ConferenceParams? = nil if let peerAddr = message.peerAddr , let chatroom = lc!.searchChatRoom(params: nilParams, localAddr: nil, remoteAddr: peerAddr, participants: nil), chatroom.muted { @@ -205,17 +213,24 @@ class NotificationService: UNNotificationServiceExtension { bestAttemptContent.userInfo.updateValue(msgData?.peerAddr as Any, forKey: "peer_addr") bestAttemptContent.userInfo.updateValue(msgData?.localAddr as Any, forKey: "local_addr") - // start remaining time count 25 instead of 30 to make sure we keep at least 5 seconds to finish the message processing - let remainingTime = max(0, 25 - Date.now.timeIntervalSince(timeStart)) - DispatchQueue.main.asyncAfter(deadline: .now() + min(3, remainingTime)) { - self.lc?.iterate() - self.stopCore() - if message.reactionContent != " " { + coreDelegate = CoreDelegateStub(onGlobalStateChanged: { (core: Core, gstate: GlobalState, _: String) in + // Wait for core full stop to display the notification + if gstate == .Off { + self.mIteratePublisher = nil contentHandler(bestAttemptContent) - } else { - contentHandler(UNNotificationContent()) } - } + }) + lc?.addDelegate(delegate: coreDelegate!) + lc?.stopAsync() + + // Auto iterate does not work for app extension, so we manualy add + mIteratePublisher = Timer.publish(every: 0.1, on: .main, in: .common) + .autoconnect() + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in + self?.lc?.iterate() + } + return } else { Log.info("Message not found for callid ["+callId+"]") @@ -329,7 +344,7 @@ class NotificationService: UNNotificationServiceExtension { lc.stop() } } - + func updateBadge() -> Int { var count = 0 count += lc!.unreadChatMessageCount