@whereby.com/browser-sdk 2.0.0-alpha1 → 2.0.0-alpha10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -2
- package/dist/{lib.cjs.js → lib.cjs} +543 -142
- package/dist/lib.esm.js +543 -144
- package/dist/types.d.ts +215 -11
- package/dist/v2-alpha10.js +43 -0
- package/package.json +12 -7
- package/dist/v2-alpha1.js +0 -105
package/dist/lib.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { define, ref } from 'heresy';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import { __rest, __awaiter } from 'tslib';
|
|
3
|
+
import React, { useRef, useEffect, useState, useReducer } from 'react';
|
|
4
4
|
import adapter from 'webrtc-adapter';
|
|
5
5
|
import io from 'socket.io-client';
|
|
6
6
|
import SDPUtils from 'sdp';
|
|
@@ -115,7 +115,7 @@ define("WherebyEmbed", {
|
|
|
115
115
|
if (!subdomain)
|
|
116
116
|
return this.html `Whereby: Missing subdomain attr.`;
|
|
117
117
|
const url = new URL(room, `https://${subdomain}.whereby.com`);
|
|
118
|
-
Object.entries(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ jsApi: true, we: "2.0.0-
|
|
118
|
+
Object.entries(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ jsApi: true, we: "2.0.0-alpha10", iframeSource: subdomain }, (displayName && { displayName })), (lang && { lang })), (metadata && { metadata })), (groups && { groups })), (virtualBackgroundUrl && { virtualBackgroundUrl })), (avatarUrl && { avatarUrl })), (minimal != null && { embed: minimal })), boolAttrs.reduce(
|
|
119
119
|
// add to URL if set in any way
|
|
120
120
|
(o, v) => (this[v.toLowerCase()] != null ? Object.assign(Object.assign({}, o), { [v]: this[v.toLowerCase()] }) : o), {}))).forEach(([k, v]) => {
|
|
121
121
|
if (!url.searchParams.has(k) && typeof v === "string") {
|
|
@@ -131,15 +131,261 @@ define("WherebyEmbed", {
|
|
|
131
131
|
},
|
|
132
132
|
});
|
|
133
133
|
|
|
134
|
-
var
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
var VideoView = (_a) => {
|
|
135
|
+
var { muted, stream } = _a, rest = __rest(_a, ["muted", "stream"]);
|
|
136
|
+
const videoEl = useRef(null);
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
if (!videoEl.current) {
|
|
139
|
+
return;
|
|
138
140
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
+
if (videoEl.current.srcObject !== stream) {
|
|
142
|
+
videoEl.current.srcObject = stream;
|
|
143
|
+
}
|
|
144
|
+
// Handle muting programatically, not as video attribute
|
|
145
|
+
// https://stackoverflow.com/questions/14111917/html5-video-muted-but-still-playing
|
|
146
|
+
if (videoEl.current.muted !== muted) {
|
|
147
|
+
videoEl.current.muted = Boolean(muted);
|
|
148
|
+
}
|
|
149
|
+
}, [muted, stream, videoEl]);
|
|
150
|
+
return React.createElement("video", Object.assign({ ref: videoEl, autoPlay: true, playsInline: true }, rest));
|
|
141
151
|
};
|
|
142
152
|
|
|
153
|
+
const TypedLocalMediaEventTarget = EventTarget;
|
|
154
|
+
class LocalMedia extends TypedLocalMediaEventTarget {
|
|
155
|
+
constructor(constraints) {
|
|
156
|
+
super();
|
|
157
|
+
this._constraints = constraints;
|
|
158
|
+
this.stream = new MediaStream();
|
|
159
|
+
this._rtcManagers = [];
|
|
160
|
+
navigator.mediaDevices.addEventListener("devicechange", this._updateDeviceList.bind(this));
|
|
161
|
+
}
|
|
162
|
+
addRtcManager(rtcManager) {
|
|
163
|
+
this._rtcManagers.push(rtcManager);
|
|
164
|
+
}
|
|
165
|
+
removeRtcManager(rtcManager) {
|
|
166
|
+
this._rtcManagers = this._rtcManagers.filter((r) => r !== rtcManager);
|
|
167
|
+
}
|
|
168
|
+
getCameraDeviceId() {
|
|
169
|
+
var _a;
|
|
170
|
+
return (_a = this.stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
|
|
171
|
+
}
|
|
172
|
+
getMicrophoneDeviceId() {
|
|
173
|
+
var _a;
|
|
174
|
+
return (_a = this.stream.getAudioTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
|
|
175
|
+
}
|
|
176
|
+
isCameraEnabled() {
|
|
177
|
+
var _a;
|
|
178
|
+
return !!((_a = this.stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.enabled);
|
|
179
|
+
}
|
|
180
|
+
isMicrophoneEnabled() {
|
|
181
|
+
var _a;
|
|
182
|
+
return !!((_a = this.stream.getAudioTracks()[0]) === null || _a === void 0 ? void 0 : _a.enabled);
|
|
183
|
+
}
|
|
184
|
+
toggleCameraEnabled(enabled) {
|
|
185
|
+
const videoTrack = this.stream.getVideoTracks()[0];
|
|
186
|
+
if (!videoTrack) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const newValue = enabled !== null && enabled !== void 0 ? enabled : !videoTrack.enabled;
|
|
190
|
+
videoTrack.enabled = newValue;
|
|
191
|
+
this.dispatchEvent(new CustomEvent("camera_enabled", { detail: { enabled: newValue } }));
|
|
192
|
+
}
|
|
193
|
+
toggleMichrophoneEnabled(enabled) {
|
|
194
|
+
const audioTrack = this.stream.getAudioTracks()[0];
|
|
195
|
+
if (!audioTrack) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const newValue = enabled !== null && enabled !== void 0 ? enabled : !audioTrack.enabled;
|
|
199
|
+
audioTrack.enabled = newValue;
|
|
200
|
+
this.dispatchEvent(new CustomEvent("microphone_enabled", { detail: { enabled: newValue } }));
|
|
201
|
+
}
|
|
202
|
+
setCameraDevice(deviceId) {
|
|
203
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
204
|
+
const newStream = yield navigator.mediaDevices.getUserMedia({ video: { deviceId } });
|
|
205
|
+
const newVideoTrack = newStream.getVideoTracks()[0];
|
|
206
|
+
if (newVideoTrack) {
|
|
207
|
+
const oldVideoTrack = this.stream.getVideoTracks()[0];
|
|
208
|
+
newVideoTrack.enabled = oldVideoTrack.enabled;
|
|
209
|
+
oldVideoTrack === null || oldVideoTrack === void 0 ? void 0 : oldVideoTrack.stop();
|
|
210
|
+
this._rtcManagers.forEach((rtcManager) => {
|
|
211
|
+
rtcManager.replaceTrack(oldVideoTrack, newVideoTrack);
|
|
212
|
+
});
|
|
213
|
+
this.stream.removeTrack(oldVideoTrack);
|
|
214
|
+
this.stream.addTrack(newVideoTrack);
|
|
215
|
+
}
|
|
216
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
217
|
+
detail: { stream: this.stream },
|
|
218
|
+
}));
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
setMicrophoneDevice(deviceId) {
|
|
222
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
223
|
+
const newStream = yield navigator.mediaDevices.getUserMedia({ audio: { deviceId } });
|
|
224
|
+
const newAudioTrack = newStream.getAudioTracks()[0];
|
|
225
|
+
const oldAudioTrack = this.stream.getAudioTracks()[0];
|
|
226
|
+
if (oldAudioTrack) {
|
|
227
|
+
newAudioTrack.enabled = oldAudioTrack.enabled;
|
|
228
|
+
oldAudioTrack.stop();
|
|
229
|
+
this.stream.removeTrack(oldAudioTrack);
|
|
230
|
+
}
|
|
231
|
+
this._rtcManagers.forEach((rtcManager) => {
|
|
232
|
+
rtcManager.replaceTrack(oldAudioTrack, newAudioTrack);
|
|
233
|
+
});
|
|
234
|
+
this.stream.addTrack(newAudioTrack);
|
|
235
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
236
|
+
detail: { stream: this.stream },
|
|
237
|
+
}));
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
_updateDeviceList() {
|
|
241
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
242
|
+
try {
|
|
243
|
+
const devices = yield navigator.mediaDevices.enumerateDevices();
|
|
244
|
+
this.dispatchEvent(new CustomEvent("device_list_updated", {
|
|
245
|
+
detail: {
|
|
246
|
+
cameraDevices: devices.filter((d) => d.kind === "videoinput"),
|
|
247
|
+
microphoneDevices: devices.filter((d) => d.kind === "audioinput"),
|
|
248
|
+
speakerDevices: devices.filter((d) => d.kind === "audiooutput"),
|
|
249
|
+
},
|
|
250
|
+
}));
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
this.dispatchEvent(new CustomEvent("device_list_update_error", {
|
|
254
|
+
detail: {
|
|
255
|
+
error,
|
|
256
|
+
},
|
|
257
|
+
}));
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
start() {
|
|
263
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
264
|
+
const newStream = yield navigator.mediaDevices.getUserMedia(this._constraints);
|
|
265
|
+
newStream.getTracks().forEach((t) => this.stream.addTrack(t));
|
|
266
|
+
this._updateDeviceList();
|
|
267
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
268
|
+
detail: { stream: this.stream },
|
|
269
|
+
}));
|
|
270
|
+
return this.stream;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
stop() {
|
|
274
|
+
var _a;
|
|
275
|
+
(_a = this.stream) === null || _a === void 0 ? void 0 : _a.getTracks().forEach((t) => {
|
|
276
|
+
t.stop();
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const initialState$1 = {
|
|
282
|
+
cameraDeviceError: null,
|
|
283
|
+
cameraDevices: [],
|
|
284
|
+
isSettingCameraDevice: false,
|
|
285
|
+
isSettingMicrophoneDevice: false,
|
|
286
|
+
isStarting: false,
|
|
287
|
+
microphoneDeviceError: null,
|
|
288
|
+
microphoneDevices: [],
|
|
289
|
+
speakerDevices: [],
|
|
290
|
+
startError: null,
|
|
291
|
+
};
|
|
292
|
+
function reducer$1(state, action) {
|
|
293
|
+
switch (action.type) {
|
|
294
|
+
case "DEVICE_LIST_UPDATED":
|
|
295
|
+
return Object.assign(Object.assign({}, state), action.payload);
|
|
296
|
+
case "LOCAL_STREAM_UPDATED":
|
|
297
|
+
return Object.assign(Object.assign({}, state), { currentCameraDeviceId: action.payload.currentCameraDeviceId, currentMicrophoneDeviceId: action.payload.currentMicrophoneDeviceId, localStream: action.payload.stream });
|
|
298
|
+
case "SET_CAMERA_DEVICE":
|
|
299
|
+
return Object.assign(Object.assign({}, state), { cameraDeviceError: null, isSettingCameraDevice: true });
|
|
300
|
+
case "SET_CAMERA_DEVICE_COMPLETE":
|
|
301
|
+
return Object.assign(Object.assign({}, state), { isSettingCameraDevice: false });
|
|
302
|
+
case "SET_CAMERA_DEVICE_ERROR":
|
|
303
|
+
return Object.assign(Object.assign({}, state), { cameraDeviceError: action.payload, isSettingCameraDevice: false });
|
|
304
|
+
case "SET_MICROPHONE_DEVICE":
|
|
305
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: true, microphoneDeviceError: null });
|
|
306
|
+
case "SET_MICROPHONE_DEVICE_COMPLETE":
|
|
307
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: false });
|
|
308
|
+
case "SET_MICROPHONE_DEVICE_ERROR":
|
|
309
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: false, microphoneDeviceError: action.payload });
|
|
310
|
+
case "START":
|
|
311
|
+
return Object.assign(Object.assign({}, state), { isStarting: true, startError: null });
|
|
312
|
+
case "START_COMPLETE":
|
|
313
|
+
return Object.assign(Object.assign({}, state), { isStarting: false });
|
|
314
|
+
case "START_ERROR":
|
|
315
|
+
return Object.assign(Object.assign({}, state), { isStarting: false, startError: action.payload });
|
|
316
|
+
default:
|
|
317
|
+
return state;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
function useLocalMedia(constraints = { audio: true, video: true }) {
|
|
321
|
+
const [localMedia] = useState(() => new LocalMedia(constraints));
|
|
322
|
+
const [state, dispatch] = useReducer(reducer$1, initialState$1);
|
|
323
|
+
useEffect(() => {
|
|
324
|
+
localMedia.addEventListener("device_list_updated", (e) => {
|
|
325
|
+
const { cameraDevices, microphoneDevices, speakerDevices } = e.detail;
|
|
326
|
+
dispatch({ type: "DEVICE_LIST_UPDATED", payload: { cameraDevices, microphoneDevices, speakerDevices } });
|
|
327
|
+
});
|
|
328
|
+
localMedia.addEventListener("stream_updated", (e) => {
|
|
329
|
+
const { stream } = e.detail;
|
|
330
|
+
dispatch({
|
|
331
|
+
type: "LOCAL_STREAM_UPDATED",
|
|
332
|
+
payload: {
|
|
333
|
+
stream,
|
|
334
|
+
currentCameraDeviceId: localMedia.getCameraDeviceId(),
|
|
335
|
+
currentMicrophoneDeviceId: localMedia.getMicrophoneDeviceId(),
|
|
336
|
+
},
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
const start = () => __awaiter(this, void 0, void 0, function* () {
|
|
340
|
+
dispatch({ type: "START" });
|
|
341
|
+
try {
|
|
342
|
+
yield localMedia.start();
|
|
343
|
+
dispatch({ type: "START_COMPLETE" });
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
dispatch({ type: "START_ERROR", payload: error });
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
start();
|
|
350
|
+
// Perform cleanup on unmount
|
|
351
|
+
return () => {
|
|
352
|
+
localMedia.stop();
|
|
353
|
+
};
|
|
354
|
+
}, []);
|
|
355
|
+
return {
|
|
356
|
+
state,
|
|
357
|
+
actions: {
|
|
358
|
+
setCameraDevice: (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
359
|
+
dispatch({ type: "SET_CAMERA_DEVICE" });
|
|
360
|
+
try {
|
|
361
|
+
yield localMedia.setCameraDevice(...args);
|
|
362
|
+
dispatch({ type: "SET_CAMERA_DEVICE_COMPLETE" });
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
dispatch({ type: "SET_CAMERA_DEVICE_ERROR", payload: error });
|
|
366
|
+
}
|
|
367
|
+
}),
|
|
368
|
+
setMicrophoneDevice: (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
369
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE" });
|
|
370
|
+
try {
|
|
371
|
+
yield localMedia.setMicrophoneDevice(...args);
|
|
372
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE_COMPLETE" });
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE_ERROR", payload: error });
|
|
376
|
+
}
|
|
377
|
+
}),
|
|
378
|
+
toggleCameraEnabled: (...args) => {
|
|
379
|
+
return localMedia.toggleCameraEnabled(...args);
|
|
380
|
+
},
|
|
381
|
+
toggleMicrophoneEnabled: (...args) => {
|
|
382
|
+
return localMedia.toggleMichrophoneEnabled(...args);
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
_ref: localMedia,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
|
|
143
389
|
const EVENTS = {
|
|
144
390
|
CLIENT_CONNECTION_STATUS_CHANGED: "client_connection_status_changed",
|
|
145
391
|
STREAM_ADDED: "stream_added",
|
|
@@ -270,10 +516,10 @@ class ServerSocket {
|
|
|
270
516
|
}
|
|
271
517
|
|
|
272
518
|
this._socket = io(hostName, options);
|
|
273
|
-
this._socket.on("reconnect", () => {
|
|
519
|
+
this._socket.io.on("reconnect", () => {
|
|
274
520
|
this._socket.sendBuffer = [];
|
|
275
521
|
});
|
|
276
|
-
this._socket.on("reconnect_attempt", () => {
|
|
522
|
+
this._socket.io.on("reconnect_attempt", () => {
|
|
277
523
|
if (this._wasConnectedUsingWebsocket) {
|
|
278
524
|
this._socket.io.opts.transports = ["websocket"];
|
|
279
525
|
// only fallback to polling if not safari
|
|
@@ -331,6 +577,10 @@ class ServerSocket {
|
|
|
331
577
|
);
|
|
332
578
|
}
|
|
333
579
|
|
|
580
|
+
getManager() {
|
|
581
|
+
return this._socket.io;
|
|
582
|
+
}
|
|
583
|
+
|
|
334
584
|
isConnecting() {
|
|
335
585
|
return this._socket && this._socket.connecting;
|
|
336
586
|
}
|
|
@@ -1964,10 +2214,11 @@ class VegaParser {
|
|
|
1964
2214
|
}
|
|
1965
2215
|
|
|
1966
2216
|
class VegaConnection extends EventEmitter {
|
|
1967
|
-
constructor(wsUrl, logger) {
|
|
2217
|
+
constructor(wsUrl, logger, protocol = "whereby-sfu#v4") {
|
|
1968
2218
|
super();
|
|
1969
2219
|
|
|
1970
2220
|
this.wsUrl = wsUrl;
|
|
2221
|
+
this.protocol = protocol;
|
|
1971
2222
|
this.logger = logger;
|
|
1972
2223
|
|
|
1973
2224
|
// This is the map of sent requests that are waiting for a response
|
|
@@ -1976,7 +2227,7 @@ class VegaConnection extends EventEmitter {
|
|
|
1976
2227
|
}
|
|
1977
2228
|
|
|
1978
2229
|
_setupSocket() {
|
|
1979
|
-
this.socket = new WebSocket(this.wsUrl,
|
|
2230
|
+
this.socket = new WebSocket(this.wsUrl, this.protocol);
|
|
1980
2231
|
this.socket.onopen = this._onOpen.bind(this);
|
|
1981
2232
|
this.socket.onmessage = this._onMessage.bind(this);
|
|
1982
2233
|
this.socket.onclose = this._onClose.bind(this);
|
|
@@ -1996,7 +2247,9 @@ class VegaConnection extends EventEmitter {
|
|
|
1996
2247
|
}
|
|
1997
2248
|
|
|
1998
2249
|
close() {
|
|
1999
|
-
this.socket
|
|
2250
|
+
if (!this.socket) return;
|
|
2251
|
+
|
|
2252
|
+
this.socket.close();
|
|
2000
2253
|
}
|
|
2001
2254
|
|
|
2002
2255
|
_onOpen() {
|
|
@@ -2008,11 +2261,15 @@ class VegaConnection extends EventEmitter {
|
|
|
2008
2261
|
_onMessage(event) {
|
|
2009
2262
|
const socketMessage = VegaParser.parse(event.data);
|
|
2010
2263
|
|
|
2264
|
+
if (!socketMessage) {
|
|
2265
|
+
return this.logger.log("VegaConnectionManager: Received invalid message", event.data);
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2011
2268
|
this.logger.log("VegaConnectionManager: Received message", socketMessage);
|
|
2012
2269
|
|
|
2013
|
-
if (socketMessage
|
|
2270
|
+
if (socketMessage.response) {
|
|
2014
2271
|
this._handleResponse(socketMessage);
|
|
2015
|
-
} else if (socketMessage
|
|
2272
|
+
} else if (socketMessage.message) {
|
|
2016
2273
|
this.emit("message", socketMessage);
|
|
2017
2274
|
}
|
|
2018
2275
|
}
|
|
@@ -2119,7 +2376,7 @@ const VIDEO_SETTINGS_VP9 = {
|
|
|
2119
2376
|
codecOptions: {
|
|
2120
2377
|
videoGoogleStartBitrate: 500,
|
|
2121
2378
|
},
|
|
2122
|
-
encodings: [{ scalabilityMode: "
|
|
2379
|
+
encodings: [{ scalabilityMode: "L3T2_KEY", networkPriority: "high" }],
|
|
2123
2380
|
};
|
|
2124
2381
|
|
|
2125
2382
|
const SCREEN_SHARE_SETTINGS = {
|
|
@@ -2128,13 +2385,13 @@ const SCREEN_SHARE_SETTINGS = {
|
|
|
2128
2385
|
|
|
2129
2386
|
const SCREEN_SHARE_SIMULCAST_SETTINGS = {
|
|
2130
2387
|
encodings: [
|
|
2131
|
-
{ dtx: true, maxBitrate: 500000 },
|
|
2132
|
-
{ dtx: true, maxBitrate: 1500000 },
|
|
2388
|
+
{ scaleResolutionDownBy: 2, dtx: true, maxBitrate: 500000 },
|
|
2389
|
+
{ scaleResolutionDownBy: 1, dtx: true, maxBitrate: 1500000 },
|
|
2133
2390
|
],
|
|
2134
2391
|
};
|
|
2135
2392
|
|
|
2136
2393
|
const SCREEN_SHARE_SETTINGS_VP9 = {
|
|
2137
|
-
encodings: [{ scalabilityMode: "
|
|
2394
|
+
encodings: [{ scalabilityMode: "L1T1", dtx: true, networkPriority: "high" }],
|
|
2138
2395
|
};
|
|
2139
2396
|
|
|
2140
2397
|
const getMediaSettings = (kind, isScreenShare, features) => {
|
|
@@ -2150,8 +2407,8 @@ const getMediaSettings = (kind, isScreenShare, features) => {
|
|
|
2150
2407
|
|
|
2151
2408
|
return SCREEN_SHARE_SETTINGS;
|
|
2152
2409
|
} else {
|
|
2153
|
-
if (lowDataModeEnabled) return VIDEO_SETTINGS_SD;
|
|
2154
2410
|
if (vp9On) return VIDEO_SETTINGS_VP9;
|
|
2411
|
+
if (lowDataModeEnabled) return VIDEO_SETTINGS_SD;
|
|
2155
2412
|
|
|
2156
2413
|
return VIDEO_SETTINGS_HD;
|
|
2157
2414
|
}
|
|
@@ -5005,12 +5262,12 @@ class LocalParticipant extends RoomParticipant {
|
|
|
5005
5262
|
}
|
|
5006
5263
|
}
|
|
5007
5264
|
|
|
5008
|
-
const API_BASE_URL = "https://api.
|
|
5265
|
+
const API_BASE_URL = "https://api.whereby.dev";
|
|
5009
5266
|
const SIGNAL_BASE_URL = "wss://signal.appearin.net";
|
|
5010
5267
|
const NON_PERSON_ROLES = ["recorder", "streamer"];
|
|
5011
5268
|
function createSocket() {
|
|
5012
5269
|
const parsedUrl = new URL(SIGNAL_BASE_URL);
|
|
5013
|
-
const path = `${parsedUrl.pathname.replace(/^\/$/, "")}/protocol/socket.io/
|
|
5270
|
+
const path = `${parsedUrl.pathname.replace(/^\/$/, "")}/protocol/socket.io/v4`;
|
|
5014
5271
|
const SOCKET_HOST = parsedUrl.origin;
|
|
5015
5272
|
const socketConf = {
|
|
5016
5273
|
host: SOCKET_HOST,
|
|
@@ -5018,6 +5275,7 @@ function createSocket() {
|
|
|
5018
5275
|
reconnectionDelay: 5000,
|
|
5019
5276
|
reconnectionDelayMax: 30000,
|
|
5020
5277
|
timeout: 10000,
|
|
5278
|
+
withCredentials: true,
|
|
5021
5279
|
};
|
|
5022
5280
|
return new ServerSocket(SOCKET_HOST, socketConf);
|
|
5023
5281
|
}
|
|
@@ -5026,12 +5284,17 @@ const noop = () => {
|
|
|
5026
5284
|
};
|
|
5027
5285
|
const TypedEventTarget = EventTarget;
|
|
5028
5286
|
class RoomConnection extends TypedEventTarget {
|
|
5029
|
-
constructor(roomUrl, { displayName,
|
|
5287
|
+
constructor(roomUrl, { displayName, localMedia, localMediaConstraints, logger, roomKey }) {
|
|
5030
5288
|
super();
|
|
5031
5289
|
this.localParticipant = null;
|
|
5032
5290
|
this.remoteParticipants = [];
|
|
5033
|
-
this.
|
|
5291
|
+
this._ownsLocalMedia = false;
|
|
5292
|
+
this.organizationId = "";
|
|
5293
|
+
this.roomConnectionStatus = "";
|
|
5034
5294
|
this.roomUrl = new URL(roomUrl); // Throw if invalid Whereby room url
|
|
5295
|
+
const searchParams = new URLSearchParams(this.roomUrl.search);
|
|
5296
|
+
this._roomKey = roomKey || searchParams.get("roomKey");
|
|
5297
|
+
this.roomName = this.roomUrl.pathname;
|
|
5035
5298
|
this.logger = logger || {
|
|
5036
5299
|
debug: noop,
|
|
5037
5300
|
error: noop,
|
|
@@ -5039,10 +5302,20 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5039
5302
|
warn: noop,
|
|
5040
5303
|
};
|
|
5041
5304
|
this.displayName = displayName;
|
|
5042
|
-
this.localStream = localStream;
|
|
5043
5305
|
this.localMediaConstraints = localMediaConstraints;
|
|
5044
5306
|
const urls = fromLocation({ host: this.roomUrl.host });
|
|
5045
|
-
//
|
|
5307
|
+
// Set up local media
|
|
5308
|
+
if (localMedia) {
|
|
5309
|
+
this.localMedia = localMedia;
|
|
5310
|
+
}
|
|
5311
|
+
else if (localMediaConstraints) {
|
|
5312
|
+
this.localMedia = new LocalMedia(localMediaConstraints);
|
|
5313
|
+
this._ownsLocalMedia = true;
|
|
5314
|
+
}
|
|
5315
|
+
else {
|
|
5316
|
+
throw new Error("Missing constraints");
|
|
5317
|
+
}
|
|
5318
|
+
// Set up services
|
|
5046
5319
|
this.credentialsService = CredentialsService.create({ baseUrl: API_BASE_URL });
|
|
5047
5320
|
this.apiClient = new ApiClient({
|
|
5048
5321
|
fetchDeviceCredentials: this.credentialsService.getCredentials.bind(this.credentialsService),
|
|
@@ -5064,10 +5337,30 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5064
5337
|
// Create signal socket and set up event listeners
|
|
5065
5338
|
this.signalSocket = createSocket();
|
|
5066
5339
|
this.signalSocket.on("new_client", this._handleNewClient.bind(this));
|
|
5340
|
+
this.signalSocket.on("chat_message", this._handleNewChatMessage.bind(this));
|
|
5067
5341
|
this.signalSocket.on("client_left", this._handleClientLeft.bind(this));
|
|
5068
5342
|
this.signalSocket.on("audio_enabled", this._handleClientAudioEnabled.bind(this));
|
|
5069
5343
|
this.signalSocket.on("video_enabled", this._handleClientVideoEnabled.bind(this));
|
|
5070
5344
|
this.signalSocket.on("client_metadata_received", this._handleClientMetadataReceived.bind(this));
|
|
5345
|
+
this.signalSocket.on("knock_handled", this._handleKnockHandled.bind(this));
|
|
5346
|
+
this.signalSocket.on("knocker_left", this._handleKnockerLeft.bind(this));
|
|
5347
|
+
this.signalSocket.on("room_joined", this._handleRoomJoined.bind(this));
|
|
5348
|
+
this.signalSocket.on("room_knocked", this._handleRoomKnocked.bind(this));
|
|
5349
|
+
// Set up local media listeners
|
|
5350
|
+
this.localMedia.addEventListener("camera_enabled", (e) => {
|
|
5351
|
+
const { enabled } = e.detail;
|
|
5352
|
+
this.signalSocket.emit("enable_video", { enabled });
|
|
5353
|
+
});
|
|
5354
|
+
this.localMedia.addEventListener("microphone_enabled", (e) => {
|
|
5355
|
+
const { enabled } = e.detail;
|
|
5356
|
+
this.signalSocket.emit("enable_audio", { enabled });
|
|
5357
|
+
});
|
|
5358
|
+
}
|
|
5359
|
+
get roomKey() {
|
|
5360
|
+
return this._roomKey;
|
|
5361
|
+
}
|
|
5362
|
+
_handleNewChatMessage(message) {
|
|
5363
|
+
this.dispatchEvent(new CustomEvent("chat_message", { detail: message }));
|
|
5071
5364
|
}
|
|
5072
5365
|
_handleNewClient({ client }) {
|
|
5073
5366
|
if (NON_PERSON_ROLES.includes(client.role.roleName)) {
|
|
@@ -5113,6 +5406,70 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5113
5406
|
detail: { participantId: remoteParticipant.id, displayName },
|
|
5114
5407
|
}));
|
|
5115
5408
|
}
|
|
5409
|
+
_handleKnockHandled(payload) {
|
|
5410
|
+
const { resolution } = payload;
|
|
5411
|
+
if (resolution === "accepted") {
|
|
5412
|
+
this.roomConnectionStatus = "accepted";
|
|
5413
|
+
this._roomKey = payload.metadata.roomKey;
|
|
5414
|
+
this._joinRoom();
|
|
5415
|
+
}
|
|
5416
|
+
else if (resolution === "rejected") {
|
|
5417
|
+
this.roomConnectionStatus = "rejected";
|
|
5418
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5419
|
+
detail: {
|
|
5420
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5421
|
+
},
|
|
5422
|
+
}));
|
|
5423
|
+
}
|
|
5424
|
+
}
|
|
5425
|
+
_handleKnockerLeft(payload) {
|
|
5426
|
+
const { clientId } = payload;
|
|
5427
|
+
this.dispatchEvent(new CustomEvent("waiting_participant_left", {
|
|
5428
|
+
detail: { participantId: clientId },
|
|
5429
|
+
}));
|
|
5430
|
+
}
|
|
5431
|
+
_handleRoomJoined(event) {
|
|
5432
|
+
const { error, isLocked, room, selfId } = event;
|
|
5433
|
+
if (error === "room_locked" && isLocked) {
|
|
5434
|
+
this.roomConnectionStatus = "room_locked";
|
|
5435
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5436
|
+
detail: {
|
|
5437
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5438
|
+
},
|
|
5439
|
+
}));
|
|
5440
|
+
return;
|
|
5441
|
+
}
|
|
5442
|
+
// Check if we have an error
|
|
5443
|
+
// Check if it is a room joined error
|
|
5444
|
+
// Set state to connect_failed_locked
|
|
5445
|
+
// Set state to connect_failed_no_host
|
|
5446
|
+
if (room) {
|
|
5447
|
+
const { clients, knockers } = room;
|
|
5448
|
+
const localClient = clients.find((c) => c.id === selfId);
|
|
5449
|
+
if (!localClient)
|
|
5450
|
+
throw new Error("Missing local client");
|
|
5451
|
+
this.localParticipant = new LocalParticipant(Object.assign(Object.assign({}, localClient), { stream: this.localMedia.stream || undefined }));
|
|
5452
|
+
this.remoteParticipants = clients
|
|
5453
|
+
.filter((c) => c.id !== selfId)
|
|
5454
|
+
.map((c) => new RemoteParticipant(Object.assign(Object.assign({}, c), { newJoiner: false })));
|
|
5455
|
+
this.roomConnectionStatus = "connected";
|
|
5456
|
+
this.dispatchEvent(new CustomEvent("room_joined", {
|
|
5457
|
+
detail: {
|
|
5458
|
+
localParticipant: this.localParticipant,
|
|
5459
|
+
remoteParticipants: this.remoteParticipants,
|
|
5460
|
+
waitingParticipants: knockers.map((knocker) => {
|
|
5461
|
+
return { id: knocker.clientId, displayName: knocker.displayName };
|
|
5462
|
+
}),
|
|
5463
|
+
},
|
|
5464
|
+
}));
|
|
5465
|
+
}
|
|
5466
|
+
}
|
|
5467
|
+
_handleRoomKnocked(event) {
|
|
5468
|
+
const { clientId, displayName } = event;
|
|
5469
|
+
this.dispatchEvent(new CustomEvent("waiting_participant_joined", {
|
|
5470
|
+
detail: { participantId: clientId, displayName },
|
|
5471
|
+
}));
|
|
5472
|
+
}
|
|
5116
5473
|
_handleRtcEvent(eventName, data) {
|
|
5117
5474
|
if (eventName === "rtc_manager_created") {
|
|
5118
5475
|
return this._handleRtcManagerCreated(data);
|
|
@@ -5125,10 +5482,14 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5125
5482
|
}
|
|
5126
5483
|
}
|
|
5127
5484
|
_handleRtcManagerCreated({ rtcManager }) {
|
|
5128
|
-
var _a
|
|
5485
|
+
var _a;
|
|
5129
5486
|
this.rtcManager = rtcManager;
|
|
5130
|
-
|
|
5131
|
-
|
|
5487
|
+
this.localMedia.addRtcManager(rtcManager);
|
|
5488
|
+
if (this.localMedia.stream) {
|
|
5489
|
+
(_a = this.rtcManager) === null || _a === void 0 ? void 0 : _a.addNewStream("0", this.localMedia.stream, !this.localMedia.isMicrophoneEnabled(), !this.localMedia.isCameraEnabled());
|
|
5490
|
+
}
|
|
5491
|
+
if (this.remoteParticipants.length) {
|
|
5492
|
+
this._handleAcceptStreams(this.remoteParticipants);
|
|
5132
5493
|
}
|
|
5133
5494
|
}
|
|
5134
5495
|
_handleAcceptStreams(remoteParticipants) {
|
|
@@ -5153,8 +5514,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5153
5514
|
if (!newState) {
|
|
5154
5515
|
return;
|
|
5155
5516
|
}
|
|
5156
|
-
// #endregion
|
|
5157
|
-
// #region doAcceptStreams
|
|
5158
5517
|
if (newState === "to_accept" ||
|
|
5159
5518
|
(newState === "new_accept" && shouldAcceptNewClients) ||
|
|
5160
5519
|
(newState === "old_accept" && !shouldAcceptNewClients)) {
|
|
@@ -5178,7 +5537,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5178
5537
|
else ;
|
|
5179
5538
|
// Update stream state
|
|
5180
5539
|
participant.updateStreamState(streamId, streamState.replace(/to_|new_|old_/, "done_"));
|
|
5181
|
-
// #endregion
|
|
5182
5540
|
});
|
|
5183
5541
|
});
|
|
5184
5542
|
}
|
|
@@ -5190,35 +5548,51 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5190
5548
|
}
|
|
5191
5549
|
this.dispatchEvent(new CustomEvent("participant_stream_added", { detail: { participantId: clientId, stream, streamId } }));
|
|
5192
5550
|
}
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5551
|
+
_joinRoom() {
|
|
5552
|
+
this.signalSocket.emit("join_room", {
|
|
5553
|
+
avatarUrl: null,
|
|
5554
|
+
config: {
|
|
5555
|
+
isAudioEnabled: this.localMedia.isMicrophoneEnabled(),
|
|
5556
|
+
isVideoEnabled: this.localMedia.isCameraEnabled(),
|
|
5557
|
+
},
|
|
5558
|
+
deviceCapabilities: { canScreenshare: true },
|
|
5559
|
+
displayName: this.displayName,
|
|
5560
|
+
isCoLocated: false,
|
|
5561
|
+
isDevicePermissionDenied: false,
|
|
5562
|
+
kickFromOtherRooms: false,
|
|
5563
|
+
organizationId: this.organizationId,
|
|
5564
|
+
roomKey: this.roomKey,
|
|
5565
|
+
roomName: this.roomName,
|
|
5566
|
+
selfId: "",
|
|
5567
|
+
userAgent: `browser-sdk:${sdkVersion }`,
|
|
5568
|
+
});
|
|
5569
|
+
}
|
|
5196
5570
|
join() {
|
|
5197
5571
|
return __awaiter(this, void 0, void 0, function* () {
|
|
5198
|
-
if (["connected", "connecting"].includes(this.
|
|
5199
|
-
console.warn(`Trying to join room state is ${this.
|
|
5572
|
+
if (["connected", "connecting"].includes(this.roomConnectionStatus)) {
|
|
5573
|
+
console.warn(`Trying to join when room state is already ${this.roomConnectionStatus}`);
|
|
5200
5574
|
return;
|
|
5201
5575
|
}
|
|
5202
5576
|
this.logger.log("Joining room");
|
|
5203
|
-
this.
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5577
|
+
this.roomConnectionStatus = "connecting";
|
|
5578
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5579
|
+
detail: {
|
|
5580
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5581
|
+
},
|
|
5582
|
+
}));
|
|
5208
5583
|
const organization = yield this.organizationServiceCache.fetchOrganization();
|
|
5209
5584
|
if (!organization) {
|
|
5210
5585
|
throw new Error("Invalid room url");
|
|
5211
5586
|
}
|
|
5212
|
-
|
|
5213
|
-
|
|
5587
|
+
this.organizationId = organization.organizationId;
|
|
5588
|
+
if (this._ownsLocalMedia) {
|
|
5589
|
+
yield this.localMedia.start();
|
|
5590
|
+
}
|
|
5214
5591
|
const webrtcProvider = {
|
|
5215
|
-
getMediaConstraints: () => {
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
video: !!((_b = this.localStream) === null || _b === void 0 ? void 0 : _b.getVideoTracks().find((t) => t.enabled)),
|
|
5220
|
-
});
|
|
5221
|
-
},
|
|
5592
|
+
getMediaConstraints: () => ({
|
|
5593
|
+
audio: this.localMedia.isMicrophoneEnabled(),
|
|
5594
|
+
video: this.localMedia.isCameraEnabled(),
|
|
5595
|
+
}),
|
|
5222
5596
|
deferrable(clientId) {
|
|
5223
5597
|
return !clientId;
|
|
5224
5598
|
},
|
|
@@ -5241,55 +5615,40 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5241
5615
|
});
|
|
5242
5616
|
// Identify device on signal connection
|
|
5243
5617
|
const deviceCredentials = yield this.credentialsService.getCredentials();
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
this.logger.log("Connected to signal socket");
|
|
5247
|
-
this.signalSocket.emit("identify_device", { deviceCredentials });
|
|
5248
|
-
}, 2000);
|
|
5618
|
+
this.logger.log("Connected to signal socket");
|
|
5619
|
+
this.signalSocket.emit("identify_device", { deviceCredentials });
|
|
5249
5620
|
this.signalSocket.once("device_identified", () => {
|
|
5250
|
-
|
|
5251
|
-
this.signalSocket.emit("join_room", {
|
|
5252
|
-
avatarUrl: null,
|
|
5253
|
-
config: {
|
|
5254
|
-
isAudioEnabled: !!((_a = this.localStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks().find((t) => t.enabled)),
|
|
5255
|
-
isVideoEnabled: !!((_b = this.localStream) === null || _b === void 0 ? void 0 : _b.getVideoTracks().find((t) => t.enabled)),
|
|
5256
|
-
},
|
|
5257
|
-
deviceCapabilities: { canScreenshare: true },
|
|
5258
|
-
displayName: this.displayName,
|
|
5259
|
-
isCoLocated: false,
|
|
5260
|
-
isDevicePermissionDenied: false,
|
|
5261
|
-
kickFromOtherRooms: false,
|
|
5262
|
-
organizationId: organization.organizationId,
|
|
5263
|
-
roomKey: null,
|
|
5264
|
-
roomName: this.roomUrl.pathname,
|
|
5265
|
-
selfId: "",
|
|
5266
|
-
});
|
|
5267
|
-
});
|
|
5268
|
-
this.signalSocket.once("room_joined", (res) => {
|
|
5269
|
-
const { selfId, room: { clients }, } = res;
|
|
5270
|
-
const localClient = clients.find((c) => c.id === selfId);
|
|
5271
|
-
if (!localClient)
|
|
5272
|
-
throw new Error("Missing local client");
|
|
5273
|
-
this.localParticipant = new LocalParticipant(Object.assign(Object.assign({}, localClient), { stream: this.localStream }));
|
|
5274
|
-
this.remoteParticipants = clients
|
|
5275
|
-
.filter((c) => c.id !== selfId)
|
|
5276
|
-
.map((c) => new RemoteParticipant(Object.assign(Object.assign({}, c), { newJoiner: false })));
|
|
5277
|
-
// Accept remote streams if RTC manager has been initialized
|
|
5278
|
-
if (this.rtcManager) {
|
|
5279
|
-
this._handleAcceptStreams(this.remoteParticipants);
|
|
5280
|
-
}
|
|
5281
|
-
this.roomConnectionState = "connected";
|
|
5282
|
-
this.dispatchEvent(new CustomEvent("room_joined", {
|
|
5283
|
-
detail: {
|
|
5284
|
-
localParticipant: this.localParticipant,
|
|
5285
|
-
remoteParticipants: this.remoteParticipants,
|
|
5286
|
-
},
|
|
5287
|
-
}));
|
|
5621
|
+
this._joinRoom();
|
|
5288
5622
|
});
|
|
5289
5623
|
});
|
|
5290
5624
|
}
|
|
5625
|
+
knock() {
|
|
5626
|
+
this.roomConnectionStatus = "knocking";
|
|
5627
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5628
|
+
detail: {
|
|
5629
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5630
|
+
},
|
|
5631
|
+
}));
|
|
5632
|
+
this.signalSocket.emit("knock_room", {
|
|
5633
|
+
displayName: this.displayName,
|
|
5634
|
+
imageUrl: null,
|
|
5635
|
+
kickFromOtherRooms: true,
|
|
5636
|
+
liveVideo: false,
|
|
5637
|
+
organizationId: this.organizationId,
|
|
5638
|
+
roomKey: this._roomKey,
|
|
5639
|
+
roomName: this.roomName,
|
|
5640
|
+
});
|
|
5641
|
+
}
|
|
5291
5642
|
leave() {
|
|
5292
5643
|
return new Promise((resolve) => {
|
|
5644
|
+
if (this._ownsLocalMedia) {
|
|
5645
|
+
this.localMedia.stop();
|
|
5646
|
+
}
|
|
5647
|
+
if (this.rtcManager) {
|
|
5648
|
+
this.localMedia.removeRtcManager(this.rtcManager);
|
|
5649
|
+
this.rtcManager.disconnectAll();
|
|
5650
|
+
this.rtcManager = undefined;
|
|
5651
|
+
}
|
|
5293
5652
|
if (!this.signalSocket) {
|
|
5294
5653
|
return resolve();
|
|
5295
5654
|
}
|
|
@@ -5304,29 +5663,10 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5304
5663
|
});
|
|
5305
5664
|
});
|
|
5306
5665
|
}
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
this.logger.log("Tried toggling non-existing video track");
|
|
5312
|
-
return;
|
|
5313
|
-
}
|
|
5314
|
-
// TODO: Do stopOrResumeVideo
|
|
5315
|
-
const newValue = enabled !== null && enabled !== void 0 ? enabled : !localVideoTrack.enabled;
|
|
5316
|
-
localVideoTrack.enabled = newValue;
|
|
5317
|
-
this.signalSocket.emit("enable_video", { enabled: newValue });
|
|
5318
|
-
}
|
|
5319
|
-
toggleMicrophone(enabled) {
|
|
5320
|
-
var _a;
|
|
5321
|
-
const localAudioTrack = (_a = this.localStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()[0];
|
|
5322
|
-
if (!localAudioTrack) {
|
|
5323
|
-
this.logger.log("Tried toggling non-existing audio track");
|
|
5324
|
-
return;
|
|
5325
|
-
}
|
|
5326
|
-
// TODO: Do stopOrResumeAudio
|
|
5327
|
-
const newValue = enabled !== null && enabled !== void 0 ? enabled : !localAudioTrack.enabled;
|
|
5328
|
-
localAudioTrack.enabled = newValue;
|
|
5329
|
-
this.signalSocket.emit("enable_audio", { enabled: newValue });
|
|
5666
|
+
sendChatMessage(text) {
|
|
5667
|
+
this.signalSocket.emit("chat_message", {
|
|
5668
|
+
text,
|
|
5669
|
+
});
|
|
5330
5670
|
}
|
|
5331
5671
|
setDisplayName(displayName) {
|
|
5332
5672
|
this.signalSocket.emit("send_client_metadata", {
|
|
@@ -5336,8 +5676,31 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5336
5676
|
},
|
|
5337
5677
|
});
|
|
5338
5678
|
}
|
|
5679
|
+
acceptWaitingParticipant(participantId) {
|
|
5680
|
+
this.signalSocket.emit("handle_knock", {
|
|
5681
|
+
action: "accept",
|
|
5682
|
+
clientId: participantId,
|
|
5683
|
+
response: {},
|
|
5684
|
+
});
|
|
5685
|
+
}
|
|
5686
|
+
rejectWaitingParticipant(participantId) {
|
|
5687
|
+
this.signalSocket.emit("handle_knock", {
|
|
5688
|
+
action: "reject",
|
|
5689
|
+
clientId: participantId,
|
|
5690
|
+
response: {},
|
|
5691
|
+
});
|
|
5692
|
+
}
|
|
5339
5693
|
}
|
|
5340
5694
|
|
|
5695
|
+
const initialState = {
|
|
5696
|
+
chatMessages: [],
|
|
5697
|
+
roomConnectionStatus: "",
|
|
5698
|
+
isJoining: false,
|
|
5699
|
+
joinError: null,
|
|
5700
|
+
mostRecentChatMessage: null,
|
|
5701
|
+
remoteParticipants: [],
|
|
5702
|
+
waitingParticipants: [],
|
|
5703
|
+
};
|
|
5341
5704
|
function updateParticipant(remoteParticipants, participantId, updates) {
|
|
5342
5705
|
const existingParticipant = remoteParticipants.find((p) => p.id === participantId);
|
|
5343
5706
|
if (!existingParticipant) {
|
|
@@ -5352,8 +5715,12 @@ function updateParticipant(remoteParticipants, participantId, updates) {
|
|
|
5352
5715
|
}
|
|
5353
5716
|
function reducer(state, action) {
|
|
5354
5717
|
switch (action.type) {
|
|
5718
|
+
case "CHAT_MESSAGE":
|
|
5719
|
+
return Object.assign(Object.assign({}, state), { chatMessages: [...state.chatMessages, action.payload], mostRecentChatMessage: action.payload });
|
|
5355
5720
|
case "ROOM_JOINED":
|
|
5356
|
-
return Object.assign(Object.assign({}, state), { localParticipant: action.payload.localParticipant, remoteParticipants: action.payload.remoteParticipants, roomConnectionStatus: "connected" });
|
|
5721
|
+
return Object.assign(Object.assign({}, state), { localParticipant: action.payload.localParticipant, remoteParticipants: action.payload.remoteParticipants, waitingParticipants: action.payload.waitingParticipants, roomConnectionStatus: "connected" });
|
|
5722
|
+
case "ROOM_CONNECTION_STATUS_CHANGED":
|
|
5723
|
+
return Object.assign(Object.assign({}, state), { roomConnectionStatus: action.payload.roomConnectionStatus });
|
|
5357
5724
|
case "PARTICIPANT_AUDIO_ENABLED":
|
|
5358
5725
|
return Object.assign(Object.assign({}, state), { remoteParticipants: updateParticipant(state.remoteParticipants, action.payload.participantId, {
|
|
5359
5726
|
isAudioEnabled: action.payload.isAudioEnabled,
|
|
@@ -5378,21 +5745,28 @@ function reducer(state, action) {
|
|
|
5378
5745
|
if (!state.localParticipant)
|
|
5379
5746
|
return state;
|
|
5380
5747
|
return Object.assign(Object.assign({}, state), { localParticipant: Object.assign(Object.assign({}, state.localParticipant), { displayName: action.payload.displayName }) });
|
|
5748
|
+
case "WAITING_PARTICIPANT_JOINED":
|
|
5749
|
+
return Object.assign(Object.assign({}, state), { waitingParticipants: [
|
|
5750
|
+
...state.waitingParticipants,
|
|
5751
|
+
{ id: action.payload.participantId, displayName: action.payload.displayName },
|
|
5752
|
+
] });
|
|
5753
|
+
case "WAITING_PARTICIPANT_LEFT":
|
|
5754
|
+
return Object.assign(Object.assign({}, state), { waitingParticipants: state.waitingParticipants.filter((wp) => wp.id !== action.payload.participantId) });
|
|
5381
5755
|
default:
|
|
5382
5756
|
throw state;
|
|
5383
5757
|
}
|
|
5384
|
-
}
|
|
5385
|
-
|
|
5758
|
+
}
|
|
5386
5759
|
function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
5387
|
-
const [roomConnection
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5760
|
+
const [roomConnection] = useState(() => {
|
|
5761
|
+
var _a;
|
|
5762
|
+
return new RoomConnection(roomUrl, Object.assign(Object.assign({}, roomConnectionOptions), { localMedia: ((_a = roomConnectionOptions === null || roomConnectionOptions === void 0 ? void 0 : roomConnectionOptions.localMedia) === null || _a === void 0 ? void 0 : _a._ref) || undefined }));
|
|
5763
|
+
});
|
|
5764
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
5392
5765
|
useEffect(() => {
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5766
|
+
roomConnection.addEventListener("chat_message", (e) => {
|
|
5767
|
+
const chatMessage = e.detail;
|
|
5768
|
+
dispatch({ type: "CHAT_MESSAGE", payload: chatMessage });
|
|
5769
|
+
});
|
|
5396
5770
|
roomConnection.addEventListener("participant_audio_enabled", (e) => {
|
|
5397
5771
|
const { participantId, isAudioEnabled } = e.detail;
|
|
5398
5772
|
dispatch({ type: "PARTICIPANT_AUDIO_ENABLED", payload: { participantId, isAudioEnabled } });
|
|
@@ -5409,9 +5783,13 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
|
5409
5783
|
const { participantId, stream } = e.detail;
|
|
5410
5784
|
dispatch({ type: "PARTICIPANT_STREAM_ADDED", payload: { participantId, stream } });
|
|
5411
5785
|
});
|
|
5786
|
+
roomConnection.addEventListener("room_connection_status_changed", (e) => {
|
|
5787
|
+
const { roomConnectionStatus } = e.detail;
|
|
5788
|
+
dispatch({ type: "ROOM_CONNECTION_STATUS_CHANGED", payload: { roomConnectionStatus } });
|
|
5789
|
+
});
|
|
5412
5790
|
roomConnection.addEventListener("room_joined", (e) => {
|
|
5413
|
-
const { localParticipant, remoteParticipants } = e.detail;
|
|
5414
|
-
dispatch({ type: "ROOM_JOINED", payload: { localParticipant, remoteParticipants } });
|
|
5791
|
+
const { localParticipant, remoteParticipants, waitingParticipants } = e.detail;
|
|
5792
|
+
dispatch({ type: "ROOM_JOINED", payload: { localParticipant, remoteParticipants, waitingParticipants } });
|
|
5415
5793
|
});
|
|
5416
5794
|
roomConnection.addEventListener("participant_video_enabled", (e) => {
|
|
5417
5795
|
const { participantId, isVideoEnabled } = e.detail;
|
|
@@ -5421,31 +5799,52 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
|
5421
5799
|
const { participantId, displayName } = e.detail;
|
|
5422
5800
|
dispatch({ type: "PARTICIPANT_METADATA_CHANGED", payload: { participantId, displayName } });
|
|
5423
5801
|
});
|
|
5802
|
+
roomConnection.addEventListener("waiting_participant_joined", (e) => {
|
|
5803
|
+
const { participantId, displayName } = e.detail;
|
|
5804
|
+
dispatch({ type: "WAITING_PARTICIPANT_JOINED", payload: { participantId, displayName } });
|
|
5805
|
+
});
|
|
5806
|
+
roomConnection.addEventListener("waiting_participant_left", (e) => {
|
|
5807
|
+
const { participantId } = e.detail;
|
|
5808
|
+
dispatch({ type: "WAITING_PARTICIPANT_LEFT", payload: { participantId } });
|
|
5809
|
+
});
|
|
5424
5810
|
roomConnection.join();
|
|
5425
5811
|
return () => {
|
|
5426
5812
|
roomConnection.leave();
|
|
5427
5813
|
};
|
|
5428
|
-
}, [
|
|
5429
|
-
return
|
|
5814
|
+
}, []);
|
|
5815
|
+
return {
|
|
5430
5816
|
state,
|
|
5431
|
-
{
|
|
5432
|
-
|
|
5433
|
-
roomConnection
|
|
5817
|
+
actions: {
|
|
5818
|
+
knock: () => {
|
|
5819
|
+
roomConnection.knock();
|
|
5434
5820
|
},
|
|
5435
|
-
|
|
5436
|
-
roomConnection
|
|
5821
|
+
sendChatMessage: (text) => {
|
|
5822
|
+
roomConnection.sendChatMessage(text);
|
|
5437
5823
|
},
|
|
5438
5824
|
setDisplayName: (displayName) => {
|
|
5439
|
-
roomConnection
|
|
5825
|
+
roomConnection.setDisplayName(displayName);
|
|
5440
5826
|
dispatch({ type: "LOCAL_CLIENT_DISPLAY_NAME_CHANGED", payload: { displayName } });
|
|
5441
5827
|
},
|
|
5828
|
+
toggleCamera: (enabled) => {
|
|
5829
|
+
roomConnection.localMedia.toggleCameraEnabled(enabled);
|
|
5830
|
+
},
|
|
5831
|
+
toggleMicrophone: (enabled) => {
|
|
5832
|
+
roomConnection.localMedia.toggleMichrophoneEnabled(enabled);
|
|
5833
|
+
},
|
|
5834
|
+
acceptWaitingParticipant: (participantId) => {
|
|
5835
|
+
roomConnection.acceptWaitingParticipant(participantId);
|
|
5836
|
+
},
|
|
5837
|
+
rejectWaitingParticipant: (participantId) => {
|
|
5838
|
+
roomConnection.rejectWaitingParticipant(participantId);
|
|
5839
|
+
},
|
|
5442
5840
|
},
|
|
5443
|
-
{
|
|
5444
|
-
VideoView
|
|
5841
|
+
components: {
|
|
5842
|
+
VideoView,
|
|
5445
5843
|
},
|
|
5446
|
-
|
|
5844
|
+
_ref: roomConnection,
|
|
5845
|
+
};
|
|
5447
5846
|
}
|
|
5448
5847
|
|
|
5449
|
-
const sdkVersion = "2.0.0-
|
|
5848
|
+
const sdkVersion = "2.0.0-alpha10";
|
|
5450
5849
|
|
|
5451
|
-
export { sdkVersion, useRoomConnection };
|
|
5850
|
+
export { VideoView, sdkVersion, useLocalMedia, useRoomConnection };
|