Element Call: Send rtc.decline event when incoming call is declined (#4499)
This commit is contained in:
@@ -8997,6 +8997,76 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
||||
return elementCallWidgetDriverDeviceIDReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - declineCall
|
||||
|
||||
var declineCallNotificationIDUnderlyingCallsCount = 0
|
||||
var declineCallNotificationIDCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return declineCallNotificationIDUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = declineCallNotificationIDUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
declineCallNotificationIDUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
declineCallNotificationIDUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var declineCallNotificationIDCalled: Bool {
|
||||
return declineCallNotificationIDCallsCount > 0
|
||||
}
|
||||
var declineCallNotificationIDReceivedNotificationID: String?
|
||||
var declineCallNotificationIDReceivedInvocations: [String] = []
|
||||
|
||||
var declineCallNotificationIDUnderlyingReturnValue: Result<Void, RoomProxyError>!
|
||||
var declineCallNotificationIDReturnValue: Result<Void, RoomProxyError>! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return declineCallNotificationIDUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: Result<Void, RoomProxyError>? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = declineCallNotificationIDUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
declineCallNotificationIDUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
declineCallNotificationIDUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var declineCallNotificationIDClosure: ((String) async -> Result<Void, RoomProxyError>)?
|
||||
|
||||
func declineCall(notificationID: String) async -> Result<Void, RoomProxyError> {
|
||||
declineCallNotificationIDCallsCount += 1
|
||||
declineCallNotificationIDReceivedNotificationID = notificationID
|
||||
DispatchQueue.main.async {
|
||||
self.declineCallNotificationIDReceivedInvocations.append(notificationID)
|
||||
}
|
||||
if let declineCallNotificationIDClosure = declineCallNotificationIDClosure {
|
||||
return await declineCallNotificationIDClosure(notificationID)
|
||||
} else {
|
||||
return declineCallNotificationIDReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - matrixToPermalink
|
||||
|
||||
var matrixToPermalinkUnderlyingCallsCount = 0
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ class NotificationHandler {
|
||||
return .processedShouldDiscard
|
||||
case .callNotify(let notifyType):
|
||||
return await handleCallNotification(notifyType: notifyType,
|
||||
rtcNotifyEventID: event.eventId(),
|
||||
timestamp: event.timestamp(),
|
||||
roomID: itemProxy.roomID,
|
||||
roomDisplayName: itemProxy.roomDisplayName)
|
||||
@@ -153,6 +154,7 @@ class NotificationHandler {
|
||||
/// Handle incoming call notifications.
|
||||
/// - Returns: A boolean indicating whether the notification was handled and should now be discarded.
|
||||
private func handleCallNotification(notifyType: NotifyType,
|
||||
rtcNotifyEventID: String,
|
||||
timestamp: Timestamp,
|
||||
roomID: String,
|
||||
roomDisplayName: String) async -> NotificationProcessingResult {
|
||||
@@ -206,7 +208,8 @@ class NotificationHandler {
|
||||
}
|
||||
|
||||
let payload = [ElementCallServiceNotificationKey.roomID.rawValue: roomID,
|
||||
ElementCallServiceNotificationKey.roomDisplayName.rawValue: roomDisplayName]
|
||||
ElementCallServiceNotificationKey.roomDisplayName.rawValue: roomDisplayName,
|
||||
ElementCallServiceNotificationKey.rtcNotifyEventID.rawValue: rtcNotifyEventID]
|
||||
|
||||
do {
|
||||
try await CXProvider.reportNewIncomingVoIPPushPayload(payload)
|
||||
|
||||
Reference in New Issue
Block a user