├── .gitignore ├── .nvmrc ├── DailyPlayground ├── .gitattributes ├── .gitignore ├── .nvmrc ├── .prettierrc.js ├── app.json ├── assets │ ├── camera-off.png │ ├── camera-off@2x.png │ ├── camera-off@3x.png │ ├── camera.png │ ├── camera@2x.png │ ├── camera@3x.png │ ├── close.png │ ├── close@2x.png │ ├── close@3x.png │ ├── error.png │ ├── error@2x.png │ ├── error@3x.png │ ├── icon.png │ ├── leave.png │ ├── leave@2x.png │ ├── leave@3x.png │ ├── logo.png │ ├── logo@2x.png │ ├── logo@3x.png │ ├── mic-off.png │ ├── mic-off@2x.png │ ├── mic-off@3x.png │ ├── mic.png │ ├── mic@2x.png │ └── mic@3x.png ├── index.js ├── metro.config.js ├── package-lock.json ├── package.json ├── src │ ├── CallObjectContext.ts │ ├── api.ts │ ├── components │ │ ├── App │ │ │ └── App.tsx │ │ ├── Button │ │ │ └── Button.tsx │ │ ├── CallMessage │ │ │ └── CallMessage.tsx │ │ ├── CallPanel │ │ │ ├── CallPanel.tsx │ │ │ └── callState.ts │ │ ├── CopyLinkButton │ │ │ └── CopyLinkButton.tsx │ │ ├── Icons │ │ │ ├── ScreenshareIcon.tsx │ │ │ └── index.ts │ │ ├── StartButton │ │ │ └── StartButton.tsx │ │ ├── Tile │ │ │ └── Tile.tsx │ │ ├── Tray │ │ │ └── Tray.tsx │ │ └── TrayButton │ │ │ └── TrayButton.tsx │ ├── theme.ts │ ├── useCallObject.ts │ ├── useMeetingState.ts │ ├── useOrientation.ts │ └── utils.ts └── tsconfig.json ├── README.md ├── debuggerWorker-screenshot.png ├── docsAssets ├── xcode-accounts.png └── xcode-signing.png └── xcode-screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Artifacts from `npm pack` 2 | *.tgz 3 | 4 | # OSX 5 | *.DS_Store 6 | 7 | # Browserstack automated testing 8 | */bs_app_url.txt 9 | DailyPlayground/android/browserstackAPKs/* 10 | 11 | # dev scripts 12 | DailyPlayground/dev_scripts/variables.sh -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 20 -------------------------------------------------------------------------------- /DailyPlayground/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /DailyPlayground/.gitignore: -------------------------------------------------------------------------------- 1 | # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files 2 | 3 | # dependencies 4 | node_modules/ 5 | 6 | # Expo 7 | .expo/ 8 | dist/ 9 | web-build/ 10 | expo-env.d.ts 11 | android/ 12 | ios/ 13 | 14 | # Native 15 | *.orig.* 16 | *.jks 17 | *.p8 18 | *.p12 19 | *.key 20 | *.mobileprovision 21 | 22 | # Metro 23 | .metro-health-check* 24 | 25 | # debug 26 | npm-debug.* 27 | yarn-debug.* 28 | yarn-error.* 29 | 30 | # macOS 31 | .DS_Store 32 | *.pem 33 | 34 | # local env files 35 | .env*.local 36 | 37 | # typescript 38 | *.tsbuildinfo 39 | -------------------------------------------------------------------------------- /DailyPlayground/.nvmrc: -------------------------------------------------------------------------------- 1 | 22.14 2 | -------------------------------------------------------------------------------- /DailyPlayground/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: true, 3 | tabWidth: 2, 4 | useTabs: false, 5 | arrowParens: 'avoid', 6 | bracketSameLine: true, 7 | bracketSpacing: false, 8 | singleQuote: true, 9 | trailingComma: 'all', 10 | }; 11 | -------------------------------------------------------------------------------- /DailyPlayground/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "DailyPlayground", 4 | "slug": "DailyPlayground", 5 | "version": "1.0.0", 6 | "newArchEnabled": true, 7 | "icon": "./assets/icon.png", 8 | "ios": { 9 | "infoPlist": { 10 | "UIBackgroundModes": [ 11 | "voip" 12 | ] 13 | }, 14 | "bitcode": false, 15 | "bundleIdentifier": "co.daily.DailyPlayground" 16 | }, 17 | "plugins": [ 18 | [ 19 | "@daily-co/config-plugin-rn-daily-js", 20 | { 21 | "enableCamera": true, 22 | "enableMicrophone": true, 23 | "enableScreenShare": true 24 | } 25 | ], 26 | [ 27 | "expo-build-properties", 28 | { 29 | "android": { 30 | "minSdkVersion": 24 31 | }, 32 | "ios": { 33 | "deploymentTarget": "15.1" 34 | } 35 | } 36 | ] 37 | ], 38 | "android": { 39 | "package": "co.daily.DailyPlayground" 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /DailyPlayground/assets/camera-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/camera-off.png -------------------------------------------------------------------------------- /DailyPlayground/assets/camera-off@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/camera-off@2x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/camera-off@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/camera-off@3x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/camera.png -------------------------------------------------------------------------------- /DailyPlayground/assets/camera@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/camera@2x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/camera@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/camera@3x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/close.png -------------------------------------------------------------------------------- /DailyPlayground/assets/close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/close@2x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/close@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/close@3x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/error.png -------------------------------------------------------------------------------- /DailyPlayground/assets/error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/error@2x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/error@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/error@3x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/icon.png -------------------------------------------------------------------------------- /DailyPlayground/assets/leave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/leave.png -------------------------------------------------------------------------------- /DailyPlayground/assets/leave@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/leave@2x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/leave@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/leave@3x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/logo.png -------------------------------------------------------------------------------- /DailyPlayground/assets/logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/logo@2x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/logo@3x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/mic-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/mic-off.png -------------------------------------------------------------------------------- /DailyPlayground/assets/mic-off@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/mic-off@2x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/mic-off@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/mic-off@3x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/mic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/mic.png -------------------------------------------------------------------------------- /DailyPlayground/assets/mic@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/mic@2x.png -------------------------------------------------------------------------------- /DailyPlayground/assets/mic@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daily-co/react-native-daily-js-playground/05ab6fefbc1a90d9f15f2087d598cfdd9f20dc3d/DailyPlayground/assets/mic@3x.png -------------------------------------------------------------------------------- /DailyPlayground/index.js: -------------------------------------------------------------------------------- 1 | import {registerRootComponent} from 'expo'; 2 | 3 | // Enable debug logs 4 | /*window.localStorage = window.localStorage || {}; 5 | window.localStorage.debug = '*'; 6 | window.localStorage.getItem = (itemName) => { 7 | console.log('Requesting the localStorage item ', itemName); 8 | return window.localStorage[itemName]; 9 | };*/ 10 | 11 | //Disable webrtc logs 12 | /*import debug from 'debug'; 13 | debug.disable('rn-webrtc:*');*/ 14 | 15 | import App from './src/components/App/App'; 16 | 17 | // registerRootComponent calls AppRegistry.registerComponent('main', () => App); 18 | // It also ensures that whether you load the app in Expo Go or in a native build, 19 | // the environment is set up appropriately 20 | registerRootComponent(App); 21 | -------------------------------------------------------------------------------- /DailyPlayground/metro.config.js: -------------------------------------------------------------------------------- 1 | // Learn more https://docs.expo.io/guides/customizing-metro 2 | const { getDefaultConfig } = require('expo/metro-config'); 3 | 4 | /** @type {import('expo/metro-config').MetroConfig} */ 5 | const config = getDefaultConfig(__dirname); 6 | 7 | module.exports = config; 8 | -------------------------------------------------------------------------------- /DailyPlayground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dailyplayground", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "start": "expo start --dev-client", 7 | "android": "expo run:android --device", 8 | "ios": "expo run:ios --device", 9 | "web": "expo start --web", 10 | }, 11 | "dependencies": { 12 | "@daily-co/config-plugin-rn-daily-js": "0.0.9", 13 | "@daily-co/react-native-daily-js": "^0.77.0", 14 | "@daily-co/react-native-webrtc": "118.0.3-daily.3", 15 | "@react-native-async-storage/async-storage": "^1.24.0", 16 | "@react-native-clipboard/clipboard": "^1.16.2", 17 | "expo": "~53.0.9", 18 | "expo-status-bar": "~2.2.3", 19 | "react": "19.0.0", 20 | "react-native": "^0.79.2", 21 | "react-native-background-timer": "^2.4.1", 22 | "react-native-dropdown-picker": "^5.4.6", 23 | "react-native-get-random-values": "^1.11.0", 24 | "react-native-svg": "^15.12.0" 25 | }, 26 | "devDependencies": { 27 | "@babel/core": "^7.27.3", 28 | "typescript": "^5.8.3", 29 | "@types/react": "~19.0.14" 30 | }, 31 | "private": true 32 | } 33 | -------------------------------------------------------------------------------- /DailyPlayground/src/CallObjectContext.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { DailyCall } from '@daily-co/react-native-daily-js'; 3 | 4 | export default React.createContext(null); 5 | -------------------------------------------------------------------------------- /DailyPlayground/src/api.ts: -------------------------------------------------------------------------------- 1 | const newRoomEndpoint = 2 | 'https://f433xwze36.execute-api.us-west-2.amazonaws.com/default/dailyRnDemoNewCall'; 3 | 4 | /** 5 | * Create a short-lived room for demo purposes. 6 | * 7 | * IMPORTANT: this is purely a "demo-only" API, and *not* how we recommend 8 | * you create rooms in real production code. In your code, we recommend that you: 9 | * - Create rooms by invoking the Daily.co REST API from your own backend server 10 | * (or from the Daily.co dashboard if you're OK with creating rooms manually). 11 | * - Pass an "exp" (expiration) parameter to the Daily.co REST endpoint so you 12 | * don't end up with a huge number of live rooms. 13 | * 14 | * See https://docs.daily.co/reference#create-room for more information on how 15 | * to use the Daily.co REST API to create rooms. 16 | */ 17 | async function createRoom(): Promise<{ url: string }> { 18 | let response = await fetch(newRoomEndpoint); 19 | return await response.json(); 20 | 21 | // Comment out the above and uncomment the below, using your own URL 22 | // return { url: "https://your-domain.daily.co/hello" }; 23 | } 24 | 25 | export default { createRoom }; 26 | -------------------------------------------------------------------------------- /DailyPlayground/src/components/App/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useEffect, useState } from 'react'; 2 | import { 3 | SafeAreaView, 4 | StyleSheet, 5 | StatusBar, 6 | View, 7 | TextInput, 8 | LogBox, 9 | Text, 10 | Image, 11 | TouchableWithoutFeedback, 12 | ScrollView, 13 | } from 'react-native'; 14 | import Daily, { 15 | DailyEvent, 16 | DailyCall, 17 | DailyEventObject, 18 | DailyEventObjectAppMessage, 19 | } from '@daily-co/react-native-daily-js'; 20 | import CallPanel from '../CallPanel/CallPanel'; 21 | import Button from '../Button/Button'; 22 | import StartButton from '../StartButton/StartButton'; 23 | import { logDailyEvent, robotID } from '../../utils'; 24 | import api from '../../api'; 25 | import Tray from '../Tray/Tray'; 26 | import CallObjectContext from '../../CallObjectContext'; 27 | import CopyLinkButton from '../CopyLinkButton/CopyLinkButton'; 28 | import theme from '../../theme'; 29 | import { useOrientation, Orientation } from '../../useOrientation'; 30 | // @ts-ignore 31 | import packageJson from '../../../package.json'; 32 | 33 | declare const global: { HermesInternal: null | {} }; 34 | 35 | // Silence an annoying warning about a harmless require cycle in React Native's 36 | // fetch library. 37 | // See https://github.com/facebook/react-native/issues/23130. 38 | LogBox.ignoreLogs(['Require cycle: node_modules']); 39 | // After upgrading to RN 0.66, app has started to show a warning about the constructor 40 | // of NativeEventEmitter been called with a non-null argument without the required removeListeners. 41 | // See https://github.com/ocetnik/react-native-background-timer/issues/366 42 | // Silencing the warning while It is not fixed by react-native-background-timer 43 | LogBox.ignoreLogs(['new NativeEventEmitter']); 44 | 45 | // Uncomment during development to temporarily intentionally ignore errors, 46 | // preventing the red screen from popping up 47 | // (console as any).reportErrorsAsExceptions = false; 48 | 49 | enum AppState { 50 | Idle, 51 | Creating, 52 | Joining, 53 | Joined, 54 | Leaving, 55 | Error, 56 | } 57 | 58 | const App = () => { 59 | const [appState, setAppState] = useState(AppState.Idle); 60 | const [roomUrl, setRoomUrl] = useState(undefined); 61 | const [roomCreateError, setRoomCreateError] = useState(false); 62 | const [callObject, setCallObject] = useState(null); 63 | const [roomUrlFieldValue, setRoomUrlFieldValue] = useState< 64 | string | undefined 65 | >(undefined); 66 | const orientation = useOrientation(); 67 | 68 | /** 69 | * Uncomment to set up debugging globals. 70 | */ 71 | // useEffect(() => { 72 | // const g = global as any; 73 | // g.Daily = Daily; 74 | // g.callObject = callObject; 75 | // }, [callObject]); 76 | 77 | /** 78 | * Uncomment to attach debugging events handlers. 79 | */ 80 | // useEffect(() => { 81 | // if (!callObject) { 82 | // return; 83 | // } 84 | 85 | // const events: DailyEvent[] = ['loading', 'load-attempt-failed', 'loaded']; 86 | 87 | // for (const event of events) { 88 | // callObject.on(event, logDailyEvent); 89 | // } 90 | 91 | // return () => { 92 | // for (const event of events) { 93 | // callObject.off(event, logDailyEvent); 94 | // } 95 | // }; 96 | // }, [callObject]); 97 | 98 | /** 99 | * Attach lifecycle event handlers. 100 | */ 101 | useEffect(() => { 102 | if (!callObject) { 103 | return; 104 | } 105 | 106 | const events: DailyEvent[] = ['joined-meeting', 'left-meeting', 'error']; 107 | 108 | function handleNewMeetingState(event?: DailyEventObject) { 109 | logDailyEvent(event); 110 | switch (callObject?.meetingState()) { 111 | case 'joined-meeting': 112 | setAppState(AppState.Joined); 113 | break; 114 | case 'left-meeting': 115 | callObject?.destroy().then(() => { 116 | setRoomUrl(undefined); 117 | setCallObject(null); 118 | setAppState(AppState.Idle); 119 | }); 120 | break; 121 | case 'error': 122 | setAppState(AppState.Error); 123 | break; 124 | default: 125 | break; 126 | } 127 | } 128 | 129 | // Use initial state 130 | handleNewMeetingState(); 131 | 132 | // Listen for changes in state 133 | for (const event of events) { 134 | callObject.on(event, handleNewMeetingState); 135 | } 136 | 137 | // Stop listening for changes in state 138 | return function cleanup() { 139 | for (const event of events) { 140 | callObject.off(event, handleNewMeetingState); 141 | } 142 | }; 143 | }, [callObject]); 144 | 145 | /** 146 | * Listen for app messages from other call participants. 147 | * These only show up in the console. 148 | */ 149 | useEffect(() => { 150 | if (!callObject) { 151 | return; 152 | } 153 | 154 | function handleAppMessage(event?: DailyEventObjectAppMessage) { 155 | if (event) { 156 | logDailyEvent(event); 157 | console.log(`received app message from ${event.fromId}: `, event.data); 158 | } 159 | } 160 | 161 | callObject.on('app-message', handleAppMessage); 162 | 163 | return function cleanup() { 164 | callObject.off('app-message', handleAppMessage); 165 | }; 166 | }, [callObject]); 167 | 168 | /** 169 | * Join a call as soon as a callObject is created. 170 | * This effect must happen *after* the event handlers are attached, above. 171 | */ 172 | useEffect(() => { 173 | if (!callObject || !roomUrl) { 174 | return; 175 | } 176 | callObject.join({ url: roomUrl }).catch((_) => { 177 | // Doing nothing here since we handle fatal join errors in another way, 178 | // via our listener attached to the 'error' event 179 | }); 180 | setAppState(AppState.Joining); 181 | }, [callObject, roomUrl]); 182 | 183 | /** 184 | * Create the callObject as soon as we have a roomUrl. 185 | * This will trigger the call starting. 186 | */ 187 | useEffect(() => { 188 | if (!roomUrl) { 189 | return; 190 | } 191 | const newCallObject = Daily.createCallObject({ 192 | /*dailyConfig: { 193 | // Point to a specific version of the call-machine bundle 194 | // @ts-ignore 195 | callObjectBundleUrlOverride: 'https://b.staging.daily.co/call-ui/0a8807ac0fc0147c996b6db8d8b4c17f640dcd47/static/call-machine-object-bundle.js' 196 | }*/ 197 | }); 198 | setCallObject(newCallObject); 199 | }, [roomUrl]); 200 | 201 | /** 202 | * Create a temporary room that will become available to join. 203 | */ 204 | const createRoom = () => { 205 | setRoomCreateError(false); 206 | setAppState(AppState.Creating); 207 | api 208 | .createRoom() 209 | .then((room) => { 210 | setRoomUrlFieldValue(room.url); 211 | setAppState(AppState.Idle); 212 | }) 213 | .catch(() => { 214 | setRoomCreateError(true); 215 | setRoomUrlFieldValue(undefined); 216 | setAppState(AppState.Idle); 217 | }); 218 | }; 219 | 220 | /** 221 | * Join the room provided by the user or the temporary room created by createRoom 222 | */ 223 | const startCall = () => { 224 | setRoomUrl(roomUrlFieldValue); 225 | }; 226 | 227 | /** 228 | * Leave the current call. 229 | * If we're in the error state (AppState.Error), we've already "left", so just 230 | * clean up our state. 231 | */ 232 | const leaveCall = useCallback(() => { 233 | if (!callObject) { 234 | return; 235 | } 236 | if (appState === AppState.Error) { 237 | callObject.destroy().then(() => { 238 | setRoomUrl(undefined); 239 | setRoomUrlFieldValue(undefined); 240 | setCallObject(null); 241 | setAppState(AppState.Idle); 242 | }); 243 | } else { 244 | setAppState(AppState.Leaving); 245 | callObject.leave(); 246 | } 247 | }, [callObject, appState]); 248 | 249 | const showCallPanel = [ 250 | AppState.Joining, 251 | AppState.Joined, 252 | AppState.Error, 253 | ].includes(appState); 254 | const enableCallButtons = [AppState.Joined, AppState.Error].includes( 255 | appState 256 | ); 257 | const isAppStateIdle = appState === AppState.Idle; 258 | const startButtonDisabled = !isAppStateIdle || !roomUrlFieldValue; 259 | 260 | return ( 261 | 262 | 263 | 264 | 270 | {showCallPanel ? ( 271 | 279 | 280 | 284 | 285 | ) : ( 286 | 294 | 298 | 299 | 300 | To get started, enter an existing room URL or create a 301 | temporary demo room 302 | 303 | 309 | { 320 | setRoomUrlFieldValue(text); 321 | setRoomCreateError(false); 322 | }} 323 | /> 324 | {!!roomUrlFieldValue && ( 325 | setRoomUrlFieldValue(undefined)} 327 | > 328 | 332 | 333 | )} 334 | 335 | {roomCreateError && ( 336 | 337 | 338 | 339 | Oops! A room couldn't be created. 340 | 341 | 342 | )} 343 | {roomUrlFieldValue ? ( 344 | 345 | ) : ( 346 |