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

// // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // import AzureCommunicationCommon import Combine import Foundation protocol AvatarViewManagerProtocol { var updatedId: PassthroughSubject<String?, Never> { get } var avatarStorage: MappedSequence<String, ParticipantViewData> { get } var localParticipantViewData: ParticipantViewData? { get } func set(remoteParticipantViewData: ParticipantViewData, for identifier: CommunicationIdentifier, completionHandler: ((Result<Void, SetParticipantViewDataError>) -> Void)?) func updateStorage(with removedParticipantsIds: [String]) } class AvatarViewManager: AvatarViewManagerProtocol, ObservableObject { var updatedId = PassthroughSubject<String?, Never>() var localParticipantViewData: ParticipantViewData? private let store: Store<AppState, Action> private(set) var avatarStorage = MappedSequence<String, ParticipantViewData>() var cancellables = Set<AnyCancellable>() init(store: Store<AppState, Action>, localParticipantId: CommunicationIdentifier, localParticipantViewData: ParticipantViewData?) { self.store = store self.localParticipantViewData = localParticipantViewData store.$state .receive(on: DispatchQueue.main) .sink { [weak self] state in self?.receive(state: state) }.store(in: &cancellables) guard let participantViewData = localParticipantViewData else { return } avatarStorage.append(forKey: localParticipantId.rawId, value: participantViewData) } private func receive(state: AppState) { guard state.callingState.status == .disconnected || state.errorState.errorCategory == .callState else { return } avatarStorage = MappedSequence<String, ParticipantViewData>() } func updateStorage(with removedParticipantsIds: [String]) { guard avatarStorage.count > 0 else { return } for id in removedParticipantsIds { avatarStorage.removeValue(forKey: id) } } func set(remoteParticipantViewData: ParticipantViewData, for identifier: CommunicationIdentifier, completionHandler: ((Result<Void, SetParticipantViewDataError>) -> Void)? = nil) { let participantsList = store.state.remoteParticipantsState.participantInfoList let idStringValue = identifier.rawId guard participantsList.contains(where: { $0.userIdentifier == idStringValue }) else { completionHandler?(.failure(SetParticipantViewDataError.participantNotInCall)) return } if avatarStorage.value(forKey: idStringValue) != nil { avatarStorage.removeValue(forKey: idStringValue) } avatarStorage.append(forKey: idStringValue, value: remoteParticipantViewData) updatedId.send(idStringValue) objectWillChange.send() completionHandler?(.success(Void())) } }