AzureCommunicationUI/sdk/AzureCommunicationUICalling/Sources/Presentation/Manager/CallStateManager.swift (41 lines of code) (raw):

// // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // import Foundation import Combine protocol CallStateManagerProtocol { func onCompositeExit() } class CallStateManager: CallStateManagerProtocol { private let store: Store<AppState, Action> private let eventsHandler: CallComposite.Events private var previousCallingStatus: CallingStatus? var cancellables = Set<AnyCancellable>() init(store: Store<AppState, Action>, callCompositeEventsHandler: CallComposite.Events) { self.store = store self.eventsHandler = callCompositeEventsHandler store.$state .receive(on: RunLoop.main) .sink { [weak self] state in self?.receive(state) }.store(in: &cancellables) } // to handle race condition where disconnected is notified after exit // fixing race condition requires call state manager to not depend on store state change // the easiest way to handle is to notify state before exit // does not seems to have any side effect as state is compared func onCompositeExit() { receive(self.store.state) } private func receive(_ state: AppState) { let callingStatus = state.callingState.status guard previousCallingStatus != callingStatus else { return } previousCallingStatus = callingStatus updateEventHandler(state.callingState) } private func updateEventHandler(_ callingState: CallingState) { guard let onCallStateChanged = eventsHandler.onCallStateChanged else { return } onCallStateChanged(CallState(rawValue: callingState.status.toCallCompositeCallState().requestString, callEndReasonCode: callingState.callEndReasonCode, callEndReasonSubCode: callingState.callEndReasonSubCode, callId: callingState.callId ?? "")) } }