React Native provider, hooks, and pre-built UI components for Hiyve video conferencing.
Provides HiyveRNProvider with 18 hooks and 5 components covering the core mobile video calling experience: video tiles, grid layout, control bar, participant list, and waiting room.
npm install @hiyve/rn-react @hiyve/rn-core @hiyve/rtc-client-rn react-native-webrtc react-native-safe-area-context @react-native-vector-icons/material-design-icons
After installing, link the native pods:
cd ios && pod install
The ControlBar component uses Material Design Icons. You must register the font in your Info.plist:
UIAppFonts
MaterialDesignIcons.ttf
Without this entry, icons will render as "?" placeholders. CocoaPods copies the font file into your app bundle automatically, but iOS requires UIAppFonts to load it at runtime.
No additional setup needed — the font is bundled automatically via Gradle.
import React from 'react';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import {
HiyveRNProvider,
useConnection,
useLocalMedia,
useParticipants,
VideoGrid,
ControlBar,
} from '@hiyve/rn-react';
const options = {
generateRoomToken: async () => {
const res = await fetch('https://your-api.com/token', { method: 'POST' });
return res.json();
},
onError: (err) => console.error('Hiyve:', err.message),
};
function VideoRoom() {
const { isConnected, createRoom, leaveRoom } = useConnection();
const { isAudioMuted, isVideoMuted, localStream, toggleAudio, toggleVideo, switchCamera } = useLocalMedia();
const { participants, localUserId } = useParticipants();
if (!isConnected) {
return <Button title="Create Room" onPress={() => createRoom('my-room', 'user1')} />;
}
return (
<View style={{ flex: 1 }}>
<VideoGrid
localStream={localStream}
localUserId={localUserId}
isLocalAudioMuted={isAudioMuted}
isLocalVideoMuted={isVideoMuted}
participants={participants}
/>
<ControlBar
isAudioMuted={isAudioMuted}
isVideoMuted={isVideoMuted}
onToggleAudio={toggleAudio}
onToggleVideo={toggleVideo}
onFlipCamera={switchCamera}
onLeave={leaveRoom}
/>
</View>
);
}
export default function App() {
return (
<SafeAreaProvider>
<HiyveRNProvider options={options}>
<VideoRoom />
</HiyveRNProvider>
</SafeAreaProvider>
);
}
Wrap your app (or the screen that uses video) with the provider:
<HiyveRNProvider options={options}>
<YourApp />
</HiyveRNProvider>
| Prop | Type | Description |
|---|---|---|
options |
HiyveStoreRNOptions |
Required. Store configuration with generateRoomToken callback |
children |
ReactNode |
Child components |
All hooks must be used within a HiyveRNProvider.
Connection state and room management.
| Return | Type | Description |
|---|---|---|
isConnected |
boolean |
Whether connected to the server |
isConnecting |
boolean |
Whether a connection attempt is in progress |
error |
string | null |
Error message if connection failed |
createRoom |
(name, userId, opts?) => Promise |
Create a new room as host |
joinRoom |
(name, userId) => Promise |
Join an existing room |
leaveRoom |
() => Promise |
Leave room and disconnect |
Room info and ownership.
| Return | Type | Description |
|---|---|---|
room |
RoomInfo | null |
Current room info |
isOwner |
boolean |
Whether the local user is the host |
isInRoom |
boolean |
Whether the user is in a room |
Remote participants in the room.
| Return | Type | Description |
|---|---|---|
participants |
Participant[] |
Array of all participants |
participantsMap |
Map<string, Participant> |
Map for direct lookup |
localUserId |
string | null |
Local user's ID |
participantCount |
number |
Total participant count |
Single participant lookup.
| Return | Type | Description |
|---|---|---|
| (value) | Participant | undefined |
The participant, or undefined |
Local media state and controls (RN-extended).
| Return | Type | Description |
|---|---|---|
isAudioMuted |
boolean |
Microphone muted |
isVideoMuted |
boolean |
Camera off |
isOutputMuted |
boolean |
Speaker muted |
isScreenSharing |
boolean |
Always false (not supported in RN) |
localStream |
MediaStream | null |
Local camera stream for RTCView |
toggleAudio |
() => Promise |
Toggle mic mute |
toggleVideo |
() => Promise |
Toggle camera |
switchCamera |
() => Promise |
Flip front/back camera |
Convenience hook returning just the local MediaStream.
const stream = useLocalStream();
Recording state with auto-incrementing duration.
| Return | Type | Description |
|---|---|---|
isRecording |
boolean |
Recording active |
isRecordingStarting |
boolean |
Recording starting |
recordingDuration |
number |
Elapsed seconds |
startRecording |
(opts?) => Promise<boolean> |
Start recording |
stopRecording |
() => Promise |
Stop recording |
Live streaming state with duration.
| Return | Type | Description |
|---|---|---|
isStreaming |
boolean |
Streaming active |
streamingDuration |
number |
Elapsed seconds |
startStreaming |
(opts?) => Promise |
Start streaming |
stopStreaming |
() => Promise |
Stop streaming |
Real-time transcription.
| Return | Type | Description |
|---|---|---|
isTranscribing |
boolean |
Transcription active |
transcriptions |
TranscriptionEntry[] |
Transcription entries |
startTranscription |
() => Promise<boolean> |
Start transcription |
stopTranscription |
() => Promise |
Stop transcription |
Text chat messaging.
| Return | Type | Description |
|---|---|---|
messages |
ChatMessage[] |
All messages |
unreadCount |
number |
Unread count |
sendMessage |
(content: string) => void |
Send a message |
clearUnread |
() => void |
Reset unread count |
Waiting room management.
| Return | Type | Description |
|---|---|---|
waitingUsers |
WaitingRoomUser[] |
Users waiting (host view) |
isWaitingForAdmission |
boolean |
Waiting to be admitted (guest) |
wasRejected |
boolean |
Was rejected (guest) |
admitUser |
(userId) => Promise |
Admit a user (host) |
rejectUser |
(userId) => Promise |
Reject a user (host) |
Hand raise feature.
| Return | Type | Description |
|---|---|---|
raisedHands |
Map<string, number> |
User IDs with raise timestamps |
toggleHandRaised |
() => Promise |
Toggle local hand |
lowerAllHands |
() => Promise |
Lower all hands (host) |
Layout and dominant speaker.
| Return | Type | Description |
|---|---|---|
dominantSpeaker |
string | null |
Dominant speaker user ID |
setDominant |
(userId) => void |
Set dominant (host) |
Audio feedback detection state.
| Return | Type | Description |
|---|---|---|
feedbackDetected |
boolean |
Whether audio feedback (echo/howl) is currently detected |
Wait-for-host state when joining before the host starts the room.
| Return | Type | Description |
|---|---|---|
isWaiting |
boolean |
Whether waiting for the host |
roomName |
string | null |
Room being waited on |
timeout |
number | null |
Timeout duration in seconds |
elapsedTime |
number |
Seconds spent waiting |
Host-only actions for remotely muting participants. Actions are no-ops when called by a non-owner.
| Return | Type | Description |
|---|---|---|
remoteMuteAudio |
(userId, mute) => Promise |
Mute/unmute a participant's mic |
remoteMuteVideo |
(userId, mute) => Promise |
Mute/unmute a participant's camera |
muteRemoteOutput |
(userId, mute) => Promise |
Mute/unmute a participant's speaker |
Escape hatch for accessing the raw store and client instances. Prefer the typed hooks for most cases.
| Return | Type | Description |
|---|---|---|
store |
HiyveStoreRN |
The store instance |
client |
Client | null |
The underlying RN WebRTC client |
Android/iOS permission requests.
| Return | Type | Description |
|---|---|---|
granted |
boolean |
Permissions granted |
denied |
boolean |
Permissions denied |
requesting |
boolean |
Request in progress |
requestPermissions |
() => Promise<boolean> |
Request camera + mic |
Renders a participant's video using RTCView, with avatar fallback and mute indicators.
<VideoTile
stream={participant.videoStream}
userId={participant.userId}
displayName="Alice"
isAudioMuted={participant.isAudioMuted}
isVideoMuted={participant.isVideoMuted}
/>
| Prop | Type | Default | Description |
|---|---|---|---|
stream |
MediaStream | null |
— | Video stream to render |
userId |
string |
— | User ID (for avatar color) |
displayName |
string |
userId | Display name |
isAudioMuted |
boolean |
false |
Show mute badge |
isVideoMuted |
boolean |
false |
Show avatar instead of video |
isLocal |
boolean |
false |
Mirror video + show "(You)" |
mirror |
boolean |
false |
Mirror the video |
colors |
Partial<VideoTileColors> |
— | Color overrides |
muteIcon |
ReactNode |
— | Custom mute indicator |
width |
number |
fill parent | Tile width |
height |
number |
fill parent | Tile height |
Auto-layout grid for local + remote video tiles.
<VideoGrid
localStream={localStream}
localUserId={localUserId}
localDisplayName="Me"
isLocalAudioMuted={isAudioMuted}
isLocalVideoMuted={isVideoMuted}
participants={participants}
gap={4}
maxColumns={2}
/>
| Prop | Type | Default | Description |
|---|---|---|---|
localStream |
MediaStream | null |
— | Local camera stream |
localUserId |
string | null |
— | Local user's ID |
localDisplayName |
string |
— | Local user's display name |
isLocalAudioMuted |
boolean |
false |
Local audio muted |
isLocalVideoMuted |
boolean |
false |
Local video off |
participants |
Participant[] |
— | Remote participants |
tileColors |
Partial<VideoTileColors> |
— | Colors for all tiles |
muteIcon |
ReactNode |
— | Custom mute icon |
gap |
number |
4 |
Gap between tiles (px) |
maxColumns |
number |
2 |
Maximum columns |
Bottom control bar with mic, camera, flip, and leave buttons.
<ControlBar
isAudioMuted={isAudioMuted}
isVideoMuted={isVideoMuted}
onToggleAudio={toggleAudio}
onToggleVideo={toggleVideo}
onFlipCamera={switchCamera}
onLeave={leaveRoom}
/>
| Prop | Type | Default | Description |
|---|---|---|---|
isAudioMuted |
boolean |
— | Microphone state |
isVideoMuted |
boolean |
— | Camera state |
onToggleAudio |
() => void |
— | Mic toggle handler |
onToggleVideo |
() => void |
— | Camera toggle handler |
onFlipCamera |
() => void |
— | Camera flip handler |
onLeave |
() => void |
— | Leave handler |
colors |
Partial<ControlBarColors> |
— | Color overrides |
labels |
Partial<ControlBarLabels> |
— | Label overrides |
icons |
{ mic?, micOff?, camera?, ... } |
— | Custom icon elements |
safeArea |
boolean |
true |
Apply safe area padding |
Reusable circular button used inside the ControlBar. Can also be used standalone to build custom control bar layouts.
<ControlBarButton
icon={<Icon name="microphone" size={24} color="#fff" />}
label="Mute"
onPress={toggleAudio}
backgroundColor="#333"
textColor="#fff"
/>
| Prop | Type | Default | Description |
|---|---|---|---|
icon |
ReactNode |
-- | Icon element to render |
label |
string |
-- | Button label text |
onPress |
() => void |
-- | Press handler |
backgroundColor |
string |
-- | Button background color |
textColor |
string |
-- | Label text color |
disabled |
boolean |
false |
Disable the button |
Small badge showing a pulsing dot, a label, and a formatted timer. Used to indicate active recording or streaming.
<DurationBadge duration={recordingDuration} label="REC" />
<DurationBadge duration={streamingDuration} label="LIVE" backgroundColor="#22c55e" />
| Prop | Type | Default | Description |
|---|---|---|---|
duration |
number |
-- | Duration in seconds |
label |
string |
-- | Badge label (e.g. "REC", "LIVE") |
backgroundColor |
string |
'#ef4444' |
Badge background color |
pulseColor |
string |
'#ffffff' |
Pulsing dot color |
Scrollable list of participants with avatar, name, and status.
<ParticipantList
participants={participants}
localUserId={localUserId}
ownerId={room?.owner}
/>
| Prop | Type | Default | Description |
|---|---|---|---|
participants |
Participant[] |
— | Participants to display |
localUserId |
string | null |
— | Local user ID (shows "You") |
ownerId |
string |
— | Host user ID (shows "Host" badge) |
colors |
Partial<ParticipantListColors> |
— | Color overrides |
labels |
Partial<ParticipantListLabels> |
— | Label overrides |
showHeader |
boolean |
true |
Show title with count |
Dual-mode waiting room for guests and hosts.
Guest mode — shows a waiting spinner or rejection message:
<WaitingRoom
mode="guest"
isWaitingForAdmission={isWaitingForAdmission}
wasRejected={wasRejected}
onGoBack={() => navigation.goBack()}
/>
Host mode — shows list of waiting users with admit/reject buttons:
<WaitingRoom
mode="host"
waitingUsers={waitingUsers}
onAdmitUser={admitUser}
onRejectUser={rejectUser}
/>
| Prop | Type | Default | Description |
|---|---|---|---|
mode |
'guest' | 'host' |
— | Render mode |
waitingUsers |
WaitingRoomUser[] |
[] |
Users waiting (host mode) |
isWaitingForAdmission |
boolean |
false |
Waiting state (guest mode) |
wasRejected |
boolean |
false |
Rejected state (guest mode) |
onAdmitUser |
(userId) => void |
— | Admit handler (host mode) |
onRejectUser |
(userId) => void |
— | Reject handler (host mode) |
onGoBack |
() => void |
— | Back handler (guest rejected) |
colors |
Partial<WaitingRoomColors> |
— | Color overrides |
labels |
Partial<WaitingRoomLabels> |
— | Label overrides |
Requests camera and microphone permissions from the OS. On Android, prompts via the native permission dialog. On iOS, returns true immediately since react-native-webrtc handles prompts automatically on first access. For a reactive hook-based API, use usePermissions instead.
import { requestCameraAndMicPermissions } from '@hiyve/rn-react';
const granted = await requestCameraAndMicPermissions();
if (!granted) {
Alert.alert('Permissions required', 'Camera and microphone access are needed.');
}
| Returns | Description |
|---|---|
Promise<boolean> |
true if both camera and microphone permissions are granted |
All components accept colors, labels, and icons props. Pass partial objects to override only what you need:
<ControlBar
colors={{
background: '#1e1e3f',
leaveBackground: '#dc2626',
}}
labels={{
mute: 'Stummschalten',
unmute: 'Mikrofon ein',
leave: 'Verlassen',
}}
icons={{
mic: <Icon name="microphone" size={24} color="#fff" />,
micOff: <Icon name="microphone-off" size={24} color="#fff" />,
}}
// ... other props
/>
react-native-webrtc >= 118.0.0react-native-safe-area-context >= 4.0.0@react-native-vector-icons/material-design-icons >= 12.0.0@hiyve/rn-core@hiyve/rtc-client-rn
Hiyve React Native SDK.
Provides React hooks and components for building real-time communication apps with React Native. Wrap your app in HiyveRNProvider, then use hooks like useConnection, useRoom, useLocalMedia, and useParticipants to manage meetings.
Example