Fixes #3050 - Sync mute state between ElementCall and CallKit

This commit is contained in:
Stefan Ceriu
2024-08-06 13:23:29 +03:00
committed by Stefan Ceriu
parent e667be0f43
commit d31e128aa7
7 changed files with 107 additions and 67 deletions
@@ -118,7 +118,7 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
tearDownCallSession(sendEndCallAction: true)
}
func setCallMuted(_ muted: Bool, roomID: String) {
func setAudioEnabled(_ enabled: Bool, roomID: String) {
guard let ongoingCallID else {
MXLog.error("Failed toggling call microphone, no calls running")
return
@@ -129,7 +129,7 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
return
}
let transaction = CXTransaction(action: CXSetMutedCallAction(call: ongoingCallID.callKitID, muted: muted))
let transaction = CXTransaction(action: CXSetMutedCallAction(call: ongoingCallID.callKitID, muted: !enabled))
callController.request(transaction) { error in
if let error {
MXLog.error("Failed toggling call microphone with error: \(error)")
@@ -211,16 +211,13 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
}
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
// if let ongoingCallID {
// actionsSubject.send(.setCallMuted(action.isMuted, roomID: ongoingCallID.roomID))
// } else {
// MXLog.error("Failed muting/unmuting call, missing ongoingCallID")
// }
//
// action.fulfill()
if let ongoingCallID {
actionsSubject.send(.setAudioEnabled(!action.isMuted, roomID: ongoingCallID.roomID))
} else {
MXLog.error("Failed muting/unmuting call, missing ongoingCallID")
}
// TODO: EC doesn't expose controls for this yet. Fail the action for now.
action.fail()
action.fulfill()
}
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
@@ -19,7 +19,7 @@ import Combine
enum ElementCallServiceAction {
case startCall(roomID: String)
case endCall(roomID: String)
case setCallMuted(_ muted: Bool, roomID: String)
case setAudioEnabled(_ enabled: Bool, roomID: String)
}
// sourcery: AutoMockable
@@ -32,5 +32,5 @@ protocol ElementCallServiceProtocol {
func tearDownCallSession()
func setCallMuted(_ muted: Bool, roomID: String)
func setAudioEnabled(_ enabled: Bool, roomID: String)
}
@@ -18,7 +18,7 @@ import Combine
import MatrixRustSDK
import SwiftUI
private struct ElementCallWidgetMessage: Codable {
struct ElementCallWidgetMessage: Codable {
enum Direction: String, Codable {
case fromWidget
case toWidget
@@ -26,14 +26,32 @@ private struct ElementCallWidgetMessage: Codable {
enum Action: String, Codable {
case hangup = "im.vector.hangup"
case mediaState = "io.element.device_mute"
}
struct Data: Codable {
var audioEnabled: Bool?
var videoEnabled: Bool?
enum CodingKeys: String, CodingKey {
case audioEnabled = "audio_enabled"
case videoEnabled = "video_enabled"
}
}
let direction: Direction
let action: Action
var data: Data = .init()
let widgetId: String
var requestId = "widgetapi-\(UUID())"
enum CodingKeys: String, CodingKey {
case direction = "api"
case action
case data
case widgetId
case requestId
}
}
@@ -151,16 +169,29 @@ class ElementCallWidgetDriver: WidgetCapabilitiesProvider, ElementCallWidgetDriv
// MARK: - Private
func handleMessageIfNeeded(_ message: String) {
guard let data = message.data(using: .utf8),
let widgetMessage = try? JSONDecoder().decode(ElementCallWidgetMessage.self, from: data) else {
guard let data = message.data(using: .utf8) else {
return
}
if widgetMessage.direction == .fromWidget {
switch widgetMessage.action {
case .hangup:
actionsSubject.send(.callEnded)
do {
let widgetMessage = try JSONDecoder().decode(ElementCallWidgetMessage.self, from: data)
if widgetMessage.direction == .fromWidget {
switch widgetMessage.action {
case .hangup:
actionsSubject.send(.callEnded)
case .mediaState:
guard let audioEnabled = widgetMessage.data.audioEnabled,
let videoEnabled = widgetMessage.data.videoEnabled else {
MXLog.error("Media state change messages should contain info data")
return
}
actionsSubject.send(.mediaStateChanged(audioEnabled: audioEnabled, videoEnabled: videoEnabled))
}
}
} catch {
// Not all actions are supported
MXLog.verbose("Failed processing widget message with error: \(error)")
}
}
}
@@ -28,6 +28,7 @@ enum ElementCallWidgetDriverError: Error {
enum ElementCallWidgetDriverAction {
case callEnded
case mediaStateChanged(audioEnabled: Bool, videoEnabled: Bool)
}
// sourcery: AutoMockable