AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Redux/Middleware/CallingMiddleware.swift (231 lines of code) (raw):
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
import Combine
extension Middleware {
static func liveCallingMiddleware(callingMiddlewareHandler actionHandler: CallingMiddlewareHandling)
-> Middleware<AppState, AzureCommunicationUICalling.Action> {
.init(
apply: { dispatch, getState in
return { next in
return { action in
switch action {
case .callingAction(let callingAction):
handleCallingAction(callingAction, actionHandler, getState, dispatch)
case .localUserAction(let localUserAction):
handleLocalUserAction(localUserAction, actionHandler, getState, dispatch)
case .permissionAction(let permissionAction):
handlePermissionAction(permissionAction, actionHandler, getState, dispatch)
case .lifecycleAction(let lifecycleAction):
handleLifecycleAction(lifecycleAction, actionHandler, getState, dispatch)
case .audioSessionAction(let audioAction):
handleAudioSessionAction(audioAction, actionHandler, getState, dispatch)
case .remoteParticipantsAction(let action):
handleRemoteParticipantAction(action, actionHandler, getState, dispatch)
case .captionsAction(let action):
handleCaptionsAction(action, actionHandler, getState, dispatch)
case .rttAction(let action):
handleRttActions(action, actionHandler, getState, dispatch)
case .errorAction,
.compositeExitAction,
.callingViewLaunched:
break
case .callDiagnosticAction(let action):
handleCallDiagnisticAction(action, actionHandler, getState, dispatch)
case .toastNotificationAction(let action):
handleToastNotificationAction(action, actionHandler, getState, dispatch)
default:
break
}
return next(action)
}
}
}
)
}
}
private func handleCallingAction(_ action: CallingAction,
_ actionHandler: CallingMiddlewareHandling,
_ getState: () -> AppState,
_ dispatch: @escaping ActionDispatch) {
switch action {
case .setupCall:
actionHandler.setupCall(state: getState(), dispatch: dispatch)
case .callStartRequested:
actionHandler.startCall(state: getState(), dispatch: dispatch)
case .callEndRequested:
actionHandler.endCall(state: getState(), dispatch: dispatch)
case .holdRequested:
actionHandler.holdCall(state: getState(), dispatch: dispatch)
case .resumeRequested:
actionHandler.resumeCall(state: getState(), dispatch: dispatch)
case .recordingStateUpdated(let isRecordingActive):
actionHandler.recordingStateUpdated(state: getState(),
dispatch: dispatch,
isRecordingActive: isRecordingActive)
case .transcriptionStateUpdated(let isTranscriptionActive):
actionHandler.transcriptionStateUpdated(state: getState(),
dispatch: dispatch,
isTranscriptionActive: isTranscriptionActive)
default:
break
}
}
private func handleLocalUserAction(_ action: LocalUserAction,
_ actionHandler: CallingMiddlewareHandling,
_ getState: () -> AppState,
_ dispatch: @escaping ActionDispatch) {
switch action {
case .cameraPreviewOnTriggered:
actionHandler.requestCameraPreviewOn(state: getState(), dispatch: dispatch)
case .cameraOnTriggered:
actionHandler.requestCameraOn(state: getState(), dispatch: dispatch)
case .cameraOffTriggered:
actionHandler.requestCameraOff(state: getState(), dispatch: dispatch)
case .cameraSwitchTriggered:
actionHandler.requestCameraSwitch(state: getState(), dispatch: dispatch)
case .microphoneOffTriggered:
actionHandler.requestMicrophoneMute(state: getState(), dispatch: dispatch)
case .microphoneOnTriggered:
actionHandler.requestMicrophoneUnmute(state: getState(), dispatch: dispatch)
case .setCapabilities(let capabilities):
actionHandler.setCapabilities(capabilities: capabilities, state: getState(), dispatch: dispatch)
case .onCapabilitiesChanged(let event):
actionHandler.onCapabilitiesChanged(event: event, state: getState(), dispatch: dispatch)
case .cameraOnSucceeded,
.cameraOnFailed,
.cameraOffSucceeded,
.cameraOffFailed,
.cameraPausedSucceeded,
.cameraPausedFailed,
.cameraSwitchSucceeded,
.cameraSwitchFailed,
.microphoneOnFailed,
.microphoneOffFailed,
.microphoneMuteStateUpdated,
.microphonePreviewOn,
.microphonePreviewOff,
.audioDeviceChangeRequested,
.audioDeviceChangeSucceeded,
.audioDeviceChangeFailed,
.participantRoleChanged:
break
}
}
private func handlePermissionAction(_ action: PermissionAction,
_ actionHandler: CallingMiddlewareHandling,
_ getState: () -> AppState,
_ dispatch: @escaping ActionDispatch) {
switch action {
case .cameraPermissionGranted:
actionHandler.onCameraPermissionIsSet(state: getState(), dispatch: dispatch)
case .audioPermissionGranted:
actionHandler.onMicPermissionIsGranted(state: getState(), dispatch: dispatch)
case .audioPermissionRequested,
.audioPermissionDenied,
.audioPermissionNotAsked,
.cameraPermissionRequested,
.cameraPermissionDenied,
.cameraPermissionNotAsked:
break
}
}
private func handleLifecycleAction(_ action: LifecycleAction,
_ actionHandler: CallingMiddlewareHandling,
_ getState: () -> AppState,
_ dispatch: @escaping ActionDispatch) {
switch action {
case .backgroundEntered:
actionHandler.enterBackground(state: getState(), dispatch: dispatch)
case .foregroundEntered:
actionHandler.enterForeground(state: getState(), dispatch: dispatch)
case .willTerminate:
if getState().callingState.status == .connected {
actionHandler.endCall(state: getState(), dispatch: dispatch)
}
}
}
private func handleAudioSessionAction(_ action: AudioSessionAction,
_ actionHandler: CallingMiddlewareHandling,
_ getState: () -> AppState,
_ dispatch: @escaping ActionDispatch) {
switch action {
case .audioInterrupted:
actionHandler.audioSessionInterrupted(state: getState(), dispatch: dispatch)
case .audioInterruptEnded,
.audioEngaged:
break
}
}
private func handleRemoteParticipantAction(_ action: RemoteParticipantsAction,
_ actionHandler: CallingMiddlewareHandling,
_ getState: () -> AppState,
_ dispatch: @escaping ActionDispatch) {
switch action {
case .admitAll:
actionHandler.admitAllLobbyParticipants(state: getState(), dispatch: dispatch)
case .declineAll:
actionHandler.declineAllLobbyParticipants(state: getState(), dispatch: dispatch)
case .admit(participantId: let participantId):
actionHandler.admitLobbyParticipant(state: getState(), dispatch: dispatch, participantId: participantId)
case .decline(participantId: let participantId):
actionHandler.declineLobbyParticipant(state: getState(), dispatch: dispatch, participantId: participantId)
case .remove(participantId: let participantId):
actionHandler.removeParticipant(state: getState(), dispatch: dispatch, participantId: participantId)
default:
break
}
}
private func handleCallDiagnisticAction(_ action: DiagnosticsAction,
_ actionHandler: CallingMiddlewareHandling,
_ getState: () -> AppState,
_ dispatch: @escaping ActionDispatch) {
switch action {
case .networkQuality(diagnostic: let diagnostic):
actionHandler.onNetworkQualityCallDiagnosticsUpdated(
state: getState(), dispatch: dispatch, diagnisticModel: diagnostic)
case .network(diagnostic: let diagnostic):
actionHandler.onNetworkCallDiagnosticsUpdated(
state: getState(), dispatch: dispatch, diagnisticModel: diagnostic)
case .media(diagnostic: let diagnostic):
actionHandler.onMediaCallDiagnosticsUpdated(state: getState(), dispatch: dispatch, diagnisticModel: diagnostic)
default:
break
}
}
private func handleToastNotificationAction(_ action: ToastNotificationAction,
_ actionHandler: CallingMiddlewareHandling,
_ getState: () -> AppState,
_ dispatch: @escaping ActionDispatch) {
switch action {
case .dismissNotification:
actionHandler.dismissNotification(state: getState(), dispatch: dispatch)
default:
break
}
}
private func handleCaptionsAction(_ action: CaptionsAction,
_ actionHandler: CallingMiddlewareHandling,
_ getState: () -> AppState,
_ dispatch: @escaping ActionDispatch) {
switch action {
case .turnOnCaptions(language: let language):
actionHandler.startCaptions(state: getState(), dispatch: dispatch, language: language)
case .turnOffCaptions:
actionHandler.stopCaptions(state: getState(), dispatch: dispatch)
case .setSpokenLanguageRequested(language: let language):
actionHandler.setCaptionsSpokenLanguage(state: getState(), dispatch: dispatch, language: language)
case .setCaptionLanguageRequested(language: let language):
actionHandler.setCaptionsLanguage(state: getState(), dispatch: dispatch, language: language)
default:
break
}
}
private func handleRttActions(_ action: RttAction,
_ actionHandler: CallingMiddlewareHandling,
_ getState: () -> AppState,
_ dispatch: @escaping ActionDispatch) {
switch action {
case .sendRtt(message: let message, isFinal: let isFinal):
actionHandler.sendRttMessage(message: message, isFinal: isFinal)
default:
break
}
}