RoomParticipantStore is a specialized module within AtomicXCore designed for managing participants in a conference room. It provides essential functionality for multi-party conference scenarios, enabling you to build a robust participant management system.
RoomParticipantStore is summarized as follows:Core Concept | Type | Core Responsibilities & Description |
struct | Represents the participant data model, encapsulating participant information and state management. Main functions include managing participant basic information (user ID, user name, user avatar, in-room role) and managing device status (microphone, camera, screen sharing, message status). | |
struct | Represents the participant state management structure, responsible for maintaining participant-related state information in the room. Main properties: participantListcollection of all participant information in the current room.participantListCursorsnapshot for paginated participant list.localParticipantcurrent user's participant information in the room. | |
enum | Represents real-time participant events in the room. Main categories: participant join/leave, role changes, device control events. | |
class | Core class for participant control. Features: manage participant audio/video status, perform participant operations, receive real-time events via participantEventPublisher. |
getParticipantList method in RoomParticipantStore to fetch the participant list.import Foundationimport AtomicXCorefunc getParticipantList() {// Prerequisite: You must have joined the room and initialized RoomParticipantStore with roomIDlet participantStore = RoomParticipantStore.create(roomID: "your_room_id")// Retrieve participant list starting from the first pagelet initialCursor: String? = nil // nil means fetch from the first pageparticipantStore.getParticipantList(cursor: initialCursor) { result inswitch result {case .success(let participantInfo):print("Participant list retrieved, count: \\(participantInfo.0.count)")case .failure(let error):print("Failed to get participant list [Error code: \\(error.code)]: \\(error.message)")}}}
searchUsers to search for members by keyword.import Foundationimport AtomicXCorefunc searchUsers() {// Prerequisite: You must have joined the room.let participantStore = RoomParticipantStore.create(roomID: "your_room_id")// Search by user name keywordlet keyword = "userName"participantStore.searchUsers(keyword: keyword) { result inswitch result {case .success(let usersInfo):print("Room members found, count: \\(usersInfo.0.count)")case .failure(let error):print("Failed to search room members [Error code: \\(error.code)]: \\(error.message)")}}}
transferOwner to transfer ownership to any participant. The original owner becomes a regular participant; each room can have only one owner.import Foundationimport AtomicXCorefunc transferOwner(to userID: String) {// Prerequisite: You must have joined the room and initialized RoomParticipantStore with roomIDlet participantStore = RoomParticipantStore.create(roomID: "your_room_id")// Only the current owner can transfer ownershipparticipantStore.transferOwner(userID: userID) { result inswitch result {case .success():print("Ownership transferred. New owner: \\(userID)")case .failure(let error):print("Ownership transfer failed [Error code: \\(error.code)]: \\(error.message)")}}}
onOwnerChanged event via participantEventPublisher to receive ownership change notifications.import Foundationimport AtomicXCoreimport Combineprivate var cancellableSet = Set<AnyCancellable>()private func subscribeParticipantEvent() {let participantStore = RoomParticipantStore.create(roomID: "your_room_id")participantStore.participantEventPublisher.receive(on: DispatchQueue.main).sink { event inswitch event {case .onOwnerChanged(let newOwner, let oldOwner):print("Ownership changed: newOwner: \\(newOwner), oldOwner: \\(oldOwner)")default: break}}.store(in: &cancellableSet)}
setAdmin to assign admin privileges or revokeAdmin to remove them.import Foundationimport AtomicXCorelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")func setUserAsAdmin(userID: String) {participantStore.setAdmin(userID: userID) { result inswitch result {case .success:print("User \\(userID) set as admin")case .failure(let error):print("Failed to set admin [Error code: \\(error.code)]: \\(error.message)")}}}func revokeUserAdmin(userID: String) {participantStore.revokeAdmin(userID: userID) { result inswitch result {case .success:print("Admin privileges revoked for user \\(userID)")case .failure(let error):print("Failed to revoke admin [Error code: \\(error.code)]: \\(error.message)")}}}
onAdminSet and onAdminRevoked events to be notified of changes.import Foundationimport AtomicXCorelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")private var cancellableSet = Set<AnyCancellable>()private func subscribeParticipantEvents() {participantStore.participantEventPublisher.receive(on: DispatchQueue.main).sink { event inswitch event {case .onAdminSet(let userInfo):print("Admin assigned: \\(userInfo)")case .onAdminRevoked(let userInfo):print("Admin revoked: \\(userInfo)")default: break}}.store(in: &cancellableSet)}
kickUser to remove participants from the room.import Foundationimport AtomicXCorelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")func kickUser(userID: String) {// Only owners and admins have permissionparticipantStore.kickUser(userID: userID) { result inswitch result {case .success():print("User \\(userID) removed from room")case .failure(let error):print("Failed to remove user [Error code: \\(error.code)]: \\(error.message)")}}}
onKickedFromRoom event to receive removal notifications.import Foundationimport AtomicXCoreimport Combinelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")private var cancellableSet = Set<AnyCancellable>()private func subscribeParticipantEvent() {participantStore.participantEventPublisher.receive(on: DispatchQueue.main).sink { event inswitch event {case .onKickedFromRoom(let reason, let message):print("Removed from room: reason: \\(reason), info: \\(message)")default:break}}.store(in: &cancellableSet)}
updateParticipantNameCard and updateParticipantMetaData to update your information, including display name and custom metadata.import Foundationimport AtomicXCorelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")func updateParticipantNameCard(userID: String, nameCard: String) {// Display name or custom identifier// Usually only admins or the participant themselves can modifyparticipantStore.updateParticipantNameCard(userID: userID, nameCard: nameCard) { result inswitch result {case .success():print("Name card updated: user \\(userID), new value: \\(nameCard)")case .failure(let error):print("Failed to update name card [Error code: \\(error.code)]: \\(error.message)")}}}func updateParticipantMetaData(userID: String, metaData: [String: String]) {// Custom business data such as tags or extended attributes// Key length ≤ 50 bytes, value length ≤ 200 bytesparticipantStore.updateParticipantMetaData(userID: userID, metaData: metaData) { result inswitch result {case .success():print("Custom metadata updated: user \\(userID), keys: \\(metaData.count)")case .failure(let error):print("Failed to update metadata [Error code: \\(error.code)]: \\(error.message)")}}}
inviteToOpenDevice to prompt participants to turn on their camera or microphone.import Foundationimport AtomicXCorelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")func inviteUserToOpenDevice(userID: String, device: DeviceType, timeout: Int = 30) {// Invite participant to enable device (microphone, camera, screen sharing)// Participants receive a notification and can accept or declineparticipantStore.inviteToOpenDevice(userID: userID, device: device, timeout: timeout) { result inswitch result {case .success():print("Device invitation sent: user \\(userID), device: \\(device)")case .failure(let error):print("Failed to send invitation [Error code: \\(error.code)]: \\(error.message)")}}}
onDeviceInvitationReceived for device invitation notifications.acceptOpenDeviceInvitation or declineOpenDeviceInvitation to accept or decline.import Foundationimport AtomicXCoreimport Combinelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")private var cancellableSet = Set<AnyCancellable>()private func subscribeDeviceInvitationEvent() {participantStore.participantEventPublisher.receive(on: DispatchQueue.main).sink { event inswitch event {case .onDeviceInvitationReceived(let invitation):print("Device invitation received: device: \\(invitation.device), sender: \\(invitation.senderUserName)")// Handle accept/declinedefault: break}}.store(in: &cancellableSet)}func acceptOpenDeviceInvitation(userID: String, device: DeviceType) {participantStore.acceptOpenDeviceInvitation(userID: userID, device: device) { result inswitch result {case .success():print("Device invitation accepted: \\(device)")case .failure(let error):print("Failed to accept invitation [Error code: \\(error.code)]: \\(error.message)")}}}func declineOpenDeviceInvitation(userID: String, device: DeviceType) {participantStore.declineOpenDeviceInvitation(userID: userID, device: device) { result inswitch result {case .success():print("Device invitation declined: \\(device)")case .failure(let error):print("Failed to decline invitation [Error code: \\(error.code)]: \\(error.message)")}}}
closeParticipantDevice to remotely disable a participant's camera or microphone.import Foundationimport AtomicXCorelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")func closeParticipantDevice(userID: String, device: DeviceType) {// Remotely disable specified participant’s deviceparticipantStore.closeParticipantDevice(userID: userID, device: device) { result inswitch result {case .success():print("Closed device: user \\(userID), device: \\(device)")case .failure(let error):print("Failed to close device [Error code: \\(error.code)]: \\(error.message)")}}}
onParticipantDeviceClosed event to receive device closure notifications.import Foundationimport AtomicXCoreimport Combinelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")private var cancellableSet = Set<AnyCancellable>()private func subscribeDeviceClosedEvent() {participantStore.participantEventPublisher.receive(on: DispatchQueue.main).sink { event inswitch event {case .onParticipantDeviceClosed(let device, let operatorUser):print("Device closed: \\(device), operator: \\(operatorUser.userName)")default:break}}.store(in: &cancellableSet)}
requestToOpenDevice to ask the owner or admins for permission to enable their camera or microphone when restricted.import Foundationimport AtomicXCorelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")func requestToOpenDevice(device: DeviceType, timeout: Int = 30) {// Request to enable deviceparticipantStore.requestToOpenDevice(device: device, timeout: timeout) { result inswitch result {case .success():print("Enable device request sent: \\(device)")case .failure(let error):print("Failed to send request [Error code: \\(error.code)]: \\(error.message)")}}}
onDeviceRequestReceived for device enable requests.approveOpenDeviceRequest or rejectOpenDeviceRequest to approve or deny.import Foundationimport AtomicXCoreimport Combinelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")private var cancellableSet = Set<AnyCancellable>()private func subscribeDeviceRequestEvent() {participantStore.participantEventPublisher.receive(on: DispatchQueue.main).sink { event inswitch event {case .onDeviceRequestReceived(let request):print("Device request received: user \\(request.senderUserName), device: \\(request.device)")// Approve or reject requestdefault:break}}.store(in: &cancellableSet)}func approveOpenDeviceRequest(device: DeviceType, userID: String) {participantStore.approveOpenDeviceRequest(device: device, userID: userID) { result inswitch result {case .success():print("Device request approved: user \\(userID), device: \\(device)")case .failure(let error):print("Failed to approve request: \\(error.message)")}}}func rejectOpenDeviceRequest(device: DeviceType, userID: String) {participantStore.rejectOpenDeviceRequest(device: device, userID: userID) { result inswitch result {case .success():print("Device request rejected: user \\(userID), device: \\(device)")case .failure(let error):print("Failed to reject request [Error code: \\(error.code)]: \\(error.message)")}}}
disableAllDevices to mute all microphones or disable all cameras in the room. Participants will not be able to enable these devices unless approved.import Foundationimport AtomicXCorelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")func disableAllDevices(device: DeviceType, disable: Bool) {// Mute/unmute all microphones or disable/enable all camerasparticipantStore.disableAllDevices(device: device, disable: disable) { result inswitch result {case .success():let action = disable ? "Disabled" : "Enabled"print("\\(action) all \\(device) successfully")case .failure(let error):let action = disable ? "Disabled" : "Enabled"print("\\(action) all \\(device) failed [Error code: \\(error.code)]: \\(error.message)")}}}
onAllDevicesDisabled to stay updated on mute-all or disable-all camera actions and synchronize their UI. When restricted, participants must request permission to enable their devices.import Foundationimport AtomicXCoreimport Combinelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")private var cancellableSet = Set<AnyCancellable>()private func subscribeAllDevicesDisabledEvent() {participantStore.participantEventPublisher.receive(on: DispatchQueue.main).sink { event inswitch event {case .onAllDevicesDisabled(let device, let disable, let operatorUser):let action = disable ? "Disabled" : "Enabled"print("All \\(device) have been \\(action) by \\(operatorUser.userName)")default:break}}.store(in: &cancellableSet)}
RoomParticipantEvent for participant join/leave notifications.import Foundationimport AtomicXCoreimport Combinelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")private var cancellableSet = Set<AnyCancellable>()private func subscribeParticipantEvent() {participantStore.participantEventPublisher.receive(on: DispatchQueue.main).sink { event inswitch event {case .onParticipantJoined(let participant):print("Participant joined: \\(participant.userName), ID: \\(participant.userID)")case .onParticipantLeft(let participant):print("Participant left: \\(participant.userName), ID: \\(participant.userID)")default:break}}.store(in: &cancellableSet)}
RoomParticipantState properties, such as tracking users who are currently speaking.import Foundationimport AtomicXCoreimport Combinelet participantStore = RoomParticipantStore.create(roomID: "your_room_id")private var cancellableSet = Set<AnyCancellable>()private func subscribeParticipantState() {participantStore.state.subscribe(StatePublisherSelector(keyPath: \\.speakingUsers)).map { $0 }.removeDuplicates { oldValue, newValue in// Prevent redundant processingreturn oldValue == newValue}.receive(on: DispatchQueue.main).sink { speakingUsers inprint("Speaking users updated: count = \\(speakingUsers.count)")}.store(in: &cancellableSet)}
Store/Component | Description | API Documentation |
RoomParticipantStore | Manage participants in the room: assign admin roles, transfer ownership, retrieve participant list, remove participants, control participant devices (e.g., close, invite to enable camera/microphone), request device enable (e.g., request to enable camera/microphone). |
피드백