Element Call: Send rtc.decline event when incoming call is declined (#4499)

This commit is contained in:
Valere Fedronic
2025-09-16 10:14:04 +02:00
committed by GitHub
parent 3891ca7ec8
commit df47858e7d
6 changed files with 121 additions and 3 deletions
@@ -16,6 +16,7 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
private struct CallID: Equatable {
let callKitID: UUID
let roomID: String
let rtcNotificationID: String?
}
private let pushRegistry: PKPushRegistry
@@ -93,7 +94,7 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
let callID = if let incomingCallID, incomingCallID.roomID == roomID {
incomingCallID
} else {
CallID(callKitID: UUID(), roomID: roomID)
CallID(callKitID: UUID(), roomID: roomID, rtcNotificationID: nil)
}
incomingCallID = nil
@@ -146,12 +147,17 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
return
}
guard let rtcNotificationID = payload.dictionaryPayload[ElementCallServiceNotificationKey.rtcNotifyEventID.rawValue] as? String else {
MXLog.error("Something went wrong, missing rtc notification event identifier for incoming voip call: \(payload)")
return
}
guard ongoingCallID?.roomID != roomID else {
MXLog.warning("Call already ongoing for room \(roomID), ignoring incoming push")
return
}
let callID = CallID(callKitID: UUID(), roomID: roomID)
let callID = CallID(callKitID: UUID(), roomID: roomID, rtcNotificationID: rtcNotificationID)
incomingCallID = callID
let roomDisplayName = payload.dictionaryPayload[ElementCallServiceNotificationKey.roomDisplayName.rawValue] as? String
@@ -253,6 +259,12 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
actionsSubject.send(.endCall(roomID: ongoingCallID.roomID))
}
if let incomingCallID {
Task {
await sendDeclineCallEvent(incomingCallID)
}
}
tearDownCallSession(sendEndCallAction: false)
action.fulfill()
@@ -274,6 +286,25 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
ongoingCallID = nil
}
private func sendDeclineCallEvent(_ incomingCallID: CallID) async {
guard let rtcNotificationID = incomingCallID.rtcNotificationID else {
MXLog.info("No rtc notification event to decline.")
return
}
guard let clientProxy else {
MXLog.warning("A ClientProxy is needed to fetch the room.")
return
}
guard case let .joined(roomProxy) = await clientProxy.roomForIdentifier(incomingCallID.roomID) else {
MXLog.warning("Failed to fetch a joined room for the incoming call.")
return
}
_ = await roomProxy.declineCall(notificationID: rtcNotificationID)
}
private func observeIncomingCallRoomInfo() async {
incomingCallRoomInfoCancellable = nil
@@ -10,6 +10,9 @@ import Foundation
enum ElementCallServiceNotificationKey: String {
case roomID
case roomDisplayName
/// When an incoming call is set to ring, there will be a `m.rtc.notification`event (MSC4075).
/// Keep the notification event id as it is needed to decline calls (MSC4310).
case rtcNotifyEventID
}
let ElementCallServiceNotificationDiscardDelta = 15.0
@@ -639,6 +639,16 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
ElementCallWidgetDriver(room: room, deviceID: deviceID)
}
func declineCall(notificationID: String) async -> Result<Void, RoomProxyError> {
do {
try await room.declineCall(rtcNotificationEventId: notificationID)
return .success(())
} catch {
MXLog.error("Failed to decline rtc notification \(notificationID) with error: \(error)")
return .failure(.sdkError(error))
}
}
// MARK: - Permalinks
func matrixToPermalink() async -> Result<URL, RoomProxyError> {
@@ -169,6 +169,7 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
// MARK: - Element Call
func elementCallWidgetDriver(deviceID: String) -> ElementCallWidgetDriverProtocol
func declineCall(notificationID: String) async -> Result<Void, RoomProxyError>
// MARK: - Permalinks