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

This commit is contained in:
QuentinA 2026-03-16 15:22:31 +01:00
parent 2f56839937
commit 0fe935a16f

View file

@ -21,6 +21,7 @@
import UserNotifications import UserNotifications
import linphonesw import linphonesw
import Combine
#if USE_CRASHLYTICS #if USE_CRASHLYTICS
import Firebase import Firebase
#endif #endif
@ -80,6 +81,8 @@ class NotificationService: UNNotificationServiceExtension {
var bestAttemptContent: UNMutableNotificationContent? var bestAttemptContent: UNMutableNotificationContent?
var lc: Core? var lc: Core?
var coreDelegate: CoreDelegate?
private var mIteratePublisher: AnyCancellable?
override init() { override init() {
super.init() super.init()
@ -89,7 +92,6 @@ class NotificationService: UNNotificationServiceExtension {
} }
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
let timeStart = Date.now
self.contentHandler = contentHandler self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
@ -173,6 +175,12 @@ class NotificationService: UNNotificationServiceExtension {
if let message = message { 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 let nilParams: ConferenceParams? = nil
if let peerAddr = message.peerAddr if let peerAddr = message.peerAddr
, let chatroom = lc!.searchChatRoom(params: nilParams, localAddr: nil, remoteAddr: peerAddr, participants: nil), chatroom.muted { , 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?.peerAddr as Any, forKey: "peer_addr")
bestAttemptContent.userInfo.updateValue(msgData?.localAddr as Any, forKey: "local_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 coreDelegate = CoreDelegateStub(onGlobalStateChanged: { (core: Core, gstate: GlobalState, _: String) in
let remainingTime = max(0, 25 - Date.now.timeIntervalSince(timeStart)) // Wait for core full stop to display the notification
DispatchQueue.main.asyncAfter(deadline: .now() + min(3, remainingTime)) { if gstate == .Off {
self.lc?.iterate() self.mIteratePublisher = nil
self.stopCore()
if message.reactionContent != " " {
contentHandler(bestAttemptContent) 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 return
} else { } else {
Log.info("Message not found for callid ["+callId+"]") Log.info("Message not found for callid ["+callId+"]")