Rely on the room's info to decide whether a call ringing notification is outdated and should be ignored as opposed to a time based approach.

This commit is contained in:
Stefan Ceriu
2025-04-29 18:11:39 +03:00
committed by Stefan Ceriu
parent 6c8cb2bbe5
commit 690ff3caa6
5 changed files with 65 additions and 21 deletions
+45 -8
View File
@@ -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)
}
}