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 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