@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
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var heresy = require('heresy');
|
|
6
|
-
var React = require('react');
|
|
7
6
|
var tslib = require('tslib');
|
|
7
|
+
var React = require('react');
|
|
8
8
|
var adapter = require('webrtc-adapter');
|
|
9
9
|
var io = require('socket.io-client');
|
|
10
10
|
var SDPUtils = require('sdp');
|
|
@@ -94,8 +94,7 @@ heresy.define("WherebyEmbed", {
|
|
|
94
94
|
// Commands
|
|
95
95
|
_postCommand(command, args = []) {
|
|
96
96
|
if (this.iframe.current) {
|
|
97
|
-
|
|
98
|
-
this.iframe.current.contentWindow.postMessage({ command, args }, url.origin);
|
|
97
|
+
this.iframe.current.contentWindow.postMessage({ command, args }, this.url.origin);
|
|
99
98
|
}
|
|
100
99
|
},
|
|
101
100
|
startRecording() {
|
|
@@ -114,8 +113,7 @@ heresy.define("WherebyEmbed", {
|
|
|
114
113
|
this._postCommand("toggle_screenshare", [enabled]);
|
|
115
114
|
},
|
|
116
115
|
onmessage({ origin, data }) {
|
|
117
|
-
|
|
118
|
-
if (origin !== url.origin)
|
|
116
|
+
if (origin !== this.url.origin)
|
|
119
117
|
return;
|
|
120
118
|
const { type, payload: detail } = data;
|
|
121
119
|
this.dispatchEvent(new CustomEvent(type, { detail }));
|
|
@@ -125,36 +123,290 @@ heresy.define("WherebyEmbed", {
|
|
|
125
123
|
if (!room)
|
|
126
124
|
return this.html `Whereby: Missing room attribute.`;
|
|
127
125
|
// Get subdomain from room URL, or use it specified
|
|
128
|
-
const m = /https:\/\/([^.]+)\.whereby.com\/.+/.exec(room);
|
|
126
|
+
const m = /https:\/\/([^.]+)(\.whereby.com|-ip-\d+-\d+-\d+-\d+.hereby.dev:4443)\/.+/.exec(room);
|
|
129
127
|
const subdomain = (m && m[1]) || this.subdomain;
|
|
130
128
|
if (!subdomain)
|
|
131
129
|
return this.html `Whereby: Missing subdomain attr.`;
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
if (!m) {
|
|
131
|
+
return this.html `could not parse URL.`;
|
|
132
|
+
}
|
|
133
|
+
const baseURL = m[2] || `.whereby.com`;
|
|
134
|
+
this.url = new URL(room, `https://${subdomain}${baseURL}`);
|
|
135
|
+
const roomUrl = new URL(room);
|
|
136
|
+
if (roomUrl.searchParams.get("roomKey")) {
|
|
137
|
+
this.url.searchParams.append("roomKey", roomUrl.searchParams.get("roomKey"));
|
|
138
|
+
}
|
|
139
|
+
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(
|
|
134
140
|
// add to URL if set in any way
|
|
135
141
|
(o, v) => (this[v.toLowerCase()] != null ? Object.assign(Object.assign({}, o), { [v]: this[v.toLowerCase()] }) : o), {}))).forEach(([k, v]) => {
|
|
136
|
-
if (!url.searchParams.has(k) && typeof v === "string") {
|
|
137
|
-
url.searchParams.set(k, v);
|
|
142
|
+
if (!this.url.searchParams.has(k) && typeof v === "string") {
|
|
143
|
+
this.url.searchParams.set(k, v);
|
|
138
144
|
}
|
|
139
145
|
});
|
|
140
146
|
return this.html `
|
|
141
147
|
<iframe
|
|
142
148
|
ref=${this.iframe}
|
|
143
|
-
src=${url}
|
|
149
|
+
src=${this.url}
|
|
144
150
|
allow="autoplay; camera; microphone; fullscreen; speaker; display-capture" />
|
|
145
151
|
`;
|
|
146
152
|
},
|
|
147
153
|
});
|
|
148
154
|
|
|
149
|
-
var
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
155
|
+
var VideoView = (_a) => {
|
|
156
|
+
var { muted, stream } = _a, rest = tslib.__rest(_a, ["muted", "stream"]);
|
|
157
|
+
const videoEl = React.useRef(null);
|
|
158
|
+
React.useEffect(() => {
|
|
159
|
+
if (!videoEl.current) {
|
|
160
|
+
return;
|
|
153
161
|
}
|
|
154
|
-
|
|
155
|
-
|
|
162
|
+
if (videoEl.current.srcObject !== stream) {
|
|
163
|
+
videoEl.current.srcObject = stream;
|
|
164
|
+
}
|
|
165
|
+
// Handle muting programatically, not as video attribute
|
|
166
|
+
// https://stackoverflow.com/questions/14111917/html5-video-muted-but-still-playing
|
|
167
|
+
if (videoEl.current.muted !== muted) {
|
|
168
|
+
videoEl.current.muted = Boolean(muted);
|
|
169
|
+
}
|
|
170
|
+
}, [muted, stream, videoEl]);
|
|
171
|
+
return React__default["default"].createElement("video", Object.assign({ ref: videoEl, autoPlay: true, playsInline: true }, rest));
|
|
156
172
|
};
|
|
157
173
|
|
|
174
|
+
const TypedLocalMediaEventTarget = EventTarget;
|
|
175
|
+
class LocalMedia extends TypedLocalMediaEventTarget {
|
|
176
|
+
constructor(constraints) {
|
|
177
|
+
super();
|
|
178
|
+
this._constraints = constraints;
|
|
179
|
+
this.stream = new MediaStream();
|
|
180
|
+
this._rtcManagers = [];
|
|
181
|
+
navigator.mediaDevices.addEventListener("devicechange", this._updateDeviceList.bind(this));
|
|
182
|
+
}
|
|
183
|
+
addRtcManager(rtcManager) {
|
|
184
|
+
this._rtcManagers.push(rtcManager);
|
|
185
|
+
}
|
|
186
|
+
removeRtcManager(rtcManager) {
|
|
187
|
+
this._rtcManagers = this._rtcManagers.filter((r) => r !== rtcManager);
|
|
188
|
+
}
|
|
189
|
+
getCameraDeviceId() {
|
|
190
|
+
var _a;
|
|
191
|
+
return (_a = this.stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
|
|
192
|
+
}
|
|
193
|
+
getMicrophoneDeviceId() {
|
|
194
|
+
var _a;
|
|
195
|
+
return (_a = this.stream.getAudioTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
|
|
196
|
+
}
|
|
197
|
+
isCameraEnabled() {
|
|
198
|
+
var _a;
|
|
199
|
+
return !!((_a = this.stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.enabled);
|
|
200
|
+
}
|
|
201
|
+
isMicrophoneEnabled() {
|
|
202
|
+
var _a;
|
|
203
|
+
return !!((_a = this.stream.getAudioTracks()[0]) === null || _a === void 0 ? void 0 : _a.enabled);
|
|
204
|
+
}
|
|
205
|
+
toggleCameraEnabled(enabled) {
|
|
206
|
+
const videoTrack = this.stream.getVideoTracks()[0];
|
|
207
|
+
if (!videoTrack) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const newValue = enabled !== null && enabled !== void 0 ? enabled : !videoTrack.enabled;
|
|
211
|
+
videoTrack.enabled = newValue;
|
|
212
|
+
this.dispatchEvent(new CustomEvent("camera_enabled", { detail: { enabled: newValue } }));
|
|
213
|
+
}
|
|
214
|
+
toggleMichrophoneEnabled(enabled) {
|
|
215
|
+
const audioTrack = this.stream.getAudioTracks()[0];
|
|
216
|
+
if (!audioTrack) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const newValue = enabled !== null && enabled !== void 0 ? enabled : !audioTrack.enabled;
|
|
220
|
+
audioTrack.enabled = newValue;
|
|
221
|
+
this.dispatchEvent(new CustomEvent("microphone_enabled", { detail: { enabled: newValue } }));
|
|
222
|
+
}
|
|
223
|
+
setCameraDevice(deviceId) {
|
|
224
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
225
|
+
const newStream = yield navigator.mediaDevices.getUserMedia({ video: { deviceId } });
|
|
226
|
+
const newVideoTrack = newStream.getVideoTracks()[0];
|
|
227
|
+
if (newVideoTrack) {
|
|
228
|
+
const oldVideoTrack = this.stream.getVideoTracks()[0];
|
|
229
|
+
newVideoTrack.enabled = oldVideoTrack.enabled;
|
|
230
|
+
oldVideoTrack === null || oldVideoTrack === void 0 ? void 0 : oldVideoTrack.stop();
|
|
231
|
+
this._rtcManagers.forEach((rtcManager) => {
|
|
232
|
+
rtcManager.replaceTrack(oldVideoTrack, newVideoTrack);
|
|
233
|
+
});
|
|
234
|
+
this.stream.removeTrack(oldVideoTrack);
|
|
235
|
+
this.stream.addTrack(newVideoTrack);
|
|
236
|
+
}
|
|
237
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
238
|
+
detail: { stream: this.stream },
|
|
239
|
+
}));
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
setMicrophoneDevice(deviceId) {
|
|
243
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
244
|
+
const newStream = yield navigator.mediaDevices.getUserMedia({ audio: { deviceId } });
|
|
245
|
+
const newAudioTrack = newStream.getAudioTracks()[0];
|
|
246
|
+
const oldAudioTrack = this.stream.getAudioTracks()[0];
|
|
247
|
+
if (oldAudioTrack) {
|
|
248
|
+
newAudioTrack.enabled = oldAudioTrack.enabled;
|
|
249
|
+
oldAudioTrack.stop();
|
|
250
|
+
this.stream.removeTrack(oldAudioTrack);
|
|
251
|
+
}
|
|
252
|
+
this._rtcManagers.forEach((rtcManager) => {
|
|
253
|
+
rtcManager.replaceTrack(oldAudioTrack, newAudioTrack);
|
|
254
|
+
});
|
|
255
|
+
this.stream.addTrack(newAudioTrack);
|
|
256
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
257
|
+
detail: { stream: this.stream },
|
|
258
|
+
}));
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
_updateDeviceList() {
|
|
262
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
263
|
+
try {
|
|
264
|
+
const devices = yield navigator.mediaDevices.enumerateDevices();
|
|
265
|
+
this.dispatchEvent(new CustomEvent("device_list_updated", {
|
|
266
|
+
detail: {
|
|
267
|
+
cameraDevices: devices.filter((d) => d.kind === "videoinput"),
|
|
268
|
+
microphoneDevices: devices.filter((d) => d.kind === "audioinput"),
|
|
269
|
+
speakerDevices: devices.filter((d) => d.kind === "audiooutput"),
|
|
270
|
+
},
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
this.dispatchEvent(new CustomEvent("device_list_update_error", {
|
|
275
|
+
detail: {
|
|
276
|
+
error,
|
|
277
|
+
},
|
|
278
|
+
}));
|
|
279
|
+
throw error;
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
start() {
|
|
284
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
285
|
+
const newStream = yield navigator.mediaDevices.getUserMedia(this._constraints);
|
|
286
|
+
newStream.getTracks().forEach((t) => this.stream.addTrack(t));
|
|
287
|
+
this._updateDeviceList();
|
|
288
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
289
|
+
detail: { stream: this.stream },
|
|
290
|
+
}));
|
|
291
|
+
return this.stream;
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
stop() {
|
|
295
|
+
var _a;
|
|
296
|
+
(_a = this.stream) === null || _a === void 0 ? void 0 : _a.getTracks().forEach((t) => {
|
|
297
|
+
t.stop();
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const initialState$1 = {
|
|
303
|
+
cameraDeviceError: null,
|
|
304
|
+
cameraDevices: [],
|
|
305
|
+
isSettingCameraDevice: false,
|
|
306
|
+
isSettingMicrophoneDevice: false,
|
|
307
|
+
isStarting: false,
|
|
308
|
+
microphoneDeviceError: null,
|
|
309
|
+
microphoneDevices: [],
|
|
310
|
+
speakerDevices: [],
|
|
311
|
+
startError: null,
|
|
312
|
+
};
|
|
313
|
+
function reducer$1(state, action) {
|
|
314
|
+
switch (action.type) {
|
|
315
|
+
case "DEVICE_LIST_UPDATED":
|
|
316
|
+
return Object.assign(Object.assign({}, state), action.payload);
|
|
317
|
+
case "LOCAL_STREAM_UPDATED":
|
|
318
|
+
return Object.assign(Object.assign({}, state), { currentCameraDeviceId: action.payload.currentCameraDeviceId, currentMicrophoneDeviceId: action.payload.currentMicrophoneDeviceId, localStream: action.payload.stream });
|
|
319
|
+
case "SET_CAMERA_DEVICE":
|
|
320
|
+
return Object.assign(Object.assign({}, state), { cameraDeviceError: null, isSettingCameraDevice: true });
|
|
321
|
+
case "SET_CAMERA_DEVICE_COMPLETE":
|
|
322
|
+
return Object.assign(Object.assign({}, state), { isSettingCameraDevice: false });
|
|
323
|
+
case "SET_CAMERA_DEVICE_ERROR":
|
|
324
|
+
return Object.assign(Object.assign({}, state), { cameraDeviceError: action.payload, isSettingCameraDevice: false });
|
|
325
|
+
case "SET_MICROPHONE_DEVICE":
|
|
326
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: true, microphoneDeviceError: null });
|
|
327
|
+
case "SET_MICROPHONE_DEVICE_COMPLETE":
|
|
328
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: false });
|
|
329
|
+
case "SET_MICROPHONE_DEVICE_ERROR":
|
|
330
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: false, microphoneDeviceError: action.payload });
|
|
331
|
+
case "START":
|
|
332
|
+
return Object.assign(Object.assign({}, state), { isStarting: true, startError: null });
|
|
333
|
+
case "START_COMPLETE":
|
|
334
|
+
return Object.assign(Object.assign({}, state), { isStarting: false });
|
|
335
|
+
case "START_ERROR":
|
|
336
|
+
return Object.assign(Object.assign({}, state), { isStarting: false, startError: action.payload });
|
|
337
|
+
default:
|
|
338
|
+
return state;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
function useLocalMedia(constraints = { audio: true, video: true }) {
|
|
342
|
+
const [localMedia] = React.useState(() => new LocalMedia(constraints));
|
|
343
|
+
const [state, dispatch] = React.useReducer(reducer$1, initialState$1);
|
|
344
|
+
React.useEffect(() => {
|
|
345
|
+
localMedia.addEventListener("device_list_updated", (e) => {
|
|
346
|
+
const { cameraDevices, microphoneDevices, speakerDevices } = e.detail;
|
|
347
|
+
dispatch({ type: "DEVICE_LIST_UPDATED", payload: { cameraDevices, microphoneDevices, speakerDevices } });
|
|
348
|
+
});
|
|
349
|
+
localMedia.addEventListener("stream_updated", (e) => {
|
|
350
|
+
const { stream } = e.detail;
|
|
351
|
+
dispatch({
|
|
352
|
+
type: "LOCAL_STREAM_UPDATED",
|
|
353
|
+
payload: {
|
|
354
|
+
stream,
|
|
355
|
+
currentCameraDeviceId: localMedia.getCameraDeviceId(),
|
|
356
|
+
currentMicrophoneDeviceId: localMedia.getMicrophoneDeviceId(),
|
|
357
|
+
},
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
const start = () => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
361
|
+
dispatch({ type: "START" });
|
|
362
|
+
try {
|
|
363
|
+
yield localMedia.start();
|
|
364
|
+
dispatch({ type: "START_COMPLETE" });
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
dispatch({ type: "START_ERROR", payload: error });
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
start();
|
|
371
|
+
// Perform cleanup on unmount
|
|
372
|
+
return () => {
|
|
373
|
+
localMedia.stop();
|
|
374
|
+
};
|
|
375
|
+
}, []);
|
|
376
|
+
return {
|
|
377
|
+
state,
|
|
378
|
+
actions: {
|
|
379
|
+
setCameraDevice: (...args) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
380
|
+
dispatch({ type: "SET_CAMERA_DEVICE" });
|
|
381
|
+
try {
|
|
382
|
+
yield localMedia.setCameraDevice(...args);
|
|
383
|
+
dispatch({ type: "SET_CAMERA_DEVICE_COMPLETE" });
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
dispatch({ type: "SET_CAMERA_DEVICE_ERROR", payload: error });
|
|
387
|
+
}
|
|
388
|
+
}),
|
|
389
|
+
setMicrophoneDevice: (...args) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
390
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE" });
|
|
391
|
+
try {
|
|
392
|
+
yield localMedia.setMicrophoneDevice(...args);
|
|
393
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE_COMPLETE" });
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE_ERROR", payload: error });
|
|
397
|
+
}
|
|
398
|
+
}),
|
|
399
|
+
toggleCameraEnabled: (...args) => {
|
|
400
|
+
return localMedia.toggleCameraEnabled(...args);
|
|
401
|
+
},
|
|
402
|
+
toggleMicrophoneEnabled: (...args) => {
|
|
403
|
+
return localMedia.toggleMichrophoneEnabled(...args);
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
_ref: localMedia,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
|
|
158
410
|
const EVENTS = {
|
|
159
411
|
CLIENT_CONNECTION_STATUS_CHANGED: "client_connection_status_changed",
|
|
160
412
|
STREAM_ADDED: "stream_added",
|
|
@@ -285,10 +537,10 @@ class ServerSocket {
|
|
|
285
537
|
}
|
|
286
538
|
|
|
287
539
|
this._socket = io__default["default"](hostName, options);
|
|
288
|
-
this._socket.on("reconnect", () => {
|
|
540
|
+
this._socket.io.on("reconnect", () => {
|
|
289
541
|
this._socket.sendBuffer = [];
|
|
290
542
|
});
|
|
291
|
-
this._socket.on("reconnect_attempt", () => {
|
|
543
|
+
this._socket.io.on("reconnect_attempt", () => {
|
|
292
544
|
if (this._wasConnectedUsingWebsocket) {
|
|
293
545
|
this._socket.io.opts.transports = ["websocket"];
|
|
294
546
|
// only fallback to polling if not safari
|
|
@@ -346,6 +598,10 @@ class ServerSocket {
|
|
|
346
598
|
);
|
|
347
599
|
}
|
|
348
600
|
|
|
601
|
+
getManager() {
|
|
602
|
+
return this._socket.io;
|
|
603
|
+
}
|
|
604
|
+
|
|
349
605
|
isConnecting() {
|
|
350
606
|
return this._socket && this._socket.connecting;
|
|
351
607
|
}
|
|
@@ -1979,10 +2235,11 @@ class VegaParser {
|
|
|
1979
2235
|
}
|
|
1980
2236
|
|
|
1981
2237
|
class VegaConnection extends EventEmitter.EventEmitter {
|
|
1982
|
-
constructor(wsUrl, logger) {
|
|
2238
|
+
constructor(wsUrl, logger, protocol = "whereby-sfu#v4") {
|
|
1983
2239
|
super();
|
|
1984
2240
|
|
|
1985
2241
|
this.wsUrl = wsUrl;
|
|
2242
|
+
this.protocol = protocol;
|
|
1986
2243
|
this.logger = logger;
|
|
1987
2244
|
|
|
1988
2245
|
// This is the map of sent requests that are waiting for a response
|
|
@@ -1991,7 +2248,7 @@ class VegaConnection extends EventEmitter.EventEmitter {
|
|
|
1991
2248
|
}
|
|
1992
2249
|
|
|
1993
2250
|
_setupSocket() {
|
|
1994
|
-
this.socket = new WebSocket(this.wsUrl,
|
|
2251
|
+
this.socket = new WebSocket(this.wsUrl, this.protocol);
|
|
1995
2252
|
this.socket.onopen = this._onOpen.bind(this);
|
|
1996
2253
|
this.socket.onmessage = this._onMessage.bind(this);
|
|
1997
2254
|
this.socket.onclose = this._onClose.bind(this);
|
|
@@ -2011,7 +2268,9 @@ class VegaConnection extends EventEmitter.EventEmitter {
|
|
|
2011
2268
|
}
|
|
2012
2269
|
|
|
2013
2270
|
close() {
|
|
2014
|
-
this.socket
|
|
2271
|
+
if (!this.socket) return;
|
|
2272
|
+
|
|
2273
|
+
this.socket.close();
|
|
2015
2274
|
}
|
|
2016
2275
|
|
|
2017
2276
|
_onOpen() {
|
|
@@ -2023,11 +2282,15 @@ class VegaConnection extends EventEmitter.EventEmitter {
|
|
|
2023
2282
|
_onMessage(event) {
|
|
2024
2283
|
const socketMessage = VegaParser.parse(event.data);
|
|
2025
2284
|
|
|
2285
|
+
if (!socketMessage) {
|
|
2286
|
+
return this.logger.log("VegaConnectionManager: Received invalid message", event.data);
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2026
2289
|
this.logger.log("VegaConnectionManager: Received message", socketMessage);
|
|
2027
2290
|
|
|
2028
|
-
if (socketMessage
|
|
2291
|
+
if (socketMessage.response) {
|
|
2029
2292
|
this._handleResponse(socketMessage);
|
|
2030
|
-
} else if (socketMessage
|
|
2293
|
+
} else if (socketMessage.message) {
|
|
2031
2294
|
this.emit("message", socketMessage);
|
|
2032
2295
|
}
|
|
2033
2296
|
}
|
|
@@ -2134,7 +2397,7 @@ const VIDEO_SETTINGS_VP9 = {
|
|
|
2134
2397
|
codecOptions: {
|
|
2135
2398
|
videoGoogleStartBitrate: 500,
|
|
2136
2399
|
},
|
|
2137
|
-
encodings: [{ scalabilityMode: "
|
|
2400
|
+
encodings: [{ scalabilityMode: "L3T2_KEY", networkPriority: "high" }],
|
|
2138
2401
|
};
|
|
2139
2402
|
|
|
2140
2403
|
const SCREEN_SHARE_SETTINGS = {
|
|
@@ -2143,13 +2406,13 @@ const SCREEN_SHARE_SETTINGS = {
|
|
|
2143
2406
|
|
|
2144
2407
|
const SCREEN_SHARE_SIMULCAST_SETTINGS = {
|
|
2145
2408
|
encodings: [
|
|
2146
|
-
{ dtx: true, maxBitrate: 500000 },
|
|
2147
|
-
{ dtx: true, maxBitrate: 1500000 },
|
|
2409
|
+
{ scaleResolutionDownBy: 2, dtx: true, maxBitrate: 500000 },
|
|
2410
|
+
{ scaleResolutionDownBy: 1, dtx: true, maxBitrate: 1500000 },
|
|
2148
2411
|
],
|
|
2149
2412
|
};
|
|
2150
2413
|
|
|
2151
2414
|
const SCREEN_SHARE_SETTINGS_VP9 = {
|
|
2152
|
-
encodings: [{ scalabilityMode: "
|
|
2415
|
+
encodings: [{ scalabilityMode: "L1T1", dtx: true, networkPriority: "high" }],
|
|
2153
2416
|
};
|
|
2154
2417
|
|
|
2155
2418
|
const getMediaSettings = (kind, isScreenShare, features) => {
|
|
@@ -2165,8 +2428,8 @@ const getMediaSettings = (kind, isScreenShare, features) => {
|
|
|
2165
2428
|
|
|
2166
2429
|
return SCREEN_SHARE_SETTINGS;
|
|
2167
2430
|
} else {
|
|
2168
|
-
if (lowDataModeEnabled) return VIDEO_SETTINGS_SD;
|
|
2169
2431
|
if (vp9On) return VIDEO_SETTINGS_VP9;
|
|
2432
|
+
if (lowDataModeEnabled) return VIDEO_SETTINGS_SD;
|
|
2170
2433
|
|
|
2171
2434
|
return VIDEO_SETTINGS_HD;
|
|
2172
2435
|
}
|
|
@@ -5020,12 +5283,12 @@ class LocalParticipant extends RoomParticipant {
|
|
|
5020
5283
|
}
|
|
5021
5284
|
}
|
|
5022
5285
|
|
|
5023
|
-
const API_BASE_URL = "https://api.
|
|
5286
|
+
const API_BASE_URL = "https://api.whereby.dev";
|
|
5024
5287
|
const SIGNAL_BASE_URL = "wss://signal.appearin.net";
|
|
5025
5288
|
const NON_PERSON_ROLES = ["recorder", "streamer"];
|
|
5026
5289
|
function createSocket() {
|
|
5027
5290
|
const parsedUrl = new URL(SIGNAL_BASE_URL);
|
|
5028
|
-
const path = `${parsedUrl.pathname.replace(/^\/$/, "")}/protocol/socket.io/
|
|
5291
|
+
const path = `${parsedUrl.pathname.replace(/^\/$/, "")}/protocol/socket.io/v4`;
|
|
5029
5292
|
const SOCKET_HOST = parsedUrl.origin;
|
|
5030
5293
|
const socketConf = {
|
|
5031
5294
|
host: SOCKET_HOST,
|
|
@@ -5033,6 +5296,7 @@ function createSocket() {
|
|
|
5033
5296
|
reconnectionDelay: 5000,
|
|
5034
5297
|
reconnectionDelayMax: 30000,
|
|
5035
5298
|
timeout: 10000,
|
|
5299
|
+
withCredentials: true,
|
|
5036
5300
|
};
|
|
5037
5301
|
return new ServerSocket(SOCKET_HOST, socketConf);
|
|
5038
5302
|
}
|
|
@@ -5041,12 +5305,17 @@ const noop = () => {
|
|
|
5041
5305
|
};
|
|
5042
5306
|
const TypedEventTarget = EventTarget;
|
|
5043
5307
|
class RoomConnection extends TypedEventTarget {
|
|
5044
|
-
constructor(roomUrl, { displayName,
|
|
5308
|
+
constructor(roomUrl, { displayName, localMedia, localMediaConstraints, logger, roomKey }) {
|
|
5045
5309
|
super();
|
|
5046
5310
|
this.localParticipant = null;
|
|
5047
5311
|
this.remoteParticipants = [];
|
|
5048
|
-
this.
|
|
5312
|
+
this._ownsLocalMedia = false;
|
|
5313
|
+
this.organizationId = "";
|
|
5314
|
+
this.roomConnectionStatus = "";
|
|
5049
5315
|
this.roomUrl = new URL(roomUrl); // Throw if invalid Whereby room url
|
|
5316
|
+
const searchParams = new URLSearchParams(this.roomUrl.search);
|
|
5317
|
+
this._roomKey = roomKey || searchParams.get("roomKey");
|
|
5318
|
+
this.roomName = this.roomUrl.pathname;
|
|
5050
5319
|
this.logger = logger || {
|
|
5051
5320
|
debug: noop,
|
|
5052
5321
|
error: noop,
|
|
@@ -5054,10 +5323,20 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5054
5323
|
warn: noop,
|
|
5055
5324
|
};
|
|
5056
5325
|
this.displayName = displayName;
|
|
5057
|
-
this.localStream = localStream;
|
|
5058
5326
|
this.localMediaConstraints = localMediaConstraints;
|
|
5059
5327
|
const urls = fromLocation({ host: this.roomUrl.host });
|
|
5060
|
-
//
|
|
5328
|
+
// Set up local media
|
|
5329
|
+
if (localMedia) {
|
|
5330
|
+
this.localMedia = localMedia;
|
|
5331
|
+
}
|
|
5332
|
+
else if (localMediaConstraints) {
|
|
5333
|
+
this.localMedia = new LocalMedia(localMediaConstraints);
|
|
5334
|
+
this._ownsLocalMedia = true;
|
|
5335
|
+
}
|
|
5336
|
+
else {
|
|
5337
|
+
throw new Error("Missing constraints");
|
|
5338
|
+
}
|
|
5339
|
+
// Set up services
|
|
5061
5340
|
this.credentialsService = CredentialsService.create({ baseUrl: API_BASE_URL });
|
|
5062
5341
|
this.apiClient = new ApiClient({
|
|
5063
5342
|
fetchDeviceCredentials: this.credentialsService.getCredentials.bind(this.credentialsService),
|
|
@@ -5079,10 +5358,30 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5079
5358
|
// Create signal socket and set up event listeners
|
|
5080
5359
|
this.signalSocket = createSocket();
|
|
5081
5360
|
this.signalSocket.on("new_client", this._handleNewClient.bind(this));
|
|
5361
|
+
this.signalSocket.on("chat_message", this._handleNewChatMessage.bind(this));
|
|
5082
5362
|
this.signalSocket.on("client_left", this._handleClientLeft.bind(this));
|
|
5083
5363
|
this.signalSocket.on("audio_enabled", this._handleClientAudioEnabled.bind(this));
|
|
5084
5364
|
this.signalSocket.on("video_enabled", this._handleClientVideoEnabled.bind(this));
|
|
5085
5365
|
this.signalSocket.on("client_metadata_received", this._handleClientMetadataReceived.bind(this));
|
|
5366
|
+
this.signalSocket.on("knock_handled", this._handleKnockHandled.bind(this));
|
|
5367
|
+
this.signalSocket.on("knocker_left", this._handleKnockerLeft.bind(this));
|
|
5368
|
+
this.signalSocket.on("room_joined", this._handleRoomJoined.bind(this));
|
|
5369
|
+
this.signalSocket.on("room_knocked", this._handleRoomKnocked.bind(this));
|
|
5370
|
+
// Set up local media listeners
|
|
5371
|
+
this.localMedia.addEventListener("camera_enabled", (e) => {
|
|
5372
|
+
const { enabled } = e.detail;
|
|
5373
|
+
this.signalSocket.emit("enable_video", { enabled });
|
|
5374
|
+
});
|
|
5375
|
+
this.localMedia.addEventListener("microphone_enabled", (e) => {
|
|
5376
|
+
const { enabled } = e.detail;
|
|
5377
|
+
this.signalSocket.emit("enable_audio", { enabled });
|
|
5378
|
+
});
|
|
5379
|
+
}
|
|
5380
|
+
get roomKey() {
|
|
5381
|
+
return this._roomKey;
|
|
5382
|
+
}
|
|
5383
|
+
_handleNewChatMessage(message) {
|
|
5384
|
+
this.dispatchEvent(new CustomEvent("chat_message", { detail: message }));
|
|
5086
5385
|
}
|
|
5087
5386
|
_handleNewClient({ client }) {
|
|
5088
5387
|
if (NON_PERSON_ROLES.includes(client.role.roleName)) {
|
|
@@ -5128,6 +5427,70 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5128
5427
|
detail: { participantId: remoteParticipant.id, displayName },
|
|
5129
5428
|
}));
|
|
5130
5429
|
}
|
|
5430
|
+
_handleKnockHandled(payload) {
|
|
5431
|
+
const { resolution } = payload;
|
|
5432
|
+
if (resolution === "accepted") {
|
|
5433
|
+
this.roomConnectionStatus = "accepted";
|
|
5434
|
+
this._roomKey = payload.metadata.roomKey;
|
|
5435
|
+
this._joinRoom();
|
|
5436
|
+
}
|
|
5437
|
+
else if (resolution === "rejected") {
|
|
5438
|
+
this.roomConnectionStatus = "rejected";
|
|
5439
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5440
|
+
detail: {
|
|
5441
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5442
|
+
},
|
|
5443
|
+
}));
|
|
5444
|
+
}
|
|
5445
|
+
}
|
|
5446
|
+
_handleKnockerLeft(payload) {
|
|
5447
|
+
const { clientId } = payload;
|
|
5448
|
+
this.dispatchEvent(new CustomEvent("waiting_participant_left", {
|
|
5449
|
+
detail: { participantId: clientId },
|
|
5450
|
+
}));
|
|
5451
|
+
}
|
|
5452
|
+
_handleRoomJoined(event) {
|
|
5453
|
+
const { error, isLocked, room, selfId } = event;
|
|
5454
|
+
if (error === "room_locked" && isLocked) {
|
|
5455
|
+
this.roomConnectionStatus = "room_locked";
|
|
5456
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5457
|
+
detail: {
|
|
5458
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5459
|
+
},
|
|
5460
|
+
}));
|
|
5461
|
+
return;
|
|
5462
|
+
}
|
|
5463
|
+
// Check if we have an error
|
|
5464
|
+
// Check if it is a room joined error
|
|
5465
|
+
// Set state to connect_failed_locked
|
|
5466
|
+
// Set state to connect_failed_no_host
|
|
5467
|
+
if (room) {
|
|
5468
|
+
const { clients, knockers } = room;
|
|
5469
|
+
const localClient = clients.find((c) => c.id === selfId);
|
|
5470
|
+
if (!localClient)
|
|
5471
|
+
throw new Error("Missing local client");
|
|
5472
|
+
this.localParticipant = new LocalParticipant(Object.assign(Object.assign({}, localClient), { stream: this.localMedia.stream || undefined }));
|
|
5473
|
+
this.remoteParticipants = clients
|
|
5474
|
+
.filter((c) => c.id !== selfId)
|
|
5475
|
+
.map((c) => new RemoteParticipant(Object.assign(Object.assign({}, c), { newJoiner: false })));
|
|
5476
|
+
this.roomConnectionStatus = "connected";
|
|
5477
|
+
this.dispatchEvent(new CustomEvent("room_joined", {
|
|
5478
|
+
detail: {
|
|
5479
|
+
localParticipant: this.localParticipant,
|
|
5480
|
+
remoteParticipants: this.remoteParticipants,
|
|
5481
|
+
waitingParticipants: knockers.map((knocker) => {
|
|
5482
|
+
return { id: knocker.clientId, displayName: knocker.displayName };
|
|
5483
|
+
}),
|
|
5484
|
+
},
|
|
5485
|
+
}));
|
|
5486
|
+
}
|
|
5487
|
+
}
|
|
5488
|
+
_handleRoomKnocked(event) {
|
|
5489
|
+
const { clientId, displayName } = event;
|
|
5490
|
+
this.dispatchEvent(new CustomEvent("waiting_participant_joined", {
|
|
5491
|
+
detail: { participantId: clientId, displayName },
|
|
5492
|
+
}));
|
|
5493
|
+
}
|
|
5131
5494
|
_handleRtcEvent(eventName, data) {
|
|
5132
5495
|
if (eventName === "rtc_manager_created") {
|
|
5133
5496
|
return this._handleRtcManagerCreated(data);
|
|
@@ -5140,10 +5503,14 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5140
5503
|
}
|
|
5141
5504
|
}
|
|
5142
5505
|
_handleRtcManagerCreated({ rtcManager }) {
|
|
5143
|
-
var _a
|
|
5506
|
+
var _a;
|
|
5144
5507
|
this.rtcManager = rtcManager;
|
|
5145
|
-
|
|
5146
|
-
|
|
5508
|
+
this.localMedia.addRtcManager(rtcManager);
|
|
5509
|
+
if (this.localMedia.stream) {
|
|
5510
|
+
(_a = this.rtcManager) === null || _a === void 0 ? void 0 : _a.addNewStream("0", this.localMedia.stream, !this.localMedia.isMicrophoneEnabled(), !this.localMedia.isCameraEnabled());
|
|
5511
|
+
}
|
|
5512
|
+
if (this.remoteParticipants.length) {
|
|
5513
|
+
this._handleAcceptStreams(this.remoteParticipants);
|
|
5147
5514
|
}
|
|
5148
5515
|
}
|
|
5149
5516
|
_handleAcceptStreams(remoteParticipants) {
|
|
@@ -5168,8 +5535,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5168
5535
|
if (!newState) {
|
|
5169
5536
|
return;
|
|
5170
5537
|
}
|
|
5171
|
-
// #endregion
|
|
5172
|
-
// #region doAcceptStreams
|
|
5173
5538
|
if (newState === "to_accept" ||
|
|
5174
5539
|
(newState === "new_accept" && shouldAcceptNewClients) ||
|
|
5175
5540
|
(newState === "old_accept" && !shouldAcceptNewClients)) {
|
|
@@ -5193,7 +5558,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5193
5558
|
else ;
|
|
5194
5559
|
// Update stream state
|
|
5195
5560
|
participant.updateStreamState(streamId, streamState.replace(/to_|new_|old_/, "done_"));
|
|
5196
|
-
// #endregion
|
|
5197
5561
|
});
|
|
5198
5562
|
});
|
|
5199
5563
|
}
|
|
@@ -5205,35 +5569,51 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5205
5569
|
}
|
|
5206
5570
|
this.dispatchEvent(new CustomEvent("participant_stream_added", { detail: { participantId: clientId, stream, streamId } }));
|
|
5207
5571
|
}
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5572
|
+
_joinRoom() {
|
|
5573
|
+
this.signalSocket.emit("join_room", {
|
|
5574
|
+
avatarUrl: null,
|
|
5575
|
+
config: {
|
|
5576
|
+
isAudioEnabled: this.localMedia.isMicrophoneEnabled(),
|
|
5577
|
+
isVideoEnabled: this.localMedia.isCameraEnabled(),
|
|
5578
|
+
},
|
|
5579
|
+
deviceCapabilities: { canScreenshare: true },
|
|
5580
|
+
displayName: this.displayName,
|
|
5581
|
+
isCoLocated: false,
|
|
5582
|
+
isDevicePermissionDenied: false,
|
|
5583
|
+
kickFromOtherRooms: false,
|
|
5584
|
+
organizationId: this.organizationId,
|
|
5585
|
+
roomKey: this.roomKey,
|
|
5586
|
+
roomName: this.roomName,
|
|
5587
|
+
selfId: "",
|
|
5588
|
+
userAgent: `browser-sdk:${sdkVersion }`,
|
|
5589
|
+
});
|
|
5590
|
+
}
|
|
5211
5591
|
join() {
|
|
5212
5592
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
5213
|
-
if (["connected", "connecting"].includes(this.
|
|
5214
|
-
console.warn(`Trying to join room state is ${this.
|
|
5593
|
+
if (["connected", "connecting"].includes(this.roomConnectionStatus)) {
|
|
5594
|
+
console.warn(`Trying to join when room state is already ${this.roomConnectionStatus}`);
|
|
5215
5595
|
return;
|
|
5216
5596
|
}
|
|
5217
5597
|
this.logger.log("Joining room");
|
|
5218
|
-
this.
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5598
|
+
this.roomConnectionStatus = "connecting";
|
|
5599
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5600
|
+
detail: {
|
|
5601
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5602
|
+
},
|
|
5603
|
+
}));
|
|
5223
5604
|
const organization = yield this.organizationServiceCache.fetchOrganization();
|
|
5224
5605
|
if (!organization) {
|
|
5225
5606
|
throw new Error("Invalid room url");
|
|
5226
5607
|
}
|
|
5227
|
-
|
|
5228
|
-
|
|
5608
|
+
this.organizationId = organization.organizationId;
|
|
5609
|
+
if (this._ownsLocalMedia) {
|
|
5610
|
+
yield this.localMedia.start();
|
|
5611
|
+
}
|
|
5229
5612
|
const webrtcProvider = {
|
|
5230
|
-
getMediaConstraints: () => {
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
video: !!((_b = this.localStream) === null || _b === void 0 ? void 0 : _b.getVideoTracks().find((t) => t.enabled)),
|
|
5235
|
-
});
|
|
5236
|
-
},
|
|
5613
|
+
getMediaConstraints: () => ({
|
|
5614
|
+
audio: this.localMedia.isMicrophoneEnabled(),
|
|
5615
|
+
video: this.localMedia.isCameraEnabled(),
|
|
5616
|
+
}),
|
|
5237
5617
|
deferrable(clientId) {
|
|
5238
5618
|
return !clientId;
|
|
5239
5619
|
},
|
|
@@ -5256,55 +5636,40 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5256
5636
|
});
|
|
5257
5637
|
// Identify device on signal connection
|
|
5258
5638
|
const deviceCredentials = yield this.credentialsService.getCredentials();
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
this.logger.log("Connected to signal socket");
|
|
5262
|
-
this.signalSocket.emit("identify_device", { deviceCredentials });
|
|
5263
|
-
}, 2000);
|
|
5639
|
+
this.logger.log("Connected to signal socket");
|
|
5640
|
+
this.signalSocket.emit("identify_device", { deviceCredentials });
|
|
5264
5641
|
this.signalSocket.once("device_identified", () => {
|
|
5265
|
-
|
|
5266
|
-
this.signalSocket.emit("join_room", {
|
|
5267
|
-
avatarUrl: null,
|
|
5268
|
-
config: {
|
|
5269
|
-
isAudioEnabled: !!((_a = this.localStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks().find((t) => t.enabled)),
|
|
5270
|
-
isVideoEnabled: !!((_b = this.localStream) === null || _b === void 0 ? void 0 : _b.getVideoTracks().find((t) => t.enabled)),
|
|
5271
|
-
},
|
|
5272
|
-
deviceCapabilities: { canScreenshare: true },
|
|
5273
|
-
displayName: this.displayName,
|
|
5274
|
-
isCoLocated: false,
|
|
5275
|
-
isDevicePermissionDenied: false,
|
|
5276
|
-
kickFromOtherRooms: false,
|
|
5277
|
-
organizationId: organization.organizationId,
|
|
5278
|
-
roomKey: null,
|
|
5279
|
-
roomName: this.roomUrl.pathname,
|
|
5280
|
-
selfId: "",
|
|
5281
|
-
});
|
|
5282
|
-
});
|
|
5283
|
-
this.signalSocket.once("room_joined", (res) => {
|
|
5284
|
-
const { selfId, room: { clients }, } = res;
|
|
5285
|
-
const localClient = clients.find((c) => c.id === selfId);
|
|
5286
|
-
if (!localClient)
|
|
5287
|
-
throw new Error("Missing local client");
|
|
5288
|
-
this.localParticipant = new LocalParticipant(Object.assign(Object.assign({}, localClient), { stream: this.localStream }));
|
|
5289
|
-
this.remoteParticipants = clients
|
|
5290
|
-
.filter((c) => c.id !== selfId)
|
|
5291
|
-
.map((c) => new RemoteParticipant(Object.assign(Object.assign({}, c), { newJoiner: false })));
|
|
5292
|
-
// Accept remote streams if RTC manager has been initialized
|
|
5293
|
-
if (this.rtcManager) {
|
|
5294
|
-
this._handleAcceptStreams(this.remoteParticipants);
|
|
5295
|
-
}
|
|
5296
|
-
this.roomConnectionState = "connected";
|
|
5297
|
-
this.dispatchEvent(new CustomEvent("room_joined", {
|
|
5298
|
-
detail: {
|
|
5299
|
-
localParticipant: this.localParticipant,
|
|
5300
|
-
remoteParticipants: this.remoteParticipants,
|
|
5301
|
-
},
|
|
5302
|
-
}));
|
|
5642
|
+
this._joinRoom();
|
|
5303
5643
|
});
|
|
5304
5644
|
});
|
|
5305
5645
|
}
|
|
5646
|
+
knock() {
|
|
5647
|
+
this.roomConnectionStatus = "knocking";
|
|
5648
|
+
this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
|
|
5649
|
+
detail: {
|
|
5650
|
+
roomConnectionStatus: this.roomConnectionStatus,
|
|
5651
|
+
},
|
|
5652
|
+
}));
|
|
5653
|
+
this.signalSocket.emit("knock_room", {
|
|
5654
|
+
displayName: this.displayName,
|
|
5655
|
+
imageUrl: null,
|
|
5656
|
+
kickFromOtherRooms: true,
|
|
5657
|
+
liveVideo: false,
|
|
5658
|
+
organizationId: this.organizationId,
|
|
5659
|
+
roomKey: this._roomKey,
|
|
5660
|
+
roomName: this.roomName,
|
|
5661
|
+
});
|
|
5662
|
+
}
|
|
5306
5663
|
leave() {
|
|
5307
5664
|
return new Promise((resolve) => {
|
|
5665
|
+
if (this._ownsLocalMedia) {
|
|
5666
|
+
this.localMedia.stop();
|
|
5667
|
+
}
|
|
5668
|
+
if (this.rtcManager) {
|
|
5669
|
+
this.localMedia.removeRtcManager(this.rtcManager);
|
|
5670
|
+
this.rtcManager.disconnectAll();
|
|
5671
|
+
this.rtcManager = undefined;
|
|
5672
|
+
}
|
|
5308
5673
|
if (!this.signalSocket) {
|
|
5309
5674
|
return resolve();
|
|
5310
5675
|
}
|
|
@@ -5319,29 +5684,10 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5319
5684
|
});
|
|
5320
5685
|
});
|
|
5321
5686
|
}
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
this.logger.log("Tried toggling non-existing video track");
|
|
5327
|
-
return;
|
|
5328
|
-
}
|
|
5329
|
-
// TODO: Do stopOrResumeVideo
|
|
5330
|
-
const newValue = enabled !== null && enabled !== void 0 ? enabled : !localVideoTrack.enabled;
|
|
5331
|
-
localVideoTrack.enabled = newValue;
|
|
5332
|
-
this.signalSocket.emit("enable_video", { enabled: newValue });
|
|
5333
|
-
}
|
|
5334
|
-
toggleMicrophone(enabled) {
|
|
5335
|
-
var _a;
|
|
5336
|
-
const localAudioTrack = (_a = this.localStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()[0];
|
|
5337
|
-
if (!localAudioTrack) {
|
|
5338
|
-
this.logger.log("Tried toggling non-existing audio track");
|
|
5339
|
-
return;
|
|
5340
|
-
}
|
|
5341
|
-
// TODO: Do stopOrResumeAudio
|
|
5342
|
-
const newValue = enabled !== null && enabled !== void 0 ? enabled : !localAudioTrack.enabled;
|
|
5343
|
-
localAudioTrack.enabled = newValue;
|
|
5344
|
-
this.signalSocket.emit("enable_audio", { enabled: newValue });
|
|
5687
|
+
sendChatMessage(text) {
|
|
5688
|
+
this.signalSocket.emit("chat_message", {
|
|
5689
|
+
text,
|
|
5690
|
+
});
|
|
5345
5691
|
}
|
|
5346
5692
|
setDisplayName(displayName) {
|
|
5347
5693
|
this.signalSocket.emit("send_client_metadata", {
|
|
@@ -5351,8 +5697,31 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5351
5697
|
},
|
|
5352
5698
|
});
|
|
5353
5699
|
}
|
|
5700
|
+
acceptWaitingParticipant(participantId) {
|
|
5701
|
+
this.signalSocket.emit("handle_knock", {
|
|
5702
|
+
action: "accept",
|
|
5703
|
+
clientId: participantId,
|
|
5704
|
+
response: {},
|
|
5705
|
+
});
|
|
5706
|
+
}
|
|
5707
|
+
rejectWaitingParticipant(participantId) {
|
|
5708
|
+
this.signalSocket.emit("handle_knock", {
|
|
5709
|
+
action: "reject",
|
|
5710
|
+
clientId: participantId,
|
|
5711
|
+
response: {},
|
|
5712
|
+
});
|
|
5713
|
+
}
|
|
5354
5714
|
}
|
|
5355
5715
|
|
|
5716
|
+
const initialState = {
|
|
5717
|
+
chatMessages: [],
|
|
5718
|
+
roomConnectionStatus: "",
|
|
5719
|
+
isJoining: false,
|
|
5720
|
+
joinError: null,
|
|
5721
|
+
mostRecentChatMessage: null,
|
|
5722
|
+
remoteParticipants: [],
|
|
5723
|
+
waitingParticipants: [],
|
|
5724
|
+
};
|
|
5356
5725
|
function updateParticipant(remoteParticipants, participantId, updates) {
|
|
5357
5726
|
const existingParticipant = remoteParticipants.find((p) => p.id === participantId);
|
|
5358
5727
|
if (!existingParticipant) {
|
|
@@ -5367,8 +5736,12 @@ function updateParticipant(remoteParticipants, participantId, updates) {
|
|
|
5367
5736
|
}
|
|
5368
5737
|
function reducer(state, action) {
|
|
5369
5738
|
switch (action.type) {
|
|
5739
|
+
case "CHAT_MESSAGE":
|
|
5740
|
+
return Object.assign(Object.assign({}, state), { chatMessages: [...state.chatMessages, action.payload], mostRecentChatMessage: action.payload });
|
|
5370
5741
|
case "ROOM_JOINED":
|
|
5371
|
-
return Object.assign(Object.assign({}, state), { localParticipant: action.payload.localParticipant, remoteParticipants: action.payload.remoteParticipants, roomConnectionStatus: "connected" });
|
|
5742
|
+
return Object.assign(Object.assign({}, state), { localParticipant: action.payload.localParticipant, remoteParticipants: action.payload.remoteParticipants, waitingParticipants: action.payload.waitingParticipants, roomConnectionStatus: "connected" });
|
|
5743
|
+
case "ROOM_CONNECTION_STATUS_CHANGED":
|
|
5744
|
+
return Object.assign(Object.assign({}, state), { roomConnectionStatus: action.payload.roomConnectionStatus });
|
|
5372
5745
|
case "PARTICIPANT_AUDIO_ENABLED":
|
|
5373
5746
|
return Object.assign(Object.assign({}, state), { remoteParticipants: updateParticipant(state.remoteParticipants, action.payload.participantId, {
|
|
5374
5747
|
isAudioEnabled: action.payload.isAudioEnabled,
|
|
@@ -5393,21 +5766,28 @@ function reducer(state, action) {
|
|
|
5393
5766
|
if (!state.localParticipant)
|
|
5394
5767
|
return state;
|
|
5395
5768
|
return Object.assign(Object.assign({}, state), { localParticipant: Object.assign(Object.assign({}, state.localParticipant), { displayName: action.payload.displayName }) });
|
|
5769
|
+
case "WAITING_PARTICIPANT_JOINED":
|
|
5770
|
+
return Object.assign(Object.assign({}, state), { waitingParticipants: [
|
|
5771
|
+
...state.waitingParticipants,
|
|
5772
|
+
{ id: action.payload.participantId, displayName: action.payload.displayName },
|
|
5773
|
+
] });
|
|
5774
|
+
case "WAITING_PARTICIPANT_LEFT":
|
|
5775
|
+
return Object.assign(Object.assign({}, state), { waitingParticipants: state.waitingParticipants.filter((wp) => wp.id !== action.payload.participantId) });
|
|
5396
5776
|
default:
|
|
5397
5777
|
throw state;
|
|
5398
5778
|
}
|
|
5399
|
-
}
|
|
5400
|
-
|
|
5779
|
+
}
|
|
5401
5780
|
function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
5402
|
-
const [roomConnection
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5781
|
+
const [roomConnection] = React.useState(() => {
|
|
5782
|
+
var _a;
|
|
5783
|
+
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 }));
|
|
5784
|
+
});
|
|
5785
|
+
const [state, dispatch] = React.useReducer(reducer, initialState);
|
|
5407
5786
|
React.useEffect(() => {
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5787
|
+
roomConnection.addEventListener("chat_message", (e) => {
|
|
5788
|
+
const chatMessage = e.detail;
|
|
5789
|
+
dispatch({ type: "CHAT_MESSAGE", payload: chatMessage });
|
|
5790
|
+
});
|
|
5411
5791
|
roomConnection.addEventListener("participant_audio_enabled", (e) => {
|
|
5412
5792
|
const { participantId, isAudioEnabled } = e.detail;
|
|
5413
5793
|
dispatch({ type: "PARTICIPANT_AUDIO_ENABLED", payload: { participantId, isAudioEnabled } });
|
|
@@ -5424,9 +5804,13 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
|
5424
5804
|
const { participantId, stream } = e.detail;
|
|
5425
5805
|
dispatch({ type: "PARTICIPANT_STREAM_ADDED", payload: { participantId, stream } });
|
|
5426
5806
|
});
|
|
5807
|
+
roomConnection.addEventListener("room_connection_status_changed", (e) => {
|
|
5808
|
+
const { roomConnectionStatus } = e.detail;
|
|
5809
|
+
dispatch({ type: "ROOM_CONNECTION_STATUS_CHANGED", payload: { roomConnectionStatus } });
|
|
5810
|
+
});
|
|
5427
5811
|
roomConnection.addEventListener("room_joined", (e) => {
|
|
5428
|
-
const { localParticipant, remoteParticipants } = e.detail;
|
|
5429
|
-
dispatch({ type: "ROOM_JOINED", payload: { localParticipant, remoteParticipants } });
|
|
5812
|
+
const { localParticipant, remoteParticipants, waitingParticipants } = e.detail;
|
|
5813
|
+
dispatch({ type: "ROOM_JOINED", payload: { localParticipant, remoteParticipants, waitingParticipants } });
|
|
5430
5814
|
});
|
|
5431
5815
|
roomConnection.addEventListener("participant_video_enabled", (e) => {
|
|
5432
5816
|
const { participantId, isVideoEnabled } = e.detail;
|
|
@@ -5436,32 +5820,55 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
|
5436
5820
|
const { participantId, displayName } = e.detail;
|
|
5437
5821
|
dispatch({ type: "PARTICIPANT_METADATA_CHANGED", payload: { participantId, displayName } });
|
|
5438
5822
|
});
|
|
5823
|
+
roomConnection.addEventListener("waiting_participant_joined", (e) => {
|
|
5824
|
+
const { participantId, displayName } = e.detail;
|
|
5825
|
+
dispatch({ type: "WAITING_PARTICIPANT_JOINED", payload: { participantId, displayName } });
|
|
5826
|
+
});
|
|
5827
|
+
roomConnection.addEventListener("waiting_participant_left", (e) => {
|
|
5828
|
+
const { participantId } = e.detail;
|
|
5829
|
+
dispatch({ type: "WAITING_PARTICIPANT_LEFT", payload: { participantId } });
|
|
5830
|
+
});
|
|
5439
5831
|
roomConnection.join();
|
|
5440
5832
|
return () => {
|
|
5441
5833
|
roomConnection.leave();
|
|
5442
5834
|
};
|
|
5443
|
-
}, [
|
|
5444
|
-
return
|
|
5835
|
+
}, []);
|
|
5836
|
+
return {
|
|
5445
5837
|
state,
|
|
5446
|
-
{
|
|
5447
|
-
|
|
5448
|
-
roomConnection
|
|
5838
|
+
actions: {
|
|
5839
|
+
knock: () => {
|
|
5840
|
+
roomConnection.knock();
|
|
5449
5841
|
},
|
|
5450
|
-
|
|
5451
|
-
roomConnection
|
|
5842
|
+
sendChatMessage: (text) => {
|
|
5843
|
+
roomConnection.sendChatMessage(text);
|
|
5452
5844
|
},
|
|
5453
5845
|
setDisplayName: (displayName) => {
|
|
5454
|
-
roomConnection
|
|
5846
|
+
roomConnection.setDisplayName(displayName);
|
|
5455
5847
|
dispatch({ type: "LOCAL_CLIENT_DISPLAY_NAME_CHANGED", payload: { displayName } });
|
|
5456
5848
|
},
|
|
5849
|
+
toggleCamera: (enabled) => {
|
|
5850
|
+
roomConnection.localMedia.toggleCameraEnabled(enabled);
|
|
5851
|
+
},
|
|
5852
|
+
toggleMicrophone: (enabled) => {
|
|
5853
|
+
roomConnection.localMedia.toggleMichrophoneEnabled(enabled);
|
|
5854
|
+
},
|
|
5855
|
+
acceptWaitingParticipant: (participantId) => {
|
|
5856
|
+
roomConnection.acceptWaitingParticipant(participantId);
|
|
5857
|
+
},
|
|
5858
|
+
rejectWaitingParticipant: (participantId) => {
|
|
5859
|
+
roomConnection.rejectWaitingParticipant(participantId);
|
|
5860
|
+
},
|
|
5457
5861
|
},
|
|
5458
|
-
{
|
|
5459
|
-
VideoView
|
|
5862
|
+
components: {
|
|
5863
|
+
VideoView,
|
|
5460
5864
|
},
|
|
5461
|
-
|
|
5865
|
+
_ref: roomConnection,
|
|
5866
|
+
};
|
|
5462
5867
|
}
|
|
5463
5868
|
|
|
5464
|
-
const sdkVersion = "2.0.0-
|
|
5869
|
+
const sdkVersion = "2.0.0-alpha11";
|
|
5465
5870
|
|
|
5871
|
+
exports.VideoView = VideoView;
|
|
5466
5872
|
exports.sdkVersion = sdkVersion;
|
|
5873
|
+
exports.useLocalMedia = useLocalMedia;
|
|
5467
5874
|
exports.useRoomConnection = useRoomConnection;
|