@whereby.com/browser-sdk 2.0.0-alpha1 → 2.0.0-alpha11
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 +52 -14
- package/dist/{lib.cjs.js → lib.cjs} +558 -151
- package/dist/lib.esm.js +558 -153
- package/dist/types.d.ts +215 -11
- package/dist/v2-alpha11.js +43 -0
- package/package.json +81 -76
- 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';
|
|
@@ -79,8 +79,7 @@ define("WherebyEmbed", {
|
|
|
79
79
|
// Commands
|
|
80
80
|
_postCommand(command, args = []) {
|
|
81
81
|
if (this.iframe.current) {
|
|
82
|
-
|
|
83
|
-
this.iframe.current.contentWindow.postMessage({ command, args }, url.origin);
|
|
82
|
+
this.iframe.current.contentWindow.postMessage({ command, args }, this.url.origin);
|
|
84
83
|
}
|
|
85
84
|
},
|
|
86
85
|
startRecording() {
|
|
@@ -99,8 +98,7 @@ define("WherebyEmbed", {
|
|
|
99
98
|
this._postCommand("toggle_screenshare", [enabled]);
|
|
100
99
|
},
|
|
101
100
|
onmessage({ origin, data }) {
|
|
102
|
-
|
|
103
|
-
if (origin !== url.origin)
|
|
101
|
+
if (origin !== this.url.origin)
|
|
104
102
|
return;
|
|
105
103
|
const { type, payload: detail } = data;
|
|
106
104
|
this.dispatchEvent(new CustomEvent(type, { detail }));
|
|
@@ -110,36 +108,290 @@ define("WherebyEmbed", {
|
|
|
110
108
|
if (!room)
|
|
111
109
|
return this.html `Whereby: Missing room attribute.`;
|
|
112
110
|
// Get subdomain from room URL, or use it specified
|
|
113
|
-
const m = /https:\/\/([^.]+)\.whereby.com\/.+/.exec(room);
|
|
111
|
+
const m = /https:\/\/([^.]+)(\.whereby.com|-ip-\d+-\d+-\d+-\d+.hereby.dev:4443)\/.+/.exec(room);
|
|
114
112
|
const subdomain = (m && m[1]) || this.subdomain;
|
|
115
113
|
if (!subdomain)
|
|
116
114
|
return this.html `Whereby: Missing subdomain attr.`;
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
if (!m) {
|
|
116
|
+
return this.html `could not parse URL.`;
|
|
117
|
+
}
|
|
118
|
+
const baseURL = m[2] || `.whereby.com`;
|
|
119
|
+
this.url = new URL(room, `https://${subdomain}${baseURL}`);
|
|
120
|
+
const roomUrl = new URL(room);
|
|
121
|
+
if (roomUrl.searchParams.get("roomKey")) {
|
|
122
|
+
this.url.searchParams.append("roomKey", roomUrl.searchParams.get("roomKey"));
|
|
123
|
+
}
|
|
124
|
+
Object.entries(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ jsApi: true, we: "2.0.0-alpha11", iframeSource: subdomain }, (displayName && { displayName })), (lang && { lang })), (metadata && { metadata })), (groups && { groups })), (virtualBackgroundUrl && { virtualBackgroundUrl })), (avatarUrl && { avatarUrl })), (minimal != null && { embed: minimal })), boolAttrs.reduce(
|
|
119
125
|
// add to URL if set in any way
|
|
120
126
|
(o, v) => (this[v.toLowerCase()] != null ? Object.assign(Object.assign({}, o), { [v]: this[v.toLowerCase()] }) : o), {}))).forEach(([k, v]) => {
|
|
121
|
-
if (!url.searchParams.has(k) && typeof v === "string") {
|
|
122
|
-
url.searchParams.set(k, v);
|
|
127
|
+
if (!this.url.searchParams.has(k) && typeof v === "string") {
|
|
128
|
+
this.url.searchParams.set(k, v);
|
|
123
129
|
}
|
|
124
130
|
});
|
|
125
131
|
return this.html `
|
|
126
132
|
<iframe
|
|
127
133
|
ref=${this.iframe}
|
|
128
|
-
src=${url}
|
|
134
|
+
src=${this.url}
|
|
129
135
|
allow="autoplay; camera; microphone; fullscreen; speaker; display-capture" />
|
|
130
136
|
`;
|
|
131
137
|
},
|
|
132
138
|
});
|
|
133
139
|
|
|
134
|
-
var
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
140
|
+
var VideoView = (_a) => {
|
|
141
|
+
var { muted, stream } = _a, rest = __rest(_a, ["muted", "stream"]);
|
|
142
|
+
const videoEl = useRef(null);
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
if (!videoEl.current) {
|
|
145
|
+
return;
|
|
138
146
|
}
|
|
139
|
-
|
|
140
|
-
|
|
147
|
+
if (videoEl.current.srcObject !== stream) {
|
|
148
|
+
videoEl.current.srcObject = stream;
|
|
149
|
+
}
|
|
150
|
+
// Handle muting programatically, not as video attribute
|
|
151
|
+
// https://stackoverflow.com/questions/14111917/html5-video-muted-but-still-playing
|
|
152
|
+
if (videoEl.current.muted !== muted) {
|
|
153
|
+
videoEl.current.muted = Boolean(muted);
|
|
154
|
+
}
|
|
155
|
+
}, [muted, stream, videoEl]);
|
|
156
|
+
return React.createElement("video", Object.assign({ ref: videoEl, autoPlay: true, playsInline: true }, rest));
|
|
141
157
|
};
|
|
142
158
|
|
|
159
|
+
const TypedLocalMediaEventTarget = EventTarget;
|
|
160
|
+
class LocalMedia extends TypedLocalMediaEventTarget {
|
|
161
|
+
constructor(constraints) {
|
|
162
|
+
super();
|
|
163
|
+
this._constraints = constraints;
|
|
164
|
+
this.stream = new MediaStream();
|
|
165
|
+
this._rtcManagers = [];
|
|
166
|
+
navigator.mediaDevices.addEventListener("devicechange", this._updateDeviceList.bind(this));
|
|
167
|
+
}
|
|
168
|
+
addRtcManager(rtcManager) {
|
|
169
|
+
this._rtcManagers.push(rtcManager);
|
|
170
|
+
}
|
|
171
|
+
removeRtcManager(rtcManager) {
|
|
172
|
+
this._rtcManagers = this._rtcManagers.filter((r) => r !== rtcManager);
|
|
173
|
+
}
|
|
174
|
+
getCameraDeviceId() {
|
|
175
|
+
var _a;
|
|
176
|
+
return (_a = this.stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
|
|
177
|
+
}
|
|
178
|
+
getMicrophoneDeviceId() {
|
|
179
|
+
var _a;
|
|
180
|
+
return (_a = this.stream.getAudioTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
|
|
181
|
+
}
|
|
182
|
+
isCameraEnabled() {
|
|
183
|
+
var _a;
|
|
184
|
+
return !!((_a = this.stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.enabled);
|
|
185
|
+
}
|
|
186
|
+
isMicrophoneEnabled() {
|
|
187
|
+
var _a;
|
|
188
|
+
return !!((_a = this.stream.getAudioTracks()[0]) === null || _a === void 0 ? void 0 : _a.enabled);
|
|
189
|
+
}
|
|
190
|
+
toggleCameraEnabled(enabled) {
|
|
191
|
+
const videoTrack = this.stream.getVideoTracks()[0];
|
|
192
|
+
if (!videoTrack) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const newValue = enabled !== null && enabled !== void 0 ? enabled : !videoTrack.enabled;
|
|
196
|
+
videoTrack.enabled = newValue;
|
|
197
|
+
this.dispatchEvent(new CustomEvent("camera_enabled", { detail: { enabled: newValue } }));
|
|
198
|
+
}
|
|
199
|
+
toggleMichrophoneEnabled(enabled) {
|
|
200
|
+
const audioTrack = this.stream.getAudioTracks()[0];
|
|
201
|
+
if (!audioTrack) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const newValue = enabled !== null && enabled !== void 0 ? enabled : !audioTrack.enabled;
|
|
205
|
+
audioTrack.enabled = newValue;
|
|
206
|
+
this.dispatchEvent(new CustomEvent("microphone_enabled", { detail: { enabled: newValue } }));
|
|
207
|
+
}
|
|
208
|
+
setCameraDevice(deviceId) {
|
|
209
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
210
|
+
const newStream = yield navigator.mediaDevices.getUserMedia({ video: { deviceId } });
|
|
211
|
+
const newVideoTrack = newStream.getVideoTracks()[0];
|
|
212
|
+
if (newVideoTrack) {
|
|
213
|
+
const oldVideoTrack = this.stream.getVideoTracks()[0];
|
|
214
|
+
newVideoTrack.enabled = oldVideoTrack.enabled;
|
|
215
|
+
oldVideoTrack === null || oldVideoTrack === void 0 ? void 0 : oldVideoTrack.stop();
|
|
216
|
+
this._rtcManagers.forEach((rtcManager) => {
|
|
217
|
+
rtcManager.replaceTrack(oldVideoTrack, newVideoTrack);
|
|
218
|
+
});
|
|
219
|
+
this.stream.removeTrack(oldVideoTrack);
|
|
220
|
+
this.stream.addTrack(newVideoTrack);
|
|
221
|
+
}
|
|
222
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
223
|
+
detail: { stream: this.stream },
|
|
224
|
+
}));
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
setMicrophoneDevice(deviceId) {
|
|
228
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
229
|
+
const newStream = yield navigator.mediaDevices.getUserMedia({ audio: { deviceId } });
|
|
230
|
+
const newAudioTrack = newStream.getAudioTracks()[0];
|
|
231
|
+
const oldAudioTrack = this.stream.getAudioTracks()[0];
|
|
232
|
+
if (oldAudioTrack) {
|
|
233
|
+
newAudioTrack.enabled = oldAudioTrack.enabled;
|
|
234
|
+
oldAudioTrack.stop();
|
|
235
|
+
this.stream.removeTrack(oldAudioTrack);
|
|
236
|
+
}
|
|
237
|
+
this._rtcManagers.forEach((rtcManager) => {
|
|
238
|
+
rtcManager.replaceTrack(oldAudioTrack, newAudioTrack);
|
|
239
|
+
});
|
|
240
|
+
this.stream.addTrack(newAudioTrack);
|
|
241
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
242
|
+
detail: { stream: this.stream },
|
|
243
|
+
}));
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
_updateDeviceList() {
|
|
247
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
248
|
+
try {
|
|
249
|
+
const devices = yield navigator.mediaDevices.enumerateDevices();
|
|
250
|
+
this.dispatchEvent(new CustomEvent("device_list_updated", {
|
|
251
|
+
detail: {
|
|
252
|
+
cameraDevices: devices.filter((d) => d.kind === "videoinput"),
|
|
253
|
+
microphoneDevices: devices.filter((d) => d.kind === "audioinput"),
|
|
254
|
+
speakerDevices: devices.filter((d) => d.kind === "audiooutput"),
|
|
255
|
+
},
|
|
256
|
+
}));
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
this.dispatchEvent(new CustomEvent("device_list_update_error", {
|
|
260
|
+
detail: {
|
|
261
|
+
error,
|
|
262
|
+
},
|
|
263
|
+
}));
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
start() {
|
|
269
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
270
|
+
const newStream = yield navigator.mediaDevices.getUserMedia(this._constraints);
|
|
271
|
+
newStream.getTracks().forEach((t) => this.stream.addTrack(t));
|
|
272
|
+
this._updateDeviceList();
|
|
273
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
274
|
+
detail: { stream: this.stream },
|
|
275
|
+
}));
|
|
276
|
+
return this.stream;
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
stop() {
|
|
280
|
+
var _a;
|
|
281
|
+
(_a = this.stream) === null || _a === void 0 ? void 0 : _a.getTracks().forEach((t) => {
|
|
282
|
+
t.stop();
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const initialState$1 = {
|
|
288
|
+
cameraDeviceError: null,
|
|
289
|
+
cameraDevices: [],
|
|
290
|
+
isSettingCameraDevice: false,
|
|
291
|
+
isSettingMicrophoneDevice: false,
|
|
292
|
+
isStarting: false,
|
|
293
|
+
microphoneDeviceError: null,
|
|
294
|
+
microphoneDevices: [],
|
|
295
|
+
speakerDevices: [],
|
|
296
|
+
startError: null,
|
|
297
|
+
};
|
|
298
|
+
function reducer$1(state, action) {
|
|
299
|
+
switch (action.type) {
|
|
300
|
+
case "DEVICE_LIST_UPDATED":
|
|
301
|
+
return Object.assign(Object.assign({}, state), action.payload);
|
|
302
|
+
case "LOCAL_STREAM_UPDATED":
|
|
303
|
+
return Object.assign(Object.assign({}, state), { currentCameraDeviceId: action.payload.currentCameraDeviceId, currentMicrophoneDeviceId: action.payload.currentMicrophoneDeviceId, localStream: action.payload.stream });
|
|
304
|
+
case "SET_CAMERA_DEVICE":
|
|
305
|
+
return Object.assign(Object.assign({}, state), { cameraDeviceError: null, isSettingCameraDevice: true });
|
|
306
|
+
case "SET_CAMERA_DEVICE_COMPLETE":
|
|
307
|
+
return Object.assign(Object.assign({}, state), { isSettingCameraDevice: false });
|
|
308
|
+
case "SET_CAMERA_DEVICE_ERROR":
|
|
309
|
+
return Object.assign(Object.assign({}, state), { cameraDeviceError: action.payload, isSettingCameraDevice: false });
|
|
310
|
+
case "SET_MICROPHONE_DEVICE":
|
|
311
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: true, microphoneDeviceError: null });
|
|
312
|
+
case "SET_MICROPHONE_DEVICE_COMPLETE":
|
|
313
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: false });
|
|
314
|
+
case "SET_MICROPHONE_DEVICE_ERROR":
|
|
315
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: false, microphoneDeviceError: action.payload });
|
|
316
|
+
case "START":
|
|
317
|
+
return Object.assign(Object.assign({}, state), { isStarting: true, startError: null });
|
|
318
|
+
case "START_COMPLETE":
|
|
319
|
+
return Object.assign(Object.assign({}, state), { isStarting: false });
|
|
320
|
+
case "START_ERROR":
|
|
321
|
+
return Object.assign(Object.assign({}, state), { isStarting: false, startError: action.payload });
|
|
322
|
+
default:
|
|
323
|
+
return state;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function useLocalMedia(constraints = { audio: true, video: true }) {
|
|
327
|
+
const [localMedia] = useState(() => new LocalMedia(constraints));
|
|
328
|
+
const [state, dispatch] = useReducer(reducer$1, initialState$1);
|
|
329
|
+
useEffect(() => {
|
|
330
|
+
localMedia.addEventListener("device_list_updated", (e) => {
|
|
331
|
+
const { cameraDevices, microphoneDevices, speakerDevices } = e.detail;
|
|
332
|
+
dispatch({ type: "DEVICE_LIST_UPDATED", payload: { cameraDevices, microphoneDevices, speakerDevices } });
|
|
333
|
+
});
|
|
334
|
+
localMedia.addEventListener("stream_updated", (e) => {
|
|
335
|
+
const { stream } = e.detail;
|
|
336
|
+
dispatch({
|
|
337
|
+
type: "LOCAL_STREAM_UPDATED",
|
|
338
|
+
payload: {
|
|
339
|
+
stream,
|
|
340
|
+
currentCameraDeviceId: localMedia.getCameraDeviceId(),
|
|
341
|
+
currentMicrophoneDeviceId: localMedia.getMicrophoneDeviceId(),
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
const start = () => __awaiter(this, void 0, void 0, function* () {
|
|
346
|
+
dispatch({ type: "START" });
|
|
347
|
+
try {
|
|
348
|
+
yield localMedia.start();
|
|
349
|
+
dispatch({ type: "START_COMPLETE" });
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
dispatch({ type: "START_ERROR", payload: error });
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
start();
|
|
356
|
+
// Perform cleanup on unmount
|
|
357
|
+
return () => {
|
|
358
|
+
localMedia.stop();
|
|
359
|
+
};
|
|
360
|
+
}, []);
|
|
361
|
+
return {
|
|
362
|
+
state,
|
|
363
|
+
actions: {
|
|
364
|
+
setCameraDevice: (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
365
|
+
dispatch({ type: "SET_CAMERA_DEVICE" });
|
|
366
|
+
try {
|
|
367
|
+
yield localMedia.setCameraDevice(...args);
|
|
368
|
+
dispatch({ type: "SET_CAMERA_DEVICE_COMPLETE" });
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
dispatch({ type: "SET_CAMERA_DEVICE_ERROR", payload: error });
|
|
372
|
+
}
|
|
373
|
+
}),
|
|
374
|
+
setMicrophoneDevice: (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
375
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE" });
|
|
376
|
+
try {
|
|
377
|
+
yield localMedia.setMicrophoneDevice(...args);
|
|
378
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE_COMPLETE" });
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE_ERROR", payload: error });
|
|
382
|
+
}
|
|
383
|
+
}),
|
|
384
|
+
toggleCameraEnabled: (...args) => {
|
|
385
|
+
return localMedia.toggleCameraEnabled(...args);
|
|
386
|
+
},
|
|
387
|
+
toggleMicrophoneEnabled: (...args) => {
|
|
388
|
+
return localMedia.toggleMichrophoneEnabled(...args);
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
_ref: localMedia,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
143
395
|
const EVENTS = {
|
|
144
396
|
CLIENT_CONNECTION_STATUS_CHANGED: "client_connection_status_changed",
|
|
145
397
|
STREAM_ADDED: "stream_added",
|
|
@@ -270,10 +522,10 @@ class ServerSocket {
|
|
|
270
522
|
}
|
|
271
523
|
|
|
272
524
|
this._socket = io(hostName, options);
|
|
273
|
-
this._socket.on("reconnect", () => {
|
|
525
|
+
this._socket.io.on("reconnect", () => {
|
|
274
526
|
this._socket.sendBuffer = [];
|
|
275
527
|
});
|
|
276
|
-
this._socket.on("reconnect_attempt", () => {
|
|
528
|
+
this._socket.io.on("reconnect_attempt", () => {
|
|
277
529
|
if (this._wasConnectedUsingWebsocket) {
|
|
278
530
|
this._socket.io.opts.transports = ["websocket"];
|
|
279
531
|
// only fallback to polling if not safari
|
|
@@ -331,6 +583,10 @@ class ServerSocket {
|
|
|
331
583
|
);
|
|
332
584
|
}
|
|
333
585
|
|
|
586
|
+
getManager() {
|
|
587
|
+
return this._socket.io;
|
|
588
|
+
}
|
|
589
|
+
|
|
334
590
|
isConnecting() {
|
|
335
591
|
return this._socket && this._socket.connecting;
|
|
336
592
|
}
|
|
@@ -1964,10 +2220,11 @@ class VegaParser {
|
|
|
1964
2220
|
}
|
|
1965
2221
|
|
|
1966
2222
|
class VegaConnection extends EventEmitter {
|
|
1967
|
-
constructor(wsUrl, logger) {
|
|
2223
|
+
constructor(wsUrl, logger, protocol = "whereby-sfu#v4") {
|
|
1968
2224
|
super();
|
|
1969
2225
|
|
|
1970
2226
|
this.wsUrl = wsUrl;
|
|
2227
|
+
this.protocol = protocol;
|
|
1971
2228
|
this.logger = logger;
|
|
1972
2229
|
|
|
1973
2230
|
// This is the map of sent requests that are waiting for a response
|
|
@@ -1976,7 +2233,7 @@ class VegaConnection extends EventEmitter {
|
|
|
1976
2233
|
}
|
|
1977
2234
|
|
|
1978
2235
|
_setupSocket() {
|
|
1979
|
-
this.socket = new WebSocket(this.wsUrl,
|
|
2236
|
+
this.socket = new WebSocket(this.wsUrl, this.protocol);
|
|
1980
2237
|
this.socket.onopen = this._onOpen.bind(this);
|
|
1981
2238
|
this.socket.onmessage = this._onMessage.bind(this);
|
|
1982
2239
|
this.socket.onclose = this._onClose.bind(this);
|
|
@@ -1996,7 +2253,9 @@ class VegaConnection extends EventEmitter {
|
|
|
1996
2253
|
}
|
|
1997
2254
|
|
|
1998
2255
|
close() {
|
|
1999
|
-
this.socket
|
|
2256
|
+
if (!this.socket) return;
|
|
2257
|
+
|
|
2258
|
+
this.socket.close();
|
|
2000
2259
|
}
|
|
2001
2260
|
|
|
2002
2261
|
_onOpen() {
|
|
@@ -2008,11 +2267,15 @@ class VegaConnection extends EventEmitter {
|
|
|
2008
2267
|
_onMessage(event) {
|
|
2009
2268
|
const socketMessage = VegaParser.parse(event.data);
|
|
2010
2269
|
|
|
2270
|
+
if (!socketMessage) {
|
|
2271
|
+
return this.logger.log("VegaConnectionManager: Received invalid message", event.data);
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2011
2274
|
this.logger.log("VegaConnectionManager: Received message", socketMessage);
|
|
2012
2275
|
|
|
2013
|
-
if (socketMessage
|
|
2276
|
+
if (socketMessage.response) {
|
|
2014
2277
|
this._handleResponse(socketMessage);
|
|
2015
|
-
} else if (socketMessage
|
|
2278
|
+
} else if (socketMessage.message) {
|
|
2016
2279
|
this.emit("message", socketMessage);
|
|
2017
2280
|
}
|
|
2018
2281
|
}
|
|
@@ -2119,7 +2382,7 @@ const VIDEO_SETTINGS_VP9 = {
|
|
|
2119
2382
|
codecOptions: {
|
|
2120
2383
|
videoGoogleStartBitrate: 500,
|
|
2121
2384
|
},
|
|
2122
|
-
encodings: [{ scalabilityMode: "
|
|
2385
|
+
encodings: [{ scalabilityMode: "L3T2_KEY", networkPriority: "high" }],
|
|
2123
2386
|
};
|
|
2124
2387
|
|
|
2125
2388
|
const SCREEN_SHARE_SETTINGS = {
|
|
@@ -2128,13 +2391,13 @@ const SCREEN_SHARE_SETTINGS = {
|
|
|
2128
2391
|
|
|
2129
2392
|
const SCREEN_SHARE_SIMULCAST_SETTINGS = {
|
|
2130
2393
|
encodings: [
|
|
2131
|
-
{ dtx: true, maxBitrate: 500000 },
|
|
2132
|
-
{ dtx: true, maxBitrate: 1500000 },
|
|
2394
|
+
{ scaleResolutionDownBy: 2, dtx: true, maxBitrate: 500000 },
|
|
2395
|
+
{ scaleResolutionDownBy: 1, dtx: true, maxBitrate: 1500000 },
|
|
2133
2396
|
],
|
|
2134
2397
|
};
|
|
2135
2398
|
|
|
2136
2399
|
const SCREEN_SHARE_SETTINGS_VP9 = {
|
|
2137
|
-
encodings: [{ scalabilityMode: "
|
|
2400
|
+
encodings: [{ scalabilityMode: "L1T1", dtx: true, networkPriority: "high" }],
|
|
2138
2401
|
};
|
|
2139
2402
|
|
|
2140
2403
|
const getMediaSettings = (kind, isScreenShare, features) => {
|
|
@@ -2150,8 +2413,8 @@ const getMediaSettings = (kind, isScreenShare, features) => {
|
|
|
2150
2413
|
|
|
2151
2414
|
return SCREEN_SHARE_SETTINGS;
|
|
2152
2415
|
} else {
|
|
2153
|
-
if (lowDataModeEnabled) return VIDEO_SETTINGS_SD;
|
|
2154
2416
|
if (vp9On) return VIDEO_SETTINGS_VP9;
|
|
2417
|
+
if (lowDataModeEnabled) return VIDEO_SETTINGS_SD;
|
|
2155
2418
|
|
|
2156
2419
|
return VIDEO_SETTINGS_HD;
|
|
2157
2420
|
}
|
|
@@ -5005,12 +5268,12 @@ class LocalParticipant extends RoomParticipant {
|
|
|
5005
5268
|
}
|
|
5006
5269
|
}
|
|
5007
5270
|
|
|
5008
|
-
const API_BASE_URL = "https://api.
|
|
5271
|
+
const API_BASE_URL = "https://api.whereby.dev";
|
|
5009
5272
|
const SIGNAL_BASE_URL = "wss://signal.appearin.net";
|
|
5010
5273
|
const NON_PERSON_ROLES = ["recorder", "streamer"];
|
|
5011
5274
|
function createSocket() {
|
|
5012
5275
|
const parsedUrl = new URL(SIGNAL_BASE_URL);
|
|
5013
|
-
const path = `${parsedUrl.pathname.replace(/^\/$/, "")}/protocol/socket.io/
|
|
5276
|
+
const path = `${parsedUrl.pathname.replace(/^\/$/, "")}/protocol/socket.io/v4`;
|
|
5014
5277
|
const SOCKET_HOST = parsedUrl.origin;
|
|
5015
5278
|
const socketConf = {
|
|
5016
5279
|
host: SOCKET_HOST,
|
|
@@ -5018,6 +5281,7 @@ function createSocket() {
|
|
|
5018
5281
|
reconnectionDelay: 5000,
|
|
5019
5282
|
reconnectionDelayMax: 30000,
|
|
5020
5283
|
timeout: 10000,
|
|
5284
|
+
withCredentials: true,
|
|
5021
5285
|
};
|
|
5022
5286
|
return new ServerSocket(SOCKET_HOST, socketConf);
|
|
5023
5287
|
}
|
|
@@ -5026,12 +5290,17 @@ const noop = () => {
|
|
|
5026
5290
|
};
|
|
5027
5291
|
const TypedEventTarget = EventTarget;
|
|
5028
5292
|
class RoomConnection extends TypedEventTarget {
|
|
5029
|
-
constructor(roomUrl, { displayName,
|
|
5293
|
+
constructor(roomUrl, { displayName, localMedia, localMediaConstraints, logger, roomKey }) {
|
|
5030
5294
|
super();
|
|
5031
5295
|
this.localParticipant = null;
|
|
5032
5296
|
this.remoteParticipants = [];
|
|
5033
|
-
this.
|
|
5297
|
+
this._ownsLocalMedia = false;
|
|
5298
|
+
this.organizationId = "";
|
|
5299
|
+
this.roomConnectionStatus = "";
|
|
5034
5300
|
this.roomUrl = new URL(roomUrl); // Throw if invalid Whereby room url
|
|
5301
|
+
const searchParams = new URLSearchParams(this.roomUrl.search);
|
|
5302
|
+
this._roomKey = roomKey || searchParams.get("roomKey");
|
|
5303
|
+
this.roomName = this.roomUrl.pathname;
|
|
5035
5304
|
this.logger = logger || {
|
|
5036
5305
|
debug: noop,
|
|
5037
5306
|
error: noop,
|
|
@@ -5039,10 +5308,20 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5039
5308
|
warn: noop,
|
|
5040
5309
|
};
|
|
5041
5310
|
this.displayName = displayName;
|
|
5042
|
-
this.localStream = localStream;
|
|
5043
5311
|
this.localMediaConstraints = localMediaConstraints;
|
|
5044
5312
|
const urls = fromLocation({ host: this.roomUrl.host });
|
|
5045
|
-
//
|
|
5313
|
+
// Set up local media
|
|
5314
|
+
if (localMedia) {
|
|
5315
|
+
this.localMedia = localMedia;
|
|
5316
|
+
}
|
|
5317
|
+
else if (localMediaConstraints) {
|
|
5318
|
+
this.localMedia = new LocalMedia(localMediaConstraints);
|
|
5319
|
+
this._ownsLocalMedia = true;
|
|
5320
|
+
}
|
|
5321
|
+
else {
|
|
5322
|
+
throw new Error("Missing constraints");
|
|
5323
|
+
}
|
|
5324
|
+
// Set up services
|
|
5046
5325
|
this.credentialsService = CredentialsService.create({ baseUrl: API_BASE_URL });
|
|
5047
5326
|
this.apiClient = new ApiClient({
|
|
5048
5327
|
fetchDeviceCredentials: this.credentialsService.getCredentials.bind(this.credentialsService),
|
|
@@ -5064,10 +5343,30 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5064
5343
|
// Create signal socket and set up event listeners
|
|
5065
5344
|
this.signalSocket = createSocket();
|
|
5066
5345
|
this.signalSocket.on("new_client", this._handleNewClient.bind(this));
|
|
5346
|
+
this.signalSocket.on("chat_message", this._handleNewChatMessage.bind(this));
|
|
5067
5347
|
this.signalSocket.on("client_left", this._handleClientLeft.bind(this));
|
|
5068
5348
|
this.signalSocket.on("audio_enabled", this._handleClientAudioEnabled.bind(this));
|
|
5069
5349
|
this.signalSocket.on("video_enabled", this._handleClientVideoEnabled.bind(this));
|
|
5070
5350
|
this.signalSocket.on("client_metadata_received", this._handleClientMetadataReceived.bind(this));
|
|
5351
|
+
this.signalSocket.on("knock_handled", this._handleKnockHandled.bind(this));
|
|
5352
|
+
this.signalSocket.on("knocker_left", this._handleKnockerLeft.bind(this));
|
|
5353
|
+
this.signalSocket.on("room_joined", this._handleRoomJoined.bind(this));
|
|
5354
|
+
this.signalSocket.on("room_knocked", this._handleRoomKnocked.bind(this));
|
|
5355
|
+
// Set up local media listeners
|
|
5356
|
+
this.localMedia.addEventListener("camera_enabled", (e) => {
|
|
5357
|
+
const { enabled } = e.detail;
|
|
5358
|
+
this.signalSocket.emit("enable_video", { enabled });
|
|
5359
|
+
});
|
|
5360
|
+
this.localMedia.addEventListener("microphone_enabled", (e) => {
|
|
5361
|
+
const { enabled } = e.detail;
|
|
5362
|
+
this.signalSocket.emit("enable_audio", { enabled });
|
|
5363
|
+
});
|
|
5364
|
+
}
|
|
5365
|
+
get roomKey() {
|
|
5366
|
+
return this._roomKey;
|
|
5367
|
+
}
|
|
5368
|
+
_handleNewChatMessage(message) {
|
|
5369
|
+
this.dispatchEvent(new CustomEvent("chat_message", { detail: message }));
|
|
5071
5370
|
}
|
|
5072
5371
|
_handleNewClient({ client }) {
|
|
5073
5372
|
if (NON_PERSON_ROLES.includes(client.role.roleName)) {
|
|
@@ -5113,6 +5412,70 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5113
5412
|
detail: { participantId: remoteParticipant.id, displayName },
|
|
5114
5413
|
}));
|
|
5115
5414
|
}
|
|
5415
|
+
_handleKnockHandled(payload) {
|
|
5416
|
+
const { resolution } = payload;
|
|
5417
|
+
if (resolution === "accepted") {
|
|
5418
|
+
this.roomConnectionStatus = "accepted";
|
|
5419
|
+
this._roomKey = payload.metadata.roomKey;
|
|
5420
|
+
this._joinRoom();
|
|
5421
|
+
}
|
|
5422
|
+
else if (resolution === "rejected") {
|
|
5423
|
+
this.roomConnectionStatus = "rejected";
|
|
5424
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5425
|
+
detail: {
|
|
5426
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5427
|
+
},
|
|
5428
|
+
}));
|
|
5429
|
+
}
|
|
5430
|
+
}
|
|
5431
|
+
_handleKnockerLeft(payload) {
|
|
5432
|
+
const { clientId } = payload;
|
|
5433
|
+
this.dispatchEvent(new CustomEvent("waiting_participant_left", {
|
|
5434
|
+
detail: { participantId: clientId },
|
|
5435
|
+
}));
|
|
5436
|
+
}
|
|
5437
|
+
_handleRoomJoined(event) {
|
|
5438
|
+
const { error, isLocked, room, selfId } = event;
|
|
5439
|
+
if (error === "room_locked" && isLocked) {
|
|
5440
|
+
this.roomConnectionStatus = "room_locked";
|
|
5441
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5442
|
+
detail: {
|
|
5443
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5444
|
+
},
|
|
5445
|
+
}));
|
|
5446
|
+
return;
|
|
5447
|
+
}
|
|
5448
|
+
// Check if we have an error
|
|
5449
|
+
// Check if it is a room joined error
|
|
5450
|
+
// Set state to connect_failed_locked
|
|
5451
|
+
// Set state to connect_failed_no_host
|
|
5452
|
+
if (room) {
|
|
5453
|
+
const { clients, knockers } = room;
|
|
5454
|
+
const localClient = clients.find((c) => c.id === selfId);
|
|
5455
|
+
if (!localClient)
|
|
5456
|
+
throw new Error("Missing local client");
|
|
5457
|
+
this.localParticipant = new LocalParticipant(Object.assign(Object.assign({}, localClient), { stream: this.localMedia.stream || undefined }));
|
|
5458
|
+
this.remoteParticipants = clients
|
|
5459
|
+
.filter((c) => c.id !== selfId)
|
|
5460
|
+
.map((c) => new RemoteParticipant(Object.assign(Object.assign({}, c), { newJoiner: false })));
|
|
5461
|
+
this.roomConnectionStatus = "connected";
|
|
5462
|
+
this.dispatchEvent(new CustomEvent("room_joined", {
|
|
5463
|
+
detail: {
|
|
5464
|
+
localParticipant: this.localParticipant,
|
|
5465
|
+
remoteParticipants: this.remoteParticipants,
|
|
5466
|
+
waitingParticipants: knockers.map((knocker) => {
|
|
5467
|
+
return { id: knocker.clientId, displayName: knocker.displayName };
|
|
5468
|
+
}),
|
|
5469
|
+
},
|
|
5470
|
+
}));
|
|
5471
|
+
}
|
|
5472
|
+
}
|
|
5473
|
+
_handleRoomKnocked(event) {
|
|
5474
|
+
const { clientId, displayName } = event;
|
|
5475
|
+
this.dispatchEvent(new CustomEvent("waiting_participant_joined", {
|
|
5476
|
+
detail: { participantId: clientId, displayName },
|
|
5477
|
+
}));
|
|
5478
|
+
}
|
|
5116
5479
|
_handleRtcEvent(eventName, data) {
|
|
5117
5480
|
if (eventName === "rtc_manager_created") {
|
|
5118
5481
|
return this._handleRtcManagerCreated(data);
|
|
@@ -5125,10 +5488,14 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5125
5488
|
}
|
|
5126
5489
|
}
|
|
5127
5490
|
_handleRtcManagerCreated({ rtcManager }) {
|
|
5128
|
-
var _a
|
|
5491
|
+
var _a;
|
|
5129
5492
|
this.rtcManager = rtcManager;
|
|
5130
|
-
|
|
5131
|
-
|
|
5493
|
+
this.localMedia.addRtcManager(rtcManager);
|
|
5494
|
+
if (this.localMedia.stream) {
|
|
5495
|
+
(_a = this.rtcManager) === null || _a === void 0 ? void 0 : _a.addNewStream("0", this.localMedia.stream, !this.localMedia.isMicrophoneEnabled(), !this.localMedia.isCameraEnabled());
|
|
5496
|
+
}
|
|
5497
|
+
if (this.remoteParticipants.length) {
|
|
5498
|
+
this._handleAcceptStreams(this.remoteParticipants);
|
|
5132
5499
|
}
|
|
5133
5500
|
}
|
|
5134
5501
|
_handleAcceptStreams(remoteParticipants) {
|
|
@@ -5153,8 +5520,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5153
5520
|
if (!newState) {
|
|
5154
5521
|
return;
|
|
5155
5522
|
}
|
|
5156
|
-
// #endregion
|
|
5157
|
-
// #region doAcceptStreams
|
|
5158
5523
|
if (newState === "to_accept" ||
|
|
5159
5524
|
(newState === "new_accept" && shouldAcceptNewClients) ||
|
|
5160
5525
|
(newState === "old_accept" && !shouldAcceptNewClients)) {
|
|
@@ -5178,7 +5543,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5178
5543
|
else ;
|
|
5179
5544
|
// Update stream state
|
|
5180
5545
|
participant.updateStreamState(streamId, streamState.replace(/to_|new_|old_/, "done_"));
|
|
5181
|
-
// #endregion
|
|
5182
5546
|
});
|
|
5183
5547
|
});
|
|
5184
5548
|
}
|
|
@@ -5190,35 +5554,51 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5190
5554
|
}
|
|
5191
5555
|
this.dispatchEvent(new CustomEvent("participant_stream_added", { detail: { participantId: clientId, stream, streamId } }));
|
|
5192
5556
|
}
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5557
|
+
_joinRoom() {
|
|
5558
|
+
this.signalSocket.emit("join_room", {
|
|
5559
|
+
avatarUrl: null,
|
|
5560
|
+
config: {
|
|
5561
|
+
isAudioEnabled: this.localMedia.isMicrophoneEnabled(),
|
|
5562
|
+
isVideoEnabled: this.localMedia.isCameraEnabled(),
|
|
5563
|
+
},
|
|
5564
|
+
deviceCapabilities: { canScreenshare: true },
|
|
5565
|
+
displayName: this.displayName,
|
|
5566
|
+
isCoLocated: false,
|
|
5567
|
+
isDevicePermissionDenied: false,
|
|
5568
|
+
kickFromOtherRooms: false,
|
|
5569
|
+
organizationId: this.organizationId,
|
|
5570
|
+
roomKey: this.roomKey,
|
|
5571
|
+
roomName: this.roomName,
|
|
5572
|
+
selfId: "",
|
|
5573
|
+
userAgent: `browser-sdk:${sdkVersion }`,
|
|
5574
|
+
});
|
|
5575
|
+
}
|
|
5196
5576
|
join() {
|
|
5197
5577
|
return __awaiter(this, void 0, void 0, function* () {
|
|
5198
|
-
if (["connected", "connecting"].includes(this.
|
|
5199
|
-
console.warn(`Trying to join room state is ${this.
|
|
5578
|
+
if (["connected", "connecting"].includes(this.roomConnectionStatus)) {
|
|
5579
|
+
console.warn(`Trying to join when room state is already ${this.roomConnectionStatus}`);
|
|
5200
5580
|
return;
|
|
5201
5581
|
}
|
|
5202
5582
|
this.logger.log("Joining room");
|
|
5203
|
-
this.
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5583
|
+
this.roomConnectionStatus = "connecting";
|
|
5584
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5585
|
+
detail: {
|
|
5586
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5587
|
+
},
|
|
5588
|
+
}));
|
|
5208
5589
|
const organization = yield this.organizationServiceCache.fetchOrganization();
|
|
5209
5590
|
if (!organization) {
|
|
5210
5591
|
throw new Error("Invalid room url");
|
|
5211
5592
|
}
|
|
5212
|
-
|
|
5213
|
-
|
|
5593
|
+
this.organizationId = organization.organizationId;
|
|
5594
|
+
if (this._ownsLocalMedia) {
|
|
5595
|
+
yield this.localMedia.start();
|
|
5596
|
+
}
|
|
5214
5597
|
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
|
-
},
|
|
5598
|
+
getMediaConstraints: () => ({
|
|
5599
|
+
audio: this.localMedia.isMicrophoneEnabled(),
|
|
5600
|
+
video: this.localMedia.isCameraEnabled(),
|
|
5601
|
+
}),
|
|
5222
5602
|
deferrable(clientId) {
|
|
5223
5603
|
return !clientId;
|
|
5224
5604
|
},
|
|
@@ -5241,55 +5621,40 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5241
5621
|
});
|
|
5242
5622
|
// Identify device on signal connection
|
|
5243
5623
|
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);
|
|
5624
|
+
this.logger.log("Connected to signal socket");
|
|
5625
|
+
this.signalSocket.emit("identify_device", { deviceCredentials });
|
|
5249
5626
|
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
|
-
}));
|
|
5627
|
+
this._joinRoom();
|
|
5288
5628
|
});
|
|
5289
5629
|
});
|
|
5290
5630
|
}
|
|
5631
|
+
knock() {
|
|
5632
|
+
this.roomConnectionStatus = "knocking";
|
|
5633
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5634
|
+
detail: {
|
|
5635
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5636
|
+
},
|
|
5637
|
+
}));
|
|
5638
|
+
this.signalSocket.emit("knock_room", {
|
|
5639
|
+
displayName: this.displayName,
|
|
5640
|
+
imageUrl: null,
|
|
5641
|
+
kickFromOtherRooms: true,
|
|
5642
|
+
liveVideo: false,
|
|
5643
|
+
organizationId: this.organizationId,
|
|
5644
|
+
roomKey: this._roomKey,
|
|
5645
|
+
roomName: this.roomName,
|
|
5646
|
+
});
|
|
5647
|
+
}
|
|
5291
5648
|
leave() {
|
|
5292
5649
|
return new Promise((resolve) => {
|
|
5650
|
+
if (this._ownsLocalMedia) {
|
|
5651
|
+
this.localMedia.stop();
|
|
5652
|
+
}
|
|
5653
|
+
if (this.rtcManager) {
|
|
5654
|
+
this.localMedia.removeRtcManager(this.rtcManager);
|
|
5655
|
+
this.rtcManager.disconnectAll();
|
|
5656
|
+
this.rtcManager = undefined;
|
|
5657
|
+
}
|
|
5293
5658
|
if (!this.signalSocket) {
|
|
5294
5659
|
return resolve();
|
|
5295
5660
|
}
|
|
@@ -5304,29 +5669,10 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5304
5669
|
});
|
|
5305
5670
|
});
|
|
5306
5671
|
}
|
|
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 });
|
|
5672
|
+
sendChatMessage(text) {
|
|
5673
|
+
this.signalSocket.emit("chat_message", {
|
|
5674
|
+
text,
|
|
5675
|
+
});
|
|
5330
5676
|
}
|
|
5331
5677
|
setDisplayName(displayName) {
|
|
5332
5678
|
this.signalSocket.emit("send_client_metadata", {
|
|
@@ -5336,8 +5682,31 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5336
5682
|
},
|
|
5337
5683
|
});
|
|
5338
5684
|
}
|
|
5685
|
+
acceptWaitingParticipant(participantId) {
|
|
5686
|
+
this.signalSocket.emit("handle_knock", {
|
|
5687
|
+
action: "accept",
|
|
5688
|
+
clientId: participantId,
|
|
5689
|
+
response: {},
|
|
5690
|
+
});
|
|
5691
|
+
}
|
|
5692
|
+
rejectWaitingParticipant(participantId) {
|
|
5693
|
+
this.signalSocket.emit("handle_knock", {
|
|
5694
|
+
action: "reject",
|
|
5695
|
+
clientId: participantId,
|
|
5696
|
+
response: {},
|
|
5697
|
+
});
|
|
5698
|
+
}
|
|
5339
5699
|
}
|
|
5340
5700
|
|
|
5701
|
+
const initialState = {
|
|
5702
|
+
chatMessages: [],
|
|
5703
|
+
roomConnectionStatus: "",
|
|
5704
|
+
isJoining: false,
|
|
5705
|
+
joinError: null,
|
|
5706
|
+
mostRecentChatMessage: null,
|
|
5707
|
+
remoteParticipants: [],
|
|
5708
|
+
waitingParticipants: [],
|
|
5709
|
+
};
|
|
5341
5710
|
function updateParticipant(remoteParticipants, participantId, updates) {
|
|
5342
5711
|
const existingParticipant = remoteParticipants.find((p) => p.id === participantId);
|
|
5343
5712
|
if (!existingParticipant) {
|
|
@@ -5352,8 +5721,12 @@ function updateParticipant(remoteParticipants, participantId, updates) {
|
|
|
5352
5721
|
}
|
|
5353
5722
|
function reducer(state, action) {
|
|
5354
5723
|
switch (action.type) {
|
|
5724
|
+
case "CHAT_MESSAGE":
|
|
5725
|
+
return Object.assign(Object.assign({}, state), { chatMessages: [...state.chatMessages, action.payload], mostRecentChatMessage: action.payload });
|
|
5355
5726
|
case "ROOM_JOINED":
|
|
5356
|
-
return Object.assign(Object.assign({}, state), { localParticipant: action.payload.localParticipant, remoteParticipants: action.payload.remoteParticipants, roomConnectionStatus: "connected" });
|
|
5727
|
+
return Object.assign(Object.assign({}, state), { localParticipant: action.payload.localParticipant, remoteParticipants: action.payload.remoteParticipants, waitingParticipants: action.payload.waitingParticipants, roomConnectionStatus: "connected" });
|
|
5728
|
+
case "ROOM_CONNECTION_STATUS_CHANGED":
|
|
5729
|
+
return Object.assign(Object.assign({}, state), { roomConnectionStatus: action.payload.roomConnectionStatus });
|
|
5357
5730
|
case "PARTICIPANT_AUDIO_ENABLED":
|
|
5358
5731
|
return Object.assign(Object.assign({}, state), { remoteParticipants: updateParticipant(state.remoteParticipants, action.payload.participantId, {
|
|
5359
5732
|
isAudioEnabled: action.payload.isAudioEnabled,
|
|
@@ -5378,21 +5751,28 @@ function reducer(state, action) {
|
|
|
5378
5751
|
if (!state.localParticipant)
|
|
5379
5752
|
return state;
|
|
5380
5753
|
return Object.assign(Object.assign({}, state), { localParticipant: Object.assign(Object.assign({}, state.localParticipant), { displayName: action.payload.displayName }) });
|
|
5754
|
+
case "WAITING_PARTICIPANT_JOINED":
|
|
5755
|
+
return Object.assign(Object.assign({}, state), { waitingParticipants: [
|
|
5756
|
+
...state.waitingParticipants,
|
|
5757
|
+
{ id: action.payload.participantId, displayName: action.payload.displayName },
|
|
5758
|
+
] });
|
|
5759
|
+
case "WAITING_PARTICIPANT_LEFT":
|
|
5760
|
+
return Object.assign(Object.assign({}, state), { waitingParticipants: state.waitingParticipants.filter((wp) => wp.id !== action.payload.participantId) });
|
|
5381
5761
|
default:
|
|
5382
5762
|
throw state;
|
|
5383
5763
|
}
|
|
5384
|
-
}
|
|
5385
|
-
|
|
5764
|
+
}
|
|
5386
5765
|
function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
5387
|
-
const [roomConnection
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5766
|
+
const [roomConnection] = useState(() => {
|
|
5767
|
+
var _a;
|
|
5768
|
+
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 }));
|
|
5769
|
+
});
|
|
5770
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
5392
5771
|
useEffect(() => {
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5772
|
+
roomConnection.addEventListener("chat_message", (e) => {
|
|
5773
|
+
const chatMessage = e.detail;
|
|
5774
|
+
dispatch({ type: "CHAT_MESSAGE", payload: chatMessage });
|
|
5775
|
+
});
|
|
5396
5776
|
roomConnection.addEventListener("participant_audio_enabled", (e) => {
|
|
5397
5777
|
const { participantId, isAudioEnabled } = e.detail;
|
|
5398
5778
|
dispatch({ type: "PARTICIPANT_AUDIO_ENABLED", payload: { participantId, isAudioEnabled } });
|
|
@@ -5409,9 +5789,13 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
|
5409
5789
|
const { participantId, stream } = e.detail;
|
|
5410
5790
|
dispatch({ type: "PARTICIPANT_STREAM_ADDED", payload: { participantId, stream } });
|
|
5411
5791
|
});
|
|
5792
|
+
roomConnection.addEventListener("room_connection_status_changed", (e) => {
|
|
5793
|
+
const { roomConnectionStatus } = e.detail;
|
|
5794
|
+
dispatch({ type: "ROOM_CONNECTION_STATUS_CHANGED", payload: { roomConnectionStatus } });
|
|
5795
|
+
});
|
|
5412
5796
|
roomConnection.addEventListener("room_joined", (e) => {
|
|
5413
|
-
const { localParticipant, remoteParticipants } = e.detail;
|
|
5414
|
-
dispatch({ type: "ROOM_JOINED", payload: { localParticipant, remoteParticipants } });
|
|
5797
|
+
const { localParticipant, remoteParticipants, waitingParticipants } = e.detail;
|
|
5798
|
+
dispatch({ type: "ROOM_JOINED", payload: { localParticipant, remoteParticipants, waitingParticipants } });
|
|
5415
5799
|
});
|
|
5416
5800
|
roomConnection.addEventListener("participant_video_enabled", (e) => {
|
|
5417
5801
|
const { participantId, isVideoEnabled } = e.detail;
|
|
@@ -5421,31 +5805,52 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
|
5421
5805
|
const { participantId, displayName } = e.detail;
|
|
5422
5806
|
dispatch({ type: "PARTICIPANT_METADATA_CHANGED", payload: { participantId, displayName } });
|
|
5423
5807
|
});
|
|
5808
|
+
roomConnection.addEventListener("waiting_participant_joined", (e) => {
|
|
5809
|
+
const { participantId, displayName } = e.detail;
|
|
5810
|
+
dispatch({ type: "WAITING_PARTICIPANT_JOINED", payload: { participantId, displayName } });
|
|
5811
|
+
});
|
|
5812
|
+
roomConnection.addEventListener("waiting_participant_left", (e) => {
|
|
5813
|
+
const { participantId } = e.detail;
|
|
5814
|
+
dispatch({ type: "WAITING_PARTICIPANT_LEFT", payload: { participantId } });
|
|
5815
|
+
});
|
|
5424
5816
|
roomConnection.join();
|
|
5425
5817
|
return () => {
|
|
5426
5818
|
roomConnection.leave();
|
|
5427
5819
|
};
|
|
5428
|
-
}, [
|
|
5429
|
-
return
|
|
5820
|
+
}, []);
|
|
5821
|
+
return {
|
|
5430
5822
|
state,
|
|
5431
|
-
{
|
|
5432
|
-
|
|
5433
|
-
roomConnection
|
|
5823
|
+
actions: {
|
|
5824
|
+
knock: () => {
|
|
5825
|
+
roomConnection.knock();
|
|
5434
5826
|
},
|
|
5435
|
-
|
|
5436
|
-
roomConnection
|
|
5827
|
+
sendChatMessage: (text) => {
|
|
5828
|
+
roomConnection.sendChatMessage(text);
|
|
5437
5829
|
},
|
|
5438
5830
|
setDisplayName: (displayName) => {
|
|
5439
|
-
roomConnection
|
|
5831
|
+
roomConnection.setDisplayName(displayName);
|
|
5440
5832
|
dispatch({ type: "LOCAL_CLIENT_DISPLAY_NAME_CHANGED", payload: { displayName } });
|
|
5441
5833
|
},
|
|
5834
|
+
toggleCamera: (enabled) => {
|
|
5835
|
+
roomConnection.localMedia.toggleCameraEnabled(enabled);
|
|
5836
|
+
},
|
|
5837
|
+
toggleMicrophone: (enabled) => {
|
|
5838
|
+
roomConnection.localMedia.toggleMichrophoneEnabled(enabled);
|
|
5839
|
+
},
|
|
5840
|
+
acceptWaitingParticipant: (participantId) => {
|
|
5841
|
+
roomConnection.acceptWaitingParticipant(participantId);
|
|
5842
|
+
},
|
|
5843
|
+
rejectWaitingParticipant: (participantId) => {
|
|
5844
|
+
roomConnection.rejectWaitingParticipant(participantId);
|
|
5845
|
+
},
|
|
5442
5846
|
},
|
|
5443
|
-
{
|
|
5444
|
-
VideoView
|
|
5847
|
+
components: {
|
|
5848
|
+
VideoView,
|
|
5445
5849
|
},
|
|
5446
|
-
|
|
5850
|
+
_ref: roomConnection,
|
|
5851
|
+
};
|
|
5447
5852
|
}
|
|
5448
5853
|
|
|
5449
|
-
const sdkVersion = "2.0.0-
|
|
5854
|
+
const sdkVersion = "2.0.0-alpha11";
|
|
5450
5855
|
|
|
5451
|
-
export { sdkVersion, useRoomConnection };
|
|
5856
|
+
export { VideoView, sdkVersion, useLocalMedia, useRoomConnection };
|