Floor Access Control
Floor access control is used in moderated sessions (typically lecture or webinar modes) where participants must request permission before they can speak or share their camera. The moderator grants or denies each request, and can also revoke access once it has been granted. The React Native SDK provides a full set of methods and callbacks for implementing this flow on both the participant and moderator side.
In a moderated session, participants join without the ability to publish audio or video. Floor access is the permission gate that controls who may speak at any given time. Understanding the full flow for both sides — participant and moderator — is essential before wiring up any individual method.
From the participant's side
- Participant taps "Raise Hand" → calls
Enx.requestFloor(). - The moderator sees the incoming request via the
floorRequestedcallback, which includes the requester'sclientIdandname. - The moderator either grants or denies the request. The participant receives
grantedFloorordeniedFlooraccordingly. - If granted, the participant can now publish their audio/video stream.
- When the participant finishes speaking, they call
Enx.finishFloor()to voluntarily release the floor.
From the moderator's side
- Incoming hand-raise requests arrive via the
floorRequestedcallback. - The moderator calls
Enx.grantFloor(clientId)to approve orEnx.denyFloor(clientId)to reject each request. - Optionally, the moderator can proactively invite a participant to speak with
Enx.inviteToFloor(clientId), without waiting for a hand-raise. - To cut off an active speaker, the moderator calls
Enx.releaseFloor(clientId).
The SDK also maintains two lists that are especially useful when a participant or moderator reconnects mid-session:
room.raisedHands— participants with pending floor requests.room.approvedHands— participants currently holding floor access.
group (non-moderated), all participants can publish freely and none of the methods on this page will have any effect.
A participant calls Enx.requestFloor() to raise their hand and notify the moderator that they would like permission to speak. This method does not grant access directly — it sends a request that the moderator must act on.
The method triggers two callbacks: one delivered to the moderator (carrying the requester's identity) and one delivered back to the requesting participant as an acknowledgement that the request was received.
// Participant raises their hand to request the floor
Enx.requestFloor();
Callbacks
| Callback | Who receives it | When it fires |
|---|---|---|
floorRequested |
Moderator | A participant requested the floor. Payload includes the requester's clientId and name. |
ackRequestFloor |
Requesting participant | Acknowledgement that the floor request was received by the server. |
On the participant side, handle ackRequestFloor to update the UI to a "waiting for approval" state:
const eventHandlers = {
ackRequestFloor: (data) => {
// Request was received — show pending state in the UI
this.setState({ floorStatus: 'pending' });
}
};
After raising their hand, a participant may decide to withdraw the request before the moderator has responded. Enx.cancelFloor() retracts the pending request and notifies the SDK so the moderator's queue is updated.
// Participant lowers their hand before the moderator responds
Enx.cancelFloor();
Callbacks
| Callback | When it fires |
|---|---|
floorCancelled |
The floor request was successfully cancelled and removed from the moderator's queue. |
Once a participant has been granted the floor and has finished speaking, they should call Enx.finishFloor() to voluntarily release the floor back to the moderator. This is the polite, participant-initiated way to end their speaking turn — as opposed to the moderator forcibly revoking access with releaseFloor().
When finishFloor() is called, the participant's publishing permission is revoked, and the moderator is notified that the floor is available again.
// Participant signals that they have finished speaking
Enx.finishFloor();
Callbacks
| Callback | When it fires |
|---|---|
floorFinished |
Floor released. The participant's publishing permission is revoked and the moderator is notified. |
When the moderator receives a floorRequested callback, they can approve the request by calling Enx.grantFloor(clientId) with the requesting participant's client ID. This gives that participant permission to publish their audio and video streams.
The typical pattern is to show an approval UI in the floorRequested handler — displaying the participant's name and two action buttons — and then call grantFloor() when the moderator taps approve.
const eventHandlers = {
floorRequested: (data) => {
// data.clientId — the requester's ID
// data.name — the requester's display name
console.log('Floor request from:', data.name);
// Show approval UI, then on moderator tap:
Enx.grantFloor(data.clientId);
}
};
Callbacks
| Callback | Who receives it | When it fires |
|---|---|---|
grantedFloor |
Approved participant | Permission granted. The participant may now publish their stream. |
ackGrantFloor |
Moderator | Confirmation that the grant was successfully applied by the server. |
grantedFloor on the participant side to trigger stream publishing. Do not begin publishing before this callback fires — the server enforces the permission gate.
The moderator calls Enx.denyFloor(clientId) to reject a participant's floor request. The denied participant is notified via the deniedFloor callback so their UI can return to the default state (hand lowered, no pending request).
const eventHandlers = {
floorRequested: (data) => {
console.log('Floor request from:', data.name);
// Deny the request
Enx.denyFloor(data.clientId);
}
};
Callbacks
| Callback | Who receives it | When it fires |
|---|---|---|
deniedFloor |
Denied participant | The floor request was rejected. The participant's hand-raise state is cleared. |
ackDenyFloor |
Moderator | Confirmation that the denial was successfully applied by the server. |
The moderator calls Enx.releaseFloor(clientId) to forcibly revoke a participant's currently active floor access. This is different from a participant voluntarily finishing their turn — here, the moderator is cutting off an active speaker. Use this when a participant is speaking for too long, the session needs to move on, or the moderator needs to reclaim order.
All participants in the room receive the floorReleased callback, which lets every client update its UI to reflect that the speaker has been removed.
// Moderator revokes an active speaker's floor access
Enx.releaseFloor(clientId);
Callbacks
| Callback | Who receives it | When it fires |
|---|---|---|
floorReleased |
All participants | The moderator revoked the speaker's floor access. All clients should update their speaker UI. |
ackReleaseFloor |
Moderator | Confirmation that the release was successfully applied by the server. |
Rather than waiting for a participant to raise their hand, a moderator can proactively invite a specific participant to speak. This is useful in structured Q&A or panel formats where the moderator controls the speaking order and wants to call on someone directly.
Enx.inviteToFloor(clientId) sends an invitation to the target participant. They receive a notification on their end and can accept or act on it — for example, by automatically beginning to publish, or by prompting the user with an "accept invitation" button.
// Moderator proactively invites a participant to speak
Enx.inviteToFloor(clientId);
Callbacks
| Callback | Who receives it | When it fires |
|---|---|---|
ackInviteToFloorRequested |
Moderator | Acknowledgement that the invitation was successfully sent to the participant. |
inviteToFloorRequested |
Invited participant | The participant receives the moderator's invitation to take the floor. |
invitedForFloorAccess |
Invited participant | The participant has been granted floor access as a result of the invitation. |
On the invited participant's side, handle inviteToFloorRequested to display an "accept" prompt or to automatically begin publishing:
const eventHandlers = {
inviteToFloorRequested: (data) => {
// The moderator has invited this participant to speak
console.log('You have been invited to speak by the moderator');
// Show an "Accept" button, or auto-accept and begin publishing
},
invitedForFloorAccess: (data) => {
// Floor access has been granted via invitation — begin publishing
console.log('Floor access granted via invitation');
}
};
If a participant or moderator reconnects mid-session, the floor access state may have changed while they were disconnected — new hand-raises may have come in, grants may have been issued, or speakers may have finished. Without restoring this state, the moderator's queue could appear empty or stale, leading to a broken experience.
The SDK solves this by including two arrays in the roomConnected payload after a reconnect:
raisedHands— an array of participant objects who currently have pending floor requests.approvedHands— an array of participant objects who currently hold active floor access.
Read both arrays in your roomConnected handler to rebuild the UI correctly as soon as the connection is restored.
const eventHandlers = {
roomConnected: (data) => {
// Restore floor state after a reconnect
const pendingRequests = data.raisedHands || [];
const approvedSpeakers = data.approvedHands || [];
console.log('Pending floor requests:', pendingRequests.length);
console.log('Current speakers:', approvedSpeakers.length);
this.setState({ pendingRequests, approvedSpeakers });
}
};
raisedHands and approvedHands from the roomConnected payload after a reconnect. This prevents the moderator's UI from showing stale or missing floor requests when the connection is restored.