@whereby.com/browser-sdk 2.0.0-alpha5 → 2.0.0-alpha7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -2
- package/dist/lib.cjs.js +334 -91
- package/dist/lib.esm.js +333 -92
- package/dist/types.d.ts +167 -7
- package/dist/v2-alpha7.js +43 -0
- package/package.json +6 -5
- package/dist/v2-alpha5.js +0 -105
package/dist/lib.cjs.js
CHANGED
|
@@ -130,7 +130,7 @@ heresy.define("WherebyEmbed", {
|
|
|
130
130
|
if (!subdomain)
|
|
131
131
|
return this.html `Whereby: Missing subdomain attr.`;
|
|
132
132
|
const url = new URL(room, `https://${subdomain}.whereby.com`);
|
|
133
|
-
Object.entries(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ jsApi: true, we: "2.0.0-
|
|
133
|
+
Object.entries(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ jsApi: true, we: "2.0.0-alpha7", iframeSource: subdomain }, (displayName && { displayName })), (lang && { lang })), (metadata && { metadata })), (groups && { groups })), (virtualBackgroundUrl && { virtualBackgroundUrl })), (avatarUrl && { avatarUrl })), (minimal != null && { embed: minimal })), boolAttrs.reduce(
|
|
134
134
|
// add to URL if set in any way
|
|
135
135
|
(o, v) => (this[v.toLowerCase()] != null ? Object.assign(Object.assign({}, o), { [v]: this[v.toLowerCase()] }) : o), {}))).forEach(([k, v]) => {
|
|
136
136
|
if (!url.searchParams.has(k) && typeof v === "string") {
|
|
@@ -165,6 +165,242 @@ var VideoView = (_a) => {
|
|
|
165
165
|
return React__default["default"].createElement("video", Object.assign({ ref: videoEl, autoPlay: true, playsInline: true }, rest));
|
|
166
166
|
};
|
|
167
167
|
|
|
168
|
+
const TypedLocalMediaEventTarget = EventTarget;
|
|
169
|
+
class LocalMedia extends TypedLocalMediaEventTarget {
|
|
170
|
+
constructor(constraints) {
|
|
171
|
+
super();
|
|
172
|
+
this._constraints = constraints;
|
|
173
|
+
this.stream = new MediaStream();
|
|
174
|
+
this._rtcManagers = [];
|
|
175
|
+
navigator.mediaDevices.addEventListener("devicechange", this._updateDeviceList.bind(this));
|
|
176
|
+
}
|
|
177
|
+
addRtcManager(rtcManager) {
|
|
178
|
+
this._rtcManagers.push(rtcManager);
|
|
179
|
+
}
|
|
180
|
+
removeRtcManager(rtcManager) {
|
|
181
|
+
this._rtcManagers = this._rtcManagers.filter((r) => r !== rtcManager);
|
|
182
|
+
}
|
|
183
|
+
getCameraDeviceId() {
|
|
184
|
+
var _a;
|
|
185
|
+
return (_a = this.stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
|
|
186
|
+
}
|
|
187
|
+
getMicrophoneDeviceId() {
|
|
188
|
+
var _a;
|
|
189
|
+
return (_a = this.stream.getAudioTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
|
|
190
|
+
}
|
|
191
|
+
isCameraEnabled() {
|
|
192
|
+
var _a;
|
|
193
|
+
return !!((_a = this.stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.enabled);
|
|
194
|
+
}
|
|
195
|
+
isMicrophoneEnabled() {
|
|
196
|
+
var _a;
|
|
197
|
+
return !!((_a = this.stream.getAudioTracks()[0]) === null || _a === void 0 ? void 0 : _a.enabled);
|
|
198
|
+
}
|
|
199
|
+
toggleCameraEnabled(enabled) {
|
|
200
|
+
const videoTrack = this.stream.getVideoTracks()[0];
|
|
201
|
+
if (!videoTrack) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const newValue = enabled !== null && enabled !== void 0 ? enabled : !videoTrack.enabled;
|
|
205
|
+
videoTrack.enabled = newValue;
|
|
206
|
+
this.dispatchEvent(new CustomEvent("camera_enabled", { detail: { enabled: newValue } }));
|
|
207
|
+
}
|
|
208
|
+
toggleMichrophoneEnabled(enabled) {
|
|
209
|
+
const audioTrack = this.stream.getAudioTracks()[0];
|
|
210
|
+
if (!audioTrack) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const newValue = enabled !== null && enabled !== void 0 ? enabled : !audioTrack.enabled;
|
|
214
|
+
audioTrack.enabled = newValue;
|
|
215
|
+
this.dispatchEvent(new CustomEvent("microphone_enabled", { detail: { enabled: newValue } }));
|
|
216
|
+
}
|
|
217
|
+
setCameraDevice(deviceId) {
|
|
218
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
219
|
+
const newStream = yield navigator.mediaDevices.getUserMedia({ video: { deviceId } });
|
|
220
|
+
const newVideoTrack = newStream.getVideoTracks()[0];
|
|
221
|
+
if (newVideoTrack) {
|
|
222
|
+
const oldVideoTrack = this.stream.getVideoTracks()[0];
|
|
223
|
+
newVideoTrack.enabled = oldVideoTrack.enabled;
|
|
224
|
+
oldVideoTrack === null || oldVideoTrack === void 0 ? void 0 : oldVideoTrack.stop();
|
|
225
|
+
this._rtcManagers.forEach((rtcManager) => {
|
|
226
|
+
rtcManager.replaceTrack(oldVideoTrack, newVideoTrack);
|
|
227
|
+
});
|
|
228
|
+
this.stream.removeTrack(oldVideoTrack);
|
|
229
|
+
this.stream.addTrack(newVideoTrack);
|
|
230
|
+
}
|
|
231
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
232
|
+
detail: { stream: this.stream },
|
|
233
|
+
}));
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
setMicrophoneDevice(deviceId) {
|
|
237
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
238
|
+
const newStream = yield navigator.mediaDevices.getUserMedia({ audio: { deviceId } });
|
|
239
|
+
const newAudioTrack = newStream.getAudioTracks()[0];
|
|
240
|
+
const oldAudioTrack = this.stream.getAudioTracks()[0];
|
|
241
|
+
if (oldAudioTrack) {
|
|
242
|
+
newAudioTrack.enabled = oldAudioTrack.enabled;
|
|
243
|
+
oldAudioTrack.stop();
|
|
244
|
+
this.stream.removeTrack(oldAudioTrack);
|
|
245
|
+
}
|
|
246
|
+
this._rtcManagers.forEach((rtcManager) => {
|
|
247
|
+
rtcManager.replaceTrack(oldAudioTrack, newAudioTrack);
|
|
248
|
+
});
|
|
249
|
+
this.stream.addTrack(newAudioTrack);
|
|
250
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
251
|
+
detail: { stream: this.stream },
|
|
252
|
+
}));
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
_updateDeviceList() {
|
|
256
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
257
|
+
try {
|
|
258
|
+
const devices = yield navigator.mediaDevices.enumerateDevices();
|
|
259
|
+
this.dispatchEvent(new CustomEvent("device_list_updated", {
|
|
260
|
+
detail: {
|
|
261
|
+
cameraDevices: devices.filter((d) => d.kind === "videoinput"),
|
|
262
|
+
microphoneDevices: devices.filter((d) => d.kind === "audioinput"),
|
|
263
|
+
speakerDevices: devices.filter((d) => d.kind === "audiooutput"),
|
|
264
|
+
},
|
|
265
|
+
}));
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
this.dispatchEvent(new CustomEvent("device_list_update_error", {
|
|
269
|
+
detail: {
|
|
270
|
+
error,
|
|
271
|
+
},
|
|
272
|
+
}));
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
start() {
|
|
278
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
279
|
+
const newStream = yield navigator.mediaDevices.getUserMedia(this._constraints);
|
|
280
|
+
newStream.getTracks().forEach((t) => this.stream.addTrack(t));
|
|
281
|
+
this._updateDeviceList();
|
|
282
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
283
|
+
detail: { stream: this.stream },
|
|
284
|
+
}));
|
|
285
|
+
return this.stream;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
stop() {
|
|
289
|
+
var _a;
|
|
290
|
+
(_a = this.stream) === null || _a === void 0 ? void 0 : _a.getTracks().forEach((t) => {
|
|
291
|
+
t.stop();
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const initialState$1 = {
|
|
297
|
+
cameraDeviceError: null,
|
|
298
|
+
cameraDevices: [],
|
|
299
|
+
isSettingCameraDevice: false,
|
|
300
|
+
isSettingMicrophoneDevice: false,
|
|
301
|
+
isStarting: false,
|
|
302
|
+
microphoneDeviceError: null,
|
|
303
|
+
microphoneDevices: [],
|
|
304
|
+
speakerDevices: [],
|
|
305
|
+
startError: null,
|
|
306
|
+
};
|
|
307
|
+
function reducer$1(state, action) {
|
|
308
|
+
switch (action.type) {
|
|
309
|
+
case "DEVICE_LIST_UPDATED":
|
|
310
|
+
return Object.assign(Object.assign({}, state), action.payload);
|
|
311
|
+
case "LOCAL_STREAM_UPDATED":
|
|
312
|
+
return Object.assign(Object.assign({}, state), { currentCameraDeviceId: action.payload.currentCameraDeviceId, currentMicrophoneDeviceId: action.payload.currentMicrophoneDeviceId, localStream: action.payload.stream });
|
|
313
|
+
case "SET_CAMERA_DEVICE":
|
|
314
|
+
return Object.assign(Object.assign({}, state), { cameraDeviceError: null, isSettingCameraDevice: true });
|
|
315
|
+
case "SET_CAMERA_DEVICE_COMPLETE":
|
|
316
|
+
return Object.assign(Object.assign({}, state), { isSettingCameraDevice: false });
|
|
317
|
+
case "SET_CAMERA_DEVICE_ERROR":
|
|
318
|
+
return Object.assign(Object.assign({}, state), { cameraDeviceError: action.payload, isSettingCameraDevice: false });
|
|
319
|
+
case "SET_MICROPHONE_DEVICE":
|
|
320
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: true, microphoneDeviceError: null });
|
|
321
|
+
case "SET_MICROPHONE_DEVICE_COMPLETE":
|
|
322
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: false });
|
|
323
|
+
case "SET_MICROPHONE_DEVICE_ERROR":
|
|
324
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: false, microphoneDeviceError: action.payload });
|
|
325
|
+
case "START":
|
|
326
|
+
return Object.assign(Object.assign({}, state), { isStarting: true, startError: null });
|
|
327
|
+
case "START_COMPLETE":
|
|
328
|
+
return Object.assign(Object.assign({}, state), { isStarting: false });
|
|
329
|
+
case "START_ERROR":
|
|
330
|
+
return Object.assign(Object.assign({}, state), { isStarting: false, startError: action.payload });
|
|
331
|
+
default:
|
|
332
|
+
return state;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function useLocalMedia(constraints = { audio: true, video: true }) {
|
|
336
|
+
const [localMedia] = React.useState(() => new LocalMedia(constraints));
|
|
337
|
+
const [state, dispatch] = React.useReducer(reducer$1, initialState$1);
|
|
338
|
+
React.useEffect(() => {
|
|
339
|
+
localMedia.addEventListener("device_list_updated", (e) => {
|
|
340
|
+
const { cameraDevices, microphoneDevices, speakerDevices } = e.detail;
|
|
341
|
+
dispatch({ type: "DEVICE_LIST_UPDATED", payload: { cameraDevices, microphoneDevices, speakerDevices } });
|
|
342
|
+
});
|
|
343
|
+
localMedia.addEventListener("stream_updated", (e) => {
|
|
344
|
+
const { stream } = e.detail;
|
|
345
|
+
dispatch({
|
|
346
|
+
type: "LOCAL_STREAM_UPDATED",
|
|
347
|
+
payload: {
|
|
348
|
+
stream,
|
|
349
|
+
currentCameraDeviceId: localMedia.getCameraDeviceId(),
|
|
350
|
+
currentMicrophoneDeviceId: localMedia.getMicrophoneDeviceId(),
|
|
351
|
+
},
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
const start = () => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
355
|
+
dispatch({ type: "START" });
|
|
356
|
+
try {
|
|
357
|
+
yield localMedia.start();
|
|
358
|
+
dispatch({ type: "START_COMPLETE" });
|
|
359
|
+
}
|
|
360
|
+
catch (error) {
|
|
361
|
+
dispatch({ type: "START_ERROR", payload: error });
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
start();
|
|
365
|
+
// Perform cleanup on unmount
|
|
366
|
+
return () => {
|
|
367
|
+
localMedia.stop();
|
|
368
|
+
};
|
|
369
|
+
}, []);
|
|
370
|
+
return {
|
|
371
|
+
state,
|
|
372
|
+
actions: {
|
|
373
|
+
setCameraDevice: (...args) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
374
|
+
dispatch({ type: "SET_CAMERA_DEVICE" });
|
|
375
|
+
try {
|
|
376
|
+
yield localMedia.setCameraDevice(...args);
|
|
377
|
+
dispatch({ type: "SET_CAMERA_DEVICE_COMPLETE" });
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
dispatch({ type: "SET_CAMERA_DEVICE_ERROR", payload: error });
|
|
381
|
+
}
|
|
382
|
+
}),
|
|
383
|
+
setMicrophoneDevice: (...args) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
384
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE" });
|
|
385
|
+
try {
|
|
386
|
+
yield localMedia.setMicrophoneDevice(...args);
|
|
387
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE_COMPLETE" });
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE_ERROR", payload: error });
|
|
391
|
+
}
|
|
392
|
+
}),
|
|
393
|
+
toggleCameraEnabled: (...args) => {
|
|
394
|
+
return localMedia.toggleCameraEnabled(...args);
|
|
395
|
+
},
|
|
396
|
+
toggleMicrophoneEnabled: (...args) => {
|
|
397
|
+
return localMedia.toggleMichrophoneEnabled(...args);
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
_ref: localMedia,
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
168
404
|
const EVENTS = {
|
|
169
405
|
CLIENT_CONNECTION_STATUS_CHANGED: "client_connection_status_changed",
|
|
170
406
|
STREAM_ADDED: "stream_added",
|
|
@@ -295,10 +531,10 @@ class ServerSocket {
|
|
|
295
531
|
}
|
|
296
532
|
|
|
297
533
|
this._socket = io__default["default"](hostName, options);
|
|
298
|
-
this._socket.on("reconnect", () => {
|
|
534
|
+
this._socket.io.on("reconnect", () => {
|
|
299
535
|
this._socket.sendBuffer = [];
|
|
300
536
|
});
|
|
301
|
-
this._socket.on("reconnect_attempt", () => {
|
|
537
|
+
this._socket.io.on("reconnect_attempt", () => {
|
|
302
538
|
if (this._wasConnectedUsingWebsocket) {
|
|
303
539
|
this._socket.io.opts.transports = ["websocket"];
|
|
304
540
|
// only fallback to polling if not safari
|
|
@@ -356,6 +592,10 @@ class ServerSocket {
|
|
|
356
592
|
);
|
|
357
593
|
}
|
|
358
594
|
|
|
595
|
+
getManager() {
|
|
596
|
+
return this._socket.io;
|
|
597
|
+
}
|
|
598
|
+
|
|
359
599
|
isConnecting() {
|
|
360
600
|
return this._socket && this._socket.connecting;
|
|
361
601
|
}
|
|
@@ -1989,10 +2229,11 @@ class VegaParser {
|
|
|
1989
2229
|
}
|
|
1990
2230
|
|
|
1991
2231
|
class VegaConnection extends EventEmitter.EventEmitter {
|
|
1992
|
-
constructor(wsUrl, logger) {
|
|
2232
|
+
constructor(wsUrl, logger, protocol = "whereby-sfu#v4") {
|
|
1993
2233
|
super();
|
|
1994
2234
|
|
|
1995
2235
|
this.wsUrl = wsUrl;
|
|
2236
|
+
this.protocol = protocol;
|
|
1996
2237
|
this.logger = logger;
|
|
1997
2238
|
|
|
1998
2239
|
// This is the map of sent requests that are waiting for a response
|
|
@@ -2001,7 +2242,7 @@ class VegaConnection extends EventEmitter.EventEmitter {
|
|
|
2001
2242
|
}
|
|
2002
2243
|
|
|
2003
2244
|
_setupSocket() {
|
|
2004
|
-
this.socket = new WebSocket(this.wsUrl,
|
|
2245
|
+
this.socket = new WebSocket(this.wsUrl, this.protocol);
|
|
2005
2246
|
this.socket.onopen = this._onOpen.bind(this);
|
|
2006
2247
|
this.socket.onmessage = this._onMessage.bind(this);
|
|
2007
2248
|
this.socket.onclose = this._onClose.bind(this);
|
|
@@ -2021,7 +2262,9 @@ class VegaConnection extends EventEmitter.EventEmitter {
|
|
|
2021
2262
|
}
|
|
2022
2263
|
|
|
2023
2264
|
close() {
|
|
2024
|
-
this.socket
|
|
2265
|
+
if (!this.socket) return;
|
|
2266
|
+
|
|
2267
|
+
this.socket.close();
|
|
2025
2268
|
}
|
|
2026
2269
|
|
|
2027
2270
|
_onOpen() {
|
|
@@ -2033,11 +2276,15 @@ class VegaConnection extends EventEmitter.EventEmitter {
|
|
|
2033
2276
|
_onMessage(event) {
|
|
2034
2277
|
const socketMessage = VegaParser.parse(event.data);
|
|
2035
2278
|
|
|
2279
|
+
if (!socketMessage) {
|
|
2280
|
+
return this.logger.log("VegaConnectionManager: Received invalid message", event.data);
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2036
2283
|
this.logger.log("VegaConnectionManager: Received message", socketMessage);
|
|
2037
2284
|
|
|
2038
|
-
if (socketMessage
|
|
2285
|
+
if (socketMessage.response) {
|
|
2039
2286
|
this._handleResponse(socketMessage);
|
|
2040
|
-
} else if (socketMessage
|
|
2287
|
+
} else if (socketMessage.message) {
|
|
2041
2288
|
this.emit("message", socketMessage);
|
|
2042
2289
|
}
|
|
2043
2290
|
}
|
|
@@ -2144,7 +2391,7 @@ const VIDEO_SETTINGS_VP9 = {
|
|
|
2144
2391
|
codecOptions: {
|
|
2145
2392
|
videoGoogleStartBitrate: 500,
|
|
2146
2393
|
},
|
|
2147
|
-
encodings: [{ scalabilityMode: "
|
|
2394
|
+
encodings: [{ scalabilityMode: "L3T2_KEY", networkPriority: "high" }],
|
|
2148
2395
|
};
|
|
2149
2396
|
|
|
2150
2397
|
const SCREEN_SHARE_SETTINGS = {
|
|
@@ -2153,13 +2400,13 @@ const SCREEN_SHARE_SETTINGS = {
|
|
|
2153
2400
|
|
|
2154
2401
|
const SCREEN_SHARE_SIMULCAST_SETTINGS = {
|
|
2155
2402
|
encodings: [
|
|
2156
|
-
{ dtx: true, maxBitrate: 500000 },
|
|
2157
|
-
{ dtx: true, maxBitrate: 1500000 },
|
|
2403
|
+
{ scaleResolutionDownBy: 2, dtx: true, maxBitrate: 500000 },
|
|
2404
|
+
{ scaleResolutionDownBy: 1, dtx: true, maxBitrate: 1500000 },
|
|
2158
2405
|
],
|
|
2159
2406
|
};
|
|
2160
2407
|
|
|
2161
2408
|
const SCREEN_SHARE_SETTINGS_VP9 = {
|
|
2162
|
-
encodings: [{ scalabilityMode: "
|
|
2409
|
+
encodings: [{ scalabilityMode: "L1T1", dtx: true, networkPriority: "high" }],
|
|
2163
2410
|
};
|
|
2164
2411
|
|
|
2165
2412
|
const getMediaSettings = (kind, isScreenShare, features) => {
|
|
@@ -2175,8 +2422,8 @@ const getMediaSettings = (kind, isScreenShare, features) => {
|
|
|
2175
2422
|
|
|
2176
2423
|
return SCREEN_SHARE_SETTINGS;
|
|
2177
2424
|
} else {
|
|
2178
|
-
if (lowDataModeEnabled) return VIDEO_SETTINGS_SD;
|
|
2179
2425
|
if (vp9On) return VIDEO_SETTINGS_VP9;
|
|
2426
|
+
if (lowDataModeEnabled) return VIDEO_SETTINGS_SD;
|
|
2180
2427
|
|
|
2181
2428
|
return VIDEO_SETTINGS_HD;
|
|
2182
2429
|
}
|
|
@@ -5035,7 +5282,7 @@ const SIGNAL_BASE_URL = "wss://signal.appearin.net";
|
|
|
5035
5282
|
const NON_PERSON_ROLES = ["recorder", "streamer"];
|
|
5036
5283
|
function createSocket() {
|
|
5037
5284
|
const parsedUrl = new URL(SIGNAL_BASE_URL);
|
|
5038
|
-
const path = `${parsedUrl.pathname.replace(/^\/$/, "")}/protocol/socket.io/
|
|
5285
|
+
const path = `${parsedUrl.pathname.replace(/^\/$/, "")}/protocol/socket.io/v4`;
|
|
5039
5286
|
const SOCKET_HOST = parsedUrl.origin;
|
|
5040
5287
|
const socketConf = {
|
|
5041
5288
|
host: SOCKET_HOST,
|
|
@@ -5051,11 +5298,12 @@ const noop = () => {
|
|
|
5051
5298
|
};
|
|
5052
5299
|
const TypedEventTarget = EventTarget;
|
|
5053
5300
|
class RoomConnection extends TypedEventTarget {
|
|
5054
|
-
constructor(roomUrl, { displayName, localMediaConstraints,
|
|
5301
|
+
constructor(roomUrl, { displayName, localMediaConstraints, logger, localMedia }) {
|
|
5055
5302
|
super();
|
|
5056
5303
|
this.localParticipant = null;
|
|
5057
5304
|
this.remoteParticipants = [];
|
|
5058
5305
|
this.roomConnectionState = "";
|
|
5306
|
+
this._ownsLocalMedia = false;
|
|
5059
5307
|
this.roomUrl = new URL(roomUrl); // Throw if invalid Whereby room url
|
|
5060
5308
|
this.logger = logger || {
|
|
5061
5309
|
debug: noop,
|
|
@@ -5064,10 +5312,19 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5064
5312
|
warn: noop,
|
|
5065
5313
|
};
|
|
5066
5314
|
this.displayName = displayName;
|
|
5067
|
-
this.localStream = localStream;
|
|
5068
5315
|
this.localMediaConstraints = localMediaConstraints;
|
|
5069
5316
|
const urls = fromLocation({ host: this.roomUrl.host });
|
|
5070
|
-
//
|
|
5317
|
+
// Set up local media
|
|
5318
|
+
if (localMedia) {
|
|
5319
|
+
this.localMedia = localMedia;
|
|
5320
|
+
}
|
|
5321
|
+
else if (localMediaConstraints) {
|
|
5322
|
+
this.localMedia = new LocalMedia(localMediaConstraints);
|
|
5323
|
+
this._ownsLocalMedia = true;
|
|
5324
|
+
}
|
|
5325
|
+
else {
|
|
5326
|
+
throw new Error("Missing constraints");
|
|
5327
|
+
}
|
|
5071
5328
|
this.credentialsService = CredentialsService.create({ baseUrl: API_BASE_URL });
|
|
5072
5329
|
this.apiClient = new ApiClient({
|
|
5073
5330
|
fetchDeviceCredentials: this.credentialsService.getCredentials.bind(this.credentialsService),
|
|
@@ -5093,6 +5350,15 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5093
5350
|
this.signalSocket.on("audio_enabled", this._handleClientAudioEnabled.bind(this));
|
|
5094
5351
|
this.signalSocket.on("video_enabled", this._handleClientVideoEnabled.bind(this));
|
|
5095
5352
|
this.signalSocket.on("client_metadata_received", this._handleClientMetadataReceived.bind(this));
|
|
5353
|
+
// Set up local media listeners
|
|
5354
|
+
this.localMedia.addEventListener("camera_enabled", (e) => {
|
|
5355
|
+
const { enabled } = e.detail;
|
|
5356
|
+
this.signalSocket.emit("enable_video", { enabled });
|
|
5357
|
+
});
|
|
5358
|
+
this.localMedia.addEventListener("microphone_enabled", (e) => {
|
|
5359
|
+
const { enabled } = e.detail;
|
|
5360
|
+
this.signalSocket.emit("enable_audio", { enabled });
|
|
5361
|
+
});
|
|
5096
5362
|
}
|
|
5097
5363
|
_handleNewClient({ client }) {
|
|
5098
5364
|
if (NON_PERSON_ROLES.includes(client.role.roleName)) {
|
|
@@ -5150,10 +5416,11 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5150
5416
|
}
|
|
5151
5417
|
}
|
|
5152
5418
|
_handleRtcManagerCreated({ rtcManager }) {
|
|
5153
|
-
var _a
|
|
5419
|
+
var _a;
|
|
5154
5420
|
this.rtcManager = rtcManager;
|
|
5155
|
-
|
|
5156
|
-
|
|
5421
|
+
this.localMedia.addRtcManager(rtcManager);
|
|
5422
|
+
if (this.localMedia.stream) {
|
|
5423
|
+
(_a = this.rtcManager) === null || _a === void 0 ? void 0 : _a.addNewStream("0", this.localMedia.stream, !this.localMedia.isMicrophoneEnabled(), !this.localMedia.isCameraEnabled());
|
|
5157
5424
|
}
|
|
5158
5425
|
}
|
|
5159
5426
|
_handleAcceptStreams(remoteParticipants) {
|
|
@@ -5178,8 +5445,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5178
5445
|
if (!newState) {
|
|
5179
5446
|
return;
|
|
5180
5447
|
}
|
|
5181
|
-
// #endregion
|
|
5182
|
-
// #region doAcceptStreams
|
|
5183
5448
|
if (newState === "to_accept" ||
|
|
5184
5449
|
(newState === "new_accept" && shouldAcceptNewClients) ||
|
|
5185
5450
|
(newState === "old_accept" && !shouldAcceptNewClients)) {
|
|
@@ -5203,7 +5468,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5203
5468
|
else ;
|
|
5204
5469
|
// Update stream state
|
|
5205
5470
|
participant.updateStreamState(streamId, streamState.replace(/to_|new_|old_/, "done_"));
|
|
5206
|
-
// #endregion
|
|
5207
5471
|
});
|
|
5208
5472
|
});
|
|
5209
5473
|
}
|
|
@@ -5215,9 +5479,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5215
5479
|
}
|
|
5216
5480
|
this.dispatchEvent(new CustomEvent("participant_stream_added", { detail: { participantId: clientId, stream, streamId } }));
|
|
5217
5481
|
}
|
|
5218
|
-
/**
|
|
5219
|
-
* Public API
|
|
5220
|
-
*/
|
|
5221
5482
|
join() {
|
|
5222
5483
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
5223
5484
|
if (["connected", "connecting"].includes(this.roomConnectionState)) {
|
|
@@ -5226,24 +5487,14 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5226
5487
|
}
|
|
5227
5488
|
this.logger.log("Joining room");
|
|
5228
5489
|
this.roomConnectionState = "connecting";
|
|
5229
|
-
if (
|
|
5230
|
-
|
|
5231
|
-
this.localStream = localStream;
|
|
5232
|
-
}
|
|
5233
|
-
const organization = yield this.organizationServiceCache.fetchOrganization();
|
|
5234
|
-
if (!organization) {
|
|
5235
|
-
throw new Error("Invalid room url");
|
|
5490
|
+
if (this._ownsLocalMedia) {
|
|
5491
|
+
yield this.localMedia.start();
|
|
5236
5492
|
}
|
|
5237
|
-
// TODO: Get room permissions
|
|
5238
|
-
// TODO: Get room features
|
|
5239
5493
|
const webrtcProvider = {
|
|
5240
|
-
getMediaConstraints: () => {
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
video: !!((_b = this.localStream) === null || _b === void 0 ? void 0 : _b.getVideoTracks().find((t) => t.enabled)),
|
|
5245
|
-
});
|
|
5246
|
-
},
|
|
5494
|
+
getMediaConstraints: () => ({
|
|
5495
|
+
audio: this.localMedia.isMicrophoneEnabled(),
|
|
5496
|
+
video: this.localMedia.isCameraEnabled(),
|
|
5497
|
+
}),
|
|
5247
5498
|
deferrable(clientId) {
|
|
5248
5499
|
return !clientId;
|
|
5249
5500
|
},
|
|
@@ -5264,20 +5515,24 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5264
5515
|
simulcastScreenshareOn: false,
|
|
5265
5516
|
},
|
|
5266
5517
|
});
|
|
5518
|
+
const organization = yield this.organizationServiceCache.fetchOrganization();
|
|
5519
|
+
if (!organization) {
|
|
5520
|
+
throw new Error("Invalid room url");
|
|
5521
|
+
}
|
|
5267
5522
|
// Identify device on signal connection
|
|
5268
5523
|
const deviceCredentials = yield this.credentialsService.getCredentials();
|
|
5524
|
+
this.signalSocket.connect();
|
|
5269
5525
|
// TODO: Handle connection and failed connection properly
|
|
5270
|
-
|
|
5526
|
+
this.signalSocket.on("connect", () => {
|
|
5271
5527
|
this.logger.log("Connected to signal socket");
|
|
5272
5528
|
this.signalSocket.emit("identify_device", { deviceCredentials });
|
|
5273
|
-
}
|
|
5529
|
+
});
|
|
5274
5530
|
this.signalSocket.once("device_identified", () => {
|
|
5275
|
-
var _a, _b;
|
|
5276
5531
|
this.signalSocket.emit("join_room", {
|
|
5277
5532
|
avatarUrl: null,
|
|
5278
5533
|
config: {
|
|
5279
|
-
isAudioEnabled:
|
|
5280
|
-
isVideoEnabled:
|
|
5534
|
+
isAudioEnabled: this.localMedia.isMicrophoneEnabled(),
|
|
5535
|
+
isVideoEnabled: this.localMedia.isCameraEnabled(),
|
|
5281
5536
|
},
|
|
5282
5537
|
deviceCapabilities: { canScreenshare: true },
|
|
5283
5538
|
displayName: this.displayName,
|
|
@@ -5288,7 +5543,7 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5288
5543
|
roomKey: null,
|
|
5289
5544
|
roomName: this.roomUrl.pathname,
|
|
5290
5545
|
selfId: "",
|
|
5291
|
-
userAgent: `browser-sdk:${sdkVersion }
|
|
5546
|
+
userAgent: `browser-sdk:${sdkVersion }`,
|
|
5292
5547
|
});
|
|
5293
5548
|
});
|
|
5294
5549
|
this.signalSocket.once("room_joined", (res) => {
|
|
@@ -5296,7 +5551,7 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5296
5551
|
const localClient = clients.find((c) => c.id === selfId);
|
|
5297
5552
|
if (!localClient)
|
|
5298
5553
|
throw new Error("Missing local client");
|
|
5299
|
-
this.localParticipant = new LocalParticipant(Object.assign(Object.assign({}, localClient), { stream: this.
|
|
5554
|
+
this.localParticipant = new LocalParticipant(Object.assign(Object.assign({}, localClient), { stream: this.localMedia.stream || undefined }));
|
|
5300
5555
|
this.remoteParticipants = clients
|
|
5301
5556
|
.filter((c) => c.id !== selfId)
|
|
5302
5557
|
.map((c) => new RemoteParticipant(Object.assign(Object.assign({}, c), { newJoiner: false })));
|
|
@@ -5316,6 +5571,14 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5316
5571
|
}
|
|
5317
5572
|
leave() {
|
|
5318
5573
|
return new Promise((resolve) => {
|
|
5574
|
+
if (this._ownsLocalMedia) {
|
|
5575
|
+
this.localMedia.stop();
|
|
5576
|
+
}
|
|
5577
|
+
if (this.rtcManager) {
|
|
5578
|
+
this.localMedia.removeRtcManager(this.rtcManager);
|
|
5579
|
+
this.rtcManager.disconnectAll();
|
|
5580
|
+
this.rtcManager = undefined;
|
|
5581
|
+
}
|
|
5319
5582
|
if (!this.signalSocket) {
|
|
5320
5583
|
return resolve();
|
|
5321
5584
|
}
|
|
@@ -5330,30 +5593,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5330
5593
|
});
|
|
5331
5594
|
});
|
|
5332
5595
|
}
|
|
5333
|
-
toggleCamera(enabled) {
|
|
5334
|
-
var _a;
|
|
5335
|
-
const localVideoTrack = (_a = this.localStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()[0];
|
|
5336
|
-
if (!localVideoTrack) {
|
|
5337
|
-
this.logger.log("Tried toggling non-existing video track");
|
|
5338
|
-
return;
|
|
5339
|
-
}
|
|
5340
|
-
// TODO: Do stopOrResumeVideo
|
|
5341
|
-
const newValue = enabled !== null && enabled !== void 0 ? enabled : !localVideoTrack.enabled;
|
|
5342
|
-
localVideoTrack.enabled = newValue;
|
|
5343
|
-
this.signalSocket.emit("enable_video", { enabled: newValue });
|
|
5344
|
-
}
|
|
5345
|
-
toggleMicrophone(enabled) {
|
|
5346
|
-
var _a;
|
|
5347
|
-
const localAudioTrack = (_a = this.localStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()[0];
|
|
5348
|
-
if (!localAudioTrack) {
|
|
5349
|
-
this.logger.log("Tried toggling non-existing audio track");
|
|
5350
|
-
return;
|
|
5351
|
-
}
|
|
5352
|
-
// TODO: Do stopOrResumeAudio
|
|
5353
|
-
const newValue = enabled !== null && enabled !== void 0 ? enabled : !localAudioTrack.enabled;
|
|
5354
|
-
localAudioTrack.enabled = newValue;
|
|
5355
|
-
this.signalSocket.emit("enable_audio", { enabled: newValue });
|
|
5356
|
-
}
|
|
5357
5596
|
setDisplayName(displayName) {
|
|
5358
5597
|
this.signalSocket.emit("send_client_metadata", {
|
|
5359
5598
|
type: "UserData",
|
|
@@ -5364,6 +5603,11 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5364
5603
|
}
|
|
5365
5604
|
}
|
|
5366
5605
|
|
|
5606
|
+
const initialState = {
|
|
5607
|
+
isJoining: false,
|
|
5608
|
+
joinError: null,
|
|
5609
|
+
remoteParticipants: [],
|
|
5610
|
+
};
|
|
5367
5611
|
function updateParticipant(remoteParticipants, participantId, updates) {
|
|
5368
5612
|
const existingParticipant = remoteParticipants.find((p) => p.id === participantId);
|
|
5369
5613
|
if (!existingParticipant) {
|
|
@@ -5407,18 +5651,14 @@ function reducer(state, action) {
|
|
|
5407
5651
|
default:
|
|
5408
5652
|
throw state;
|
|
5409
5653
|
}
|
|
5410
|
-
}
|
|
5411
|
-
|
|
5654
|
+
}
|
|
5412
5655
|
function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
5413
|
-
const [roomConnection
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5656
|
+
const [roomConnection] = React.useState(() => {
|
|
5657
|
+
var _a;
|
|
5658
|
+
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 }));
|
|
5659
|
+
});
|
|
5660
|
+
const [state, dispatch] = React.useReducer(reducer, initialState);
|
|
5418
5661
|
React.useEffect(() => {
|
|
5419
|
-
if (!roomConnection) {
|
|
5420
|
-
return;
|
|
5421
|
-
}
|
|
5422
5662
|
roomConnection.addEventListener("participant_audio_enabled", (e) => {
|
|
5423
5663
|
const { participantId, isAudioEnabled } = e.detail;
|
|
5424
5664
|
dispatch({ type: "PARTICIPANT_AUDIO_ENABLED", payload: { participantId, isAudioEnabled } });
|
|
@@ -5451,28 +5691,31 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
|
5451
5691
|
return () => {
|
|
5452
5692
|
roomConnection.leave();
|
|
5453
5693
|
};
|
|
5454
|
-
}, [
|
|
5455
|
-
return
|
|
5694
|
+
}, []);
|
|
5695
|
+
return {
|
|
5456
5696
|
state,
|
|
5457
|
-
{
|
|
5697
|
+
actions: {
|
|
5458
5698
|
toggleCamera: (enabled) => {
|
|
5459
|
-
roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.
|
|
5699
|
+
roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.localMedia.toggleCameraEnabled(enabled);
|
|
5460
5700
|
},
|
|
5461
5701
|
toggleMicrophone: (enabled) => {
|
|
5462
|
-
roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.
|
|
5702
|
+
roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.localMedia.toggleMichrophoneEnabled(enabled);
|
|
5463
5703
|
},
|
|
5464
5704
|
setDisplayName: (displayName) => {
|
|
5465
5705
|
roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.setDisplayName(displayName);
|
|
5466
5706
|
dispatch({ type: "LOCAL_CLIENT_DISPLAY_NAME_CHANGED", payload: { displayName } });
|
|
5467
5707
|
},
|
|
5468
5708
|
},
|
|
5469
|
-
{
|
|
5709
|
+
components: {
|
|
5470
5710
|
VideoView,
|
|
5471
5711
|
},
|
|
5472
|
-
|
|
5712
|
+
_ref: roomConnection,
|
|
5713
|
+
};
|
|
5473
5714
|
}
|
|
5474
5715
|
|
|
5475
|
-
const sdkVersion = "2.0.0-
|
|
5716
|
+
const sdkVersion = "2.0.0-alpha7";
|
|
5476
5717
|
|
|
5718
|
+
exports.VideoView = VideoView;
|
|
5477
5719
|
exports.sdkVersion = sdkVersion;
|
|
5720
|
+
exports.useLocalMedia = useLocalMedia;
|
|
5478
5721
|
exports.useRoomConnection = useRoomConnection;
|