mirror of
https://github.com/element-hq/element-x-ios.git
synced 2025-03-10 21:39:12 +00:00
Hook up CallKit lock screen muting controls to the ElementCall widget
This commit is contained in:
parent
2cce310540
commit
d16ba9f3ef
@ -157,8 +157,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
|||||||
switch action {
|
switch action {
|
||||||
case .startCall(let roomID):
|
case .startCall(let roomID):
|
||||||
self?.handleAppRoute(.call(roomID: roomID))
|
self?.handleAppRoute(.call(roomID: roomID))
|
||||||
case .endCall:
|
default:
|
||||||
break // Handled internally in the UserSessionFlowCoordinator
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
@ -173,10 +173,10 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] action in
|
.sink { [weak self] action in
|
||||||
switch action {
|
switch action {
|
||||||
case .startCall:
|
|
||||||
break
|
|
||||||
case .endCall:
|
case .endCall:
|
||||||
self?.dismissCallScreenIfNeeded()
|
self?.dismissCallScreenIfNeeded()
|
||||||
|
default:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Generated using Sourcery 2.2.4 — https://github.com/krzysztofzablocki/Sourcery
|
// Generated using Sourcery 2.2.5 — https://github.com/krzysztofzablocki/Sourcery
|
||||||
// DO NOT EDIT
|
// DO NOT EDIT
|
||||||
|
|
||||||
// swiftlint:disable all
|
// swiftlint:disable all
|
||||||
@ -4902,6 +4902,47 @@ class ElementCallServiceMock: ElementCallServiceProtocol {
|
|||||||
tearDownCallSessionCallsCount += 1
|
tearDownCallSessionCallsCount += 1
|
||||||
tearDownCallSessionClosure?()
|
tearDownCallSessionClosure?()
|
||||||
}
|
}
|
||||||
|
//MARK: - setCallMuted
|
||||||
|
|
||||||
|
var setCallMutedRoomIDUnderlyingCallsCount = 0
|
||||||
|
var setCallMutedRoomIDCallsCount: Int {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return setCallMutedRoomIDUnderlyingCallsCount
|
||||||
|
} else {
|
||||||
|
var returnValue: Int? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = setCallMutedRoomIDUnderlyingCallsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
setCallMutedRoomIDUnderlyingCallsCount = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
setCallMutedRoomIDUnderlyingCallsCount = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var setCallMutedRoomIDCalled: Bool {
|
||||||
|
return setCallMutedRoomIDCallsCount > 0
|
||||||
|
}
|
||||||
|
var setCallMutedRoomIDReceivedArguments: (muted: Bool, roomID: String)?
|
||||||
|
var setCallMutedRoomIDReceivedInvocations: [(muted: Bool, roomID: String)] = []
|
||||||
|
var setCallMutedRoomIDClosure: ((Bool, String) -> Void)?
|
||||||
|
|
||||||
|
func setCallMuted(_ muted: Bool, roomID: String) {
|
||||||
|
setCallMutedRoomIDCallsCount += 1
|
||||||
|
setCallMutedRoomIDReceivedArguments = (muted: muted, roomID: roomID)
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.setCallMutedRoomIDReceivedInvocations.append((muted: muted, roomID: roomID))
|
||||||
|
}
|
||||||
|
setCallMutedRoomIDClosure?(muted, roomID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class ElementCallWidgetDriverMock: ElementCallWidgetDriverProtocol {
|
class ElementCallWidgetDriverMock: ElementCallWidgetDriverProtocol {
|
||||||
var widgetID: String {
|
var widgetID: String {
|
||||||
|
@ -58,11 +58,35 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: intercept EC mute state changes and pass them over to CallKit
|
||||||
|
// elementCallService.setCallMuted(roomID: roomProxy.id, muted: muted)
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
await self.widgetDriver.sendMessage(message)
|
await self.widgetDriver.sendMessage(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elementCallService.actions
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] action in
|
||||||
|
guard let self else { return }
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case let .setCallMuted(muted, roomID):
|
||||||
|
guard roomID == roomProxy.id else {
|
||||||
|
MXLog.error("Received mute request for a different room: \(roomID) != \(roomProxy.id)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Task {
|
||||||
|
await self.setMuted(muted)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
widgetDriver.messagePublisher
|
widgetDriver.messagePublisher
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] receivedMessage in
|
.sink { [weak self] receivedMessage in
|
||||||
@ -115,6 +139,8 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
|
|||||||
|
|
||||||
await elementCallService.setupCallSession(roomID: roomProxy.id, roomDisplayName: roomProxy.roomTitle)
|
await elementCallService.setupCallSession(roomID: roomProxy.id, roomDisplayName: roomProxy.roomTitle)
|
||||||
|
|
||||||
|
// TODO: Pass over the current EC mute status to CallKit
|
||||||
|
|
||||||
let _ = await roomProxy.sendCallNotificationIfNeeeded()
|
let _ = await roomProxy.sendCallNotificationIfNeeeded()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,6 +163,10 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
|
|||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
|
private func setMuted(_ muted: Bool) async {
|
||||||
|
// Not supported on EC yet
|
||||||
|
}
|
||||||
|
|
||||||
private func hangUp() async {
|
private func hangUp() async {
|
||||||
let hangUpMessage = """
|
let hangUpMessage = """
|
||||||
{"api":"fromWidget",
|
{"api":"fromWidget",
|
||||||
|
@ -103,6 +103,25 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
|
|||||||
func tearDownCallSession() {
|
func tearDownCallSession() {
|
||||||
tearDownCallSession(sendEndCallAction: true)
|
tearDownCallSession(sendEndCallAction: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setCallMuted(_ muted: Bool, roomID: String) {
|
||||||
|
guard let ongoingCallID else {
|
||||||
|
MXLog.error("Failed toggling call microphone, no calls running")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard ongoingCallID.roomID == roomID else {
|
||||||
|
MXLog.error("Failed toggling call microphone, rooms don't match: \(ongoingCallID.roomID) != \(roomID)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let transaction = CXTransaction(action: CXSetMutedCallAction(call: ongoingCallID.callKitID, muted: muted))
|
||||||
|
callController.request(transaction) { error in
|
||||||
|
if let error {
|
||||||
|
MXLog.error("Failed toggling call microphone with error: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - PKPushRegistryDelegate
|
// MARK: - PKPushRegistryDelegate
|
||||||
|
|
||||||
@ -164,9 +183,16 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
|
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
|
||||||
// Forward this to the widget somehow
|
// if let ongoingCallID {
|
||||||
// webView.evaluateJavaScript("groupCall.setLocalVideoMuted(!groupCall.isLocalVideoMuted())")
|
// actionsSubject.send(.setCallMuted(action.isMuted, roomID: ongoingCallID.roomID))
|
||||||
// webView.evaluateJavaScript("groupCall.setMicrophoneMuted(!groupCall.isMicrophoneMuted())"
|
// } else {
|
||||||
|
// MXLog.error("Failed muting/unmuting call, missing ongoingCallID")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// action.fulfill()
|
||||||
|
|
||||||
|
// TODO: EC doesn't expose controls for this yet. Fail the action for now.
|
||||||
|
action.fail()
|
||||||
}
|
}
|
||||||
|
|
||||||
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
|
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
|
||||||
|
@ -19,6 +19,7 @@ import Combine
|
|||||||
enum ElementCallServiceAction {
|
enum ElementCallServiceAction {
|
||||||
case startCall(roomID: String)
|
case startCall(roomID: String)
|
||||||
case endCall(roomID: String)
|
case endCall(roomID: String)
|
||||||
|
case setCallMuted(_ muted: Bool, roomID: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ElementCallServiceNotificationKey: String {
|
enum ElementCallServiceNotificationKey: String {
|
||||||
@ -35,4 +36,6 @@ protocol ElementCallServiceProtocol {
|
|||||||
func setupCallSession(roomID: String, roomDisplayName: String) async
|
func setupCallSession(roomID: String, roomDisplayName: String) async
|
||||||
|
|
||||||
func tearDownCallSession()
|
func tearDownCallSession()
|
||||||
|
|
||||||
|
func setCallMuted(_ muted: Bool, roomID: String)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user