CoGuestState and LiveSeatState to quickly implement voice co-hosting in your application.
CoGuestState and LiveSeatState support these common interaction scenarios:applyForSeat method.import { useCoGuestState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoGuestState';// Get the live room ID (liveID). Usually, select from the room list (can use LiveListState's liveList data)const liveID = "xxx"; // The liveID of the voice room you joined// Get CoGuestState instance for the liveIDconst { applyForSeat } = useCoGuestState(liveID);// User clicks "Request to Co-host"const handleApplyForSeat = () => {applyForSeat({liveID,seatIndex: -1, // Target seat; -1 assigns a random seattimeout: 30, // Timeout, e.g., 30s});};
onGuestApplicationResponded event with addCoGuestGuestListener to get the host’s decision.import { useCoGuestState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoGuestState';import { useDeviceState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/DeviceState';const { addCoGuestGuestListener } = useCoGuestState(liveID);const { openLocalMicrophone } = useDeviceState(liveID);// Subscribe to co-host application response on page initializationuseEffect(() => {addCoGuestGuestListener('onGuestApplicationResponded', (event) => {const res = typeof event === 'string' ? JSON.parse(event) : event;if (res.isAccept) {console.log('Co-host request accepted');// 1. Open microphoneopenLocalMicrophone();// 2. Update UI, e.g., change request button to "Co-hosting"} else {console.log('Co-host request rejected');// Show popup to notify user their request was rejected}});}, [liveID]);
disconnect method to return to audience mode.import { useCoGuestState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoGuestState';const { disconnect } = useCoGuestState(liveID);// User clicks "Leave Mic"const handleLeaveSeat = () => {disconnect({liveID,onSuccess: () => {console.log('Successfully left the mic');},onError: (error) => {console.log('Failed to leave the mic', error);},});};
cancelApplication.import { useCoGuestState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoGuestState';const { cancelApplication } = useCoGuestState(liveID);// User clicks "Cancel Request" while waitingconst handleCancelRequest = () => {cancelApplication({liveID,onSuccess: () => {console.log('Successfully canceled request');},onError: (error) => {console.log('Failed to cancel request', error);},});};
onGuestApplicationReceived event using CoGuestHostListener to get notified as soon as an audience request arrives.import { useCoGuestState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoGuestState';// Get CoGuestState instanceconst { addCoGuestHostListener } = useCoGuestState(liveID);// Subscribe to event on page initializationuseEffect(() => {addCoGuestHostListener('onGuestApplicationReceived', (event) => {const res = JSON.parse(event);console.log('Received co-host request from audience');// Update UI, e.g., show a red dot on the "Request List" button});}, [liveID]);
CoGuestState maintains a real-time applicants list (applicants), which is reactive and can be used directly in your UI.const { addCoGuestHostListener, applicants } = useCoGuestState(liveID);{/* Applicant List */}{applicants && applicants.length > 0 ? (<View style={styles.applicantContainer}><Text style={styles.applicantTitle}>Request List ({applicants.length})</Text>{applicants.map((audience) => (<View key={audience?.userID} style={styles.applicantItem}><Text style={styles.applicantName}>{audience.userName}</Text><Text style={styles.applicantId}>{audience.userID}</Text></View>))}</View>) : null}
import { useCoGuestState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoGuestState';const { acceptApplication, rejectApplication } = useCoGuestState(liveID);// Host clicks "Accept", passing user's userIDconst handleAccept = (userID) => {acceptApplication({liveID,userID,onSuccess: () => {console.log('Co-host request accepted');},onError: (error) => {console.log('Failed to accept co-host request', error);},});};// Host clicks "Reject", passing user's userIDconst handleReject = (userID) => {rejectApplication({liveID,userID,onSuccess: () => {console.log('Co-host request rejected');},onError: (error) => {console.log('Failed to reject co-host request', error);},});};
inviteToSeat method.import { useCoGuestState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoGuestState';const { inviteToSeat } = useCoGuestState(liveID);// Host selects user and sends invitationconst handleInviteToSeat = (inviteeID) => {inviteToSeat({liveID,inviteeID,seatIndex: -1, // Target seat; -1 assigns a random seattimeout: 30, // Invitation timeoutonSuccess: () => {console.log('Invitation sent to audience, awaiting response...');},onError: (error) => {console.log('Failed to send invitation to audience', error);},});};
onHostInvitationResponded event via CoGuestHostListener.import { useCoGuestState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoGuestState';const { addCoGuestHostListener } = useCoGuestState(liveID);// Subscribe on page initializationuseEffect(() => {addCoGuestHostListener('onHostInvitationResponded', (event) => {const res = JSON.parse(event);if (res.isAccept) {console.log('Audience accepted your invitation');} else {console.log('Audience rejected your invitation');}});}, [liveID]);
onHostInvitationReceived event using addCoGuestGuestListener.import { useCoGuestState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoGuestState';import { useLiveListState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/LiveListState';const { addCoGuestGuestListener } = useCoGuestState(liveID);const { currentLive } = useLiveListState();// Listen for co-host invitation on page initializationuseEffect(() => {addCoGuestGuestListener('onHostInvitationReceived', (event) => {const inviterID = currentLive?.liveOwner?.userID || '';console.log('Inviter ID:', inviterID);// Show dialog for user to choose "Accept" or "Reject"});}, [liveID]);
import { useCoGuestState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/CoGuestState';const { acceptInvitation, rejectInvitation } = useCoGuestState(liveID);const { openLocalMicrophone } = useDeviceState(liveID);// User clicks "Accept"const handleAcceptInvitation = (inviterID) => {acceptInvitation({liveID,inviterID,onSuccess: () => {console.log('Accepted co-host invitation');openLocalMicrophone(); // Optionally open microphone here},onError: (error) => {console.log('Failed to accept co-host invitation', error);},});};// User clicks "Reject"const handleRejectInvitation = (inviterID) => {rejectInvitation({liveID,inviterID,onSuccess: () => {console.log('Rejected co-host invitation');},onError: (error) => {console.log('Failed to reject co-host invitation', error);},});};
LiveSeatState and can be used with CoGuestState.LiveSeatState.muteMicrophone(). This is a one-way request with no callback.unmuteMicrophone(onSuccess: onError:).import { useLiveSeatState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/LiveSeatState';const { muteMicrophone, unmuteMicrophone } = useLiveSeatState(liveID);// Muteconst handleMuteMic = () => {muteMicrophone();};// Unmuteconst handleUnmuteMic = () => {unmuteMicrophone({onSuccess: () => {console.log('Unmute successful');},onError: (error) => {console.log('Unmute failed', error);},});};
Parameter | Type | Description |
onSuccess | Function | Callback for successful unmute. |
onError | Function | Callback for unmute failure. |
closeRemoteMicrophone to forcibly mute and lock the user's microphone. The muted user receives the 'onLocalMicrophoneClosedByAdmin' event and their "Open Microphone" button becomes unclickable.openRemoteMicrophone, which unlocks mic permissions without unmuting. The user receives the onLocalMicrophoneOpenedByAdmin event, their "Open Microphone" button is enabled, and they must manually unmute.LiveSeatState's unmuteMicrophone() to unmute.import { useLiveSeatState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/LiveSeatState';const { openRemoteMicrophone, closeRemoteMicrophone } = useLiveSeatState(liveID);const targetUserID = "userA";// 1. Force mute userA and lockconst handleCloseRemoteMic = (userID) => {closeRemoteMicrophone({liveID,userID,onSuccess: () => {console.log('Mute and lock successful');},onError: (error) => {console.log('Mute and lock failed', error);},});};// 2. Unlock userA’s microphone permissions (userA remains muted)const handleOpenRemoteMic = (userID) => {openRemoteMicrophone({liveID,userID,onSuccess: () => {console.log('Invite to unmute successful');},onError: (error) => {console.log('Invite to unmute failed', error);},});};
import { useLiveSeatState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/LiveSeatState';const { addLiveSeatEventListener } = useLiveSeatState(liveID);// Listen for host’s mute/unlock actionsuseEffect(() => {addLiveSeatEventListener('onLocalMicrophoneClosedByAdmin', () => {console.log('Muted by host');// Show popup notification here});addLiveSeatEventListener('onLocalMicrophoneOpenedByAdmin', () => {console.log('Host unlocked mute');// Show popup notification here});}, [liveID]);
Parameter | Type | Description |
liveID | string | The current voice room's liveID. |
userID | string | The operated user's userID. |
onSuccess | Function | Callback for successful mute. |
onError | Function | Callback for mute failure. |
Parameter | Type | Description |
liveID | string | The current voice room's liveID. |
userID | string | The operated user's userID. |
onSuccess | Function | Callback for successful unlock. |
onError | Function | Callback for unlock failure. |
kickUserOutOfSeat to remove a user from a seat.onKickedOffSeat notification.import { useLiveSeatState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/LiveSeatState';const { kickUserOutOfSeat, addLiveSeatEventListener } = useLiveSeatState(liveID);// Kick userB off micconst targetUserID = "userB";const handleKickUserOutOfSeat = (userID) => {kickUserOutOfSeat({liveID: liveID,userID: userID,onSuccess: () => {console.log('Successfully kicked off the seat');},onError: (error) => {console.log('Failed to kick user', error);},});};useEffect(() => {addLiveSeatEventListener('onKickedOffSeat', () => {console.log('Kicked off the mic by host');// Show popup notification here});}, [liveID]);
Parameter | Type | Description |
liveID | string | The current voice room's liveID. |
userID | string | The userID of the user being kicked off the mic. |
onSuccess | Function | Callback for successful kick. |
onError | Function | Callback for kick failure. |
lockSeat to lock a seat at a given index. Once locked, audience members cannot join that seat with applyForSeat or takeSeat.unlockSeat to make the seat available again.import { useLiveSeatState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/LiveSeatState';const { lockSeat, unlockSeat } = useLiveSeatState(liveID);// Lock seat 2const handleLockSeat = () => {lockSeat({liveID: liveID,seatIndex: 2,onSuccess: () => {console.log(`Seat 2 locked`);},onError: (error) => {console.log('Failed to lock seat', error);},});};// Unlock seat 2const handleUnlockSeat = () => {unlockSeat({liveID: liveID,seatIndex: 2,onSuccess: () => {console.log('Seat 2 unlocked');},onError: (error) => {console.log('Failed to unlock seat', error);},});};
Parameter | Type | Description |
liveID | string | The current voice room's liveID. |
seatIndex | number | Index of the seat to lock. |
onSuccess | Function | Callback for successful lock. |
onError | Function | Callback for lock failure. |
Parameter | Type | Description |
liveID | string | The current voice room's liveID. |
seatIndex | number | Index of the seat to unlock. |
onSuccess | Function | Callback for successful unlock. |
onError | Function | Callback for unlock failure. |
moveUserToSeat to move users between seats.userID is the target user, targetIndex is the target seat, and policy specifies the strategy if the target seat is occupied. See method parameters for details.userID must be their own, targetIndex is the new seat, and policy is ignored. If the target seat is occupied, an error is returned and the move is aborted.import { useLiveSeatState } from 'react-native-tuikit-atomic-x/lib/module/atomic-x/state/LiveSeatState';const { moveUserToSeat } = useLiveSeatState(liveID);const newSeatIndex = 2; // Target seat index.const moveSeat = () => {moveUserToSeat({liveID: liveID,userID: "userC",targetIndex: newSeatIndex, // Target seatpolicy: 'FORCE_REPLACE',onSuccess: () => {console.log('Seat moved successfully');},onError: (error) => {console.log('Seat move failed', error);}});};
Parameter | Type | Description |
userID | string | The userID of the user to move. |
targetIndex | number | Target seat index. |
policy | string | Move strategy enum when target seat is occupied: ABORT_WHEN_OCCUPIED: Abort move if target seat is occupied (default)FORCE_REPLACE: Force replace the user on the target seat; replaced user will be removedSWAP_POSITION: Swap positions with the user on the target seat. |
onSuccess | Function | Callback for successful seat move. |
onError | Function | Callback for seat move failure. |
State | Function Description | API Documentation |
CoGuestState | Audience co-host management: co-host requests, invitations, accept/reject, member permission control (microphone/camera), state synchronization. | |
LiveSeatState | Seat management: mute/unmute, lock/unlock seat, remove user from mic, remote microphone control, listen to seat list state changes. |
LiveCoreView to render the host and co-host audience video streams. The UI focuses on video layout, sizing, and overlays (nicknames, placeholders). Both camera and microphone are typically enabled.LiveSeatState data (especially seatList). The focus is on real-time display of each seat's SeatInfo: occupied, muted, locked, or speaking. Only the microphone is used.seatList property in LiveSeatState, which is a reactive [SeatInfo] array. Any change triggers a UI update. Iterate through this array to:seatInfo.userInfo to get the user for each seat.seatInfo.isLocked to check if the seat is locked.seatInfo.userInfo.microphoneStatus to get the mic user’s microphone status.DeviceState manages the physical device; LiveSeatState manages seat-level business logic (audio stream).openLocalMicrophone: Requests system permissions and starts the microphone for audio capture (a "heavy" operation).closeLocalMicrophone: Stops audio capture and releases the microphone.muteMicrophone: Mutes, stopping the local audio stream from being sent. The microphone device stays running.unmuteMicrophone: Unmutes, resuming audio stream transmission.openLocalMicrophone once.muteMicrophone and unmuteMicrophone for all mute/unmute actions while on the seat.피드백