@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.esm.js
CHANGED
|
@@ -115,7 +115,7 @@ define("WherebyEmbed", {
|
|
|
115
115
|
if (!subdomain)
|
|
116
116
|
return this.html `Whereby: Missing subdomain attr.`;
|
|
117
117
|
const url = new URL(room, `https://${subdomain}.whereby.com`);
|
|
118
|
-
Object.entries(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ jsApi: true, we: "2.0.0-
|
|
118
|
+
Object.entries(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ jsApi: true, we: "2.0.0-alpha7", iframeSource: subdomain }, (displayName && { displayName })), (lang && { lang })), (metadata && { metadata })), (groups && { groups })), (virtualBackgroundUrl && { virtualBackgroundUrl })), (avatarUrl && { avatarUrl })), (minimal != null && { embed: minimal })), boolAttrs.reduce(
|
|
119
119
|
// add to URL if set in any way
|
|
120
120
|
(o, v) => (this[v.toLowerCase()] != null ? Object.assign(Object.assign({}, o), { [v]: this[v.toLowerCase()] }) : o), {}))).forEach(([k, v]) => {
|
|
121
121
|
if (!url.searchParams.has(k) && typeof v === "string") {
|
|
@@ -150,6 +150,242 @@ var VideoView = (_a) => {
|
|
|
150
150
|
return React.createElement("video", Object.assign({ ref: videoEl, autoPlay: true, playsInline: true }, rest));
|
|
151
151
|
};
|
|
152
152
|
|
|
153
|
+
const TypedLocalMediaEventTarget = EventTarget;
|
|
154
|
+
class LocalMedia extends TypedLocalMediaEventTarget {
|
|
155
|
+
constructor(constraints) {
|
|
156
|
+
super();
|
|
157
|
+
this._constraints = constraints;
|
|
158
|
+
this.stream = new MediaStream();
|
|
159
|
+
this._rtcManagers = [];
|
|
160
|
+
navigator.mediaDevices.addEventListener("devicechange", this._updateDeviceList.bind(this));
|
|
161
|
+
}
|
|
162
|
+
addRtcManager(rtcManager) {
|
|
163
|
+
this._rtcManagers.push(rtcManager);
|
|
164
|
+
}
|
|
165
|
+
removeRtcManager(rtcManager) {
|
|
166
|
+
this._rtcManagers = this._rtcManagers.filter((r) => r !== rtcManager);
|
|
167
|
+
}
|
|
168
|
+
getCameraDeviceId() {
|
|
169
|
+
var _a;
|
|
170
|
+
return (_a = this.stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
|
|
171
|
+
}
|
|
172
|
+
getMicrophoneDeviceId() {
|
|
173
|
+
var _a;
|
|
174
|
+
return (_a = this.stream.getAudioTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
|
|
175
|
+
}
|
|
176
|
+
isCameraEnabled() {
|
|
177
|
+
var _a;
|
|
178
|
+
return !!((_a = this.stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.enabled);
|
|
179
|
+
}
|
|
180
|
+
isMicrophoneEnabled() {
|
|
181
|
+
var _a;
|
|
182
|
+
return !!((_a = this.stream.getAudioTracks()[0]) === null || _a === void 0 ? void 0 : _a.enabled);
|
|
183
|
+
}
|
|
184
|
+
toggleCameraEnabled(enabled) {
|
|
185
|
+
const videoTrack = this.stream.getVideoTracks()[0];
|
|
186
|
+
if (!videoTrack) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const newValue = enabled !== null && enabled !== void 0 ? enabled : !videoTrack.enabled;
|
|
190
|
+
videoTrack.enabled = newValue;
|
|
191
|
+
this.dispatchEvent(new CustomEvent("camera_enabled", { detail: { enabled: newValue } }));
|
|
192
|
+
}
|
|
193
|
+
toggleMichrophoneEnabled(enabled) {
|
|
194
|
+
const audioTrack = this.stream.getAudioTracks()[0];
|
|
195
|
+
if (!audioTrack) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const newValue = enabled !== null && enabled !== void 0 ? enabled : !audioTrack.enabled;
|
|
199
|
+
audioTrack.enabled = newValue;
|
|
200
|
+
this.dispatchEvent(new CustomEvent("microphone_enabled", { detail: { enabled: newValue } }));
|
|
201
|
+
}
|
|
202
|
+
setCameraDevice(deviceId) {
|
|
203
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
204
|
+
const newStream = yield navigator.mediaDevices.getUserMedia({ video: { deviceId } });
|
|
205
|
+
const newVideoTrack = newStream.getVideoTracks()[0];
|
|
206
|
+
if (newVideoTrack) {
|
|
207
|
+
const oldVideoTrack = this.stream.getVideoTracks()[0];
|
|
208
|
+
newVideoTrack.enabled = oldVideoTrack.enabled;
|
|
209
|
+
oldVideoTrack === null || oldVideoTrack === void 0 ? void 0 : oldVideoTrack.stop();
|
|
210
|
+
this._rtcManagers.forEach((rtcManager) => {
|
|
211
|
+
rtcManager.replaceTrack(oldVideoTrack, newVideoTrack);
|
|
212
|
+
});
|
|
213
|
+
this.stream.removeTrack(oldVideoTrack);
|
|
214
|
+
this.stream.addTrack(newVideoTrack);
|
|
215
|
+
}
|
|
216
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
217
|
+
detail: { stream: this.stream },
|
|
218
|
+
}));
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
setMicrophoneDevice(deviceId) {
|
|
222
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
223
|
+
const newStream = yield navigator.mediaDevices.getUserMedia({ audio: { deviceId } });
|
|
224
|
+
const newAudioTrack = newStream.getAudioTracks()[0];
|
|
225
|
+
const oldAudioTrack = this.stream.getAudioTracks()[0];
|
|
226
|
+
if (oldAudioTrack) {
|
|
227
|
+
newAudioTrack.enabled = oldAudioTrack.enabled;
|
|
228
|
+
oldAudioTrack.stop();
|
|
229
|
+
this.stream.removeTrack(oldAudioTrack);
|
|
230
|
+
}
|
|
231
|
+
this._rtcManagers.forEach((rtcManager) => {
|
|
232
|
+
rtcManager.replaceTrack(oldAudioTrack, newAudioTrack);
|
|
233
|
+
});
|
|
234
|
+
this.stream.addTrack(newAudioTrack);
|
|
235
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
236
|
+
detail: { stream: this.stream },
|
|
237
|
+
}));
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
_updateDeviceList() {
|
|
241
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
242
|
+
try {
|
|
243
|
+
const devices = yield navigator.mediaDevices.enumerateDevices();
|
|
244
|
+
this.dispatchEvent(new CustomEvent("device_list_updated", {
|
|
245
|
+
detail: {
|
|
246
|
+
cameraDevices: devices.filter((d) => d.kind === "videoinput"),
|
|
247
|
+
microphoneDevices: devices.filter((d) => d.kind === "audioinput"),
|
|
248
|
+
speakerDevices: devices.filter((d) => d.kind === "audiooutput"),
|
|
249
|
+
},
|
|
250
|
+
}));
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
this.dispatchEvent(new CustomEvent("device_list_update_error", {
|
|
254
|
+
detail: {
|
|
255
|
+
error,
|
|
256
|
+
},
|
|
257
|
+
}));
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
start() {
|
|
263
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
264
|
+
const newStream = yield navigator.mediaDevices.getUserMedia(this._constraints);
|
|
265
|
+
newStream.getTracks().forEach((t) => this.stream.addTrack(t));
|
|
266
|
+
this._updateDeviceList();
|
|
267
|
+
this.dispatchEvent(new CustomEvent("stream_updated", {
|
|
268
|
+
detail: { stream: this.stream },
|
|
269
|
+
}));
|
|
270
|
+
return this.stream;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
stop() {
|
|
274
|
+
var _a;
|
|
275
|
+
(_a = this.stream) === null || _a === void 0 ? void 0 : _a.getTracks().forEach((t) => {
|
|
276
|
+
t.stop();
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const initialState$1 = {
|
|
282
|
+
cameraDeviceError: null,
|
|
283
|
+
cameraDevices: [],
|
|
284
|
+
isSettingCameraDevice: false,
|
|
285
|
+
isSettingMicrophoneDevice: false,
|
|
286
|
+
isStarting: false,
|
|
287
|
+
microphoneDeviceError: null,
|
|
288
|
+
microphoneDevices: [],
|
|
289
|
+
speakerDevices: [],
|
|
290
|
+
startError: null,
|
|
291
|
+
};
|
|
292
|
+
function reducer$1(state, action) {
|
|
293
|
+
switch (action.type) {
|
|
294
|
+
case "DEVICE_LIST_UPDATED":
|
|
295
|
+
return Object.assign(Object.assign({}, state), action.payload);
|
|
296
|
+
case "LOCAL_STREAM_UPDATED":
|
|
297
|
+
return Object.assign(Object.assign({}, state), { currentCameraDeviceId: action.payload.currentCameraDeviceId, currentMicrophoneDeviceId: action.payload.currentMicrophoneDeviceId, localStream: action.payload.stream });
|
|
298
|
+
case "SET_CAMERA_DEVICE":
|
|
299
|
+
return Object.assign(Object.assign({}, state), { cameraDeviceError: null, isSettingCameraDevice: true });
|
|
300
|
+
case "SET_CAMERA_DEVICE_COMPLETE":
|
|
301
|
+
return Object.assign(Object.assign({}, state), { isSettingCameraDevice: false });
|
|
302
|
+
case "SET_CAMERA_DEVICE_ERROR":
|
|
303
|
+
return Object.assign(Object.assign({}, state), { cameraDeviceError: action.payload, isSettingCameraDevice: false });
|
|
304
|
+
case "SET_MICROPHONE_DEVICE":
|
|
305
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: true, microphoneDeviceError: null });
|
|
306
|
+
case "SET_MICROPHONE_DEVICE_COMPLETE":
|
|
307
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: false });
|
|
308
|
+
case "SET_MICROPHONE_DEVICE_ERROR":
|
|
309
|
+
return Object.assign(Object.assign({}, state), { isSettingMicrophoneDevice: false, microphoneDeviceError: action.payload });
|
|
310
|
+
case "START":
|
|
311
|
+
return Object.assign(Object.assign({}, state), { isStarting: true, startError: null });
|
|
312
|
+
case "START_COMPLETE":
|
|
313
|
+
return Object.assign(Object.assign({}, state), { isStarting: false });
|
|
314
|
+
case "START_ERROR":
|
|
315
|
+
return Object.assign(Object.assign({}, state), { isStarting: false, startError: action.payload });
|
|
316
|
+
default:
|
|
317
|
+
return state;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
function useLocalMedia(constraints = { audio: true, video: true }) {
|
|
321
|
+
const [localMedia] = useState(() => new LocalMedia(constraints));
|
|
322
|
+
const [state, dispatch] = useReducer(reducer$1, initialState$1);
|
|
323
|
+
useEffect(() => {
|
|
324
|
+
localMedia.addEventListener("device_list_updated", (e) => {
|
|
325
|
+
const { cameraDevices, microphoneDevices, speakerDevices } = e.detail;
|
|
326
|
+
dispatch({ type: "DEVICE_LIST_UPDATED", payload: { cameraDevices, microphoneDevices, speakerDevices } });
|
|
327
|
+
});
|
|
328
|
+
localMedia.addEventListener("stream_updated", (e) => {
|
|
329
|
+
const { stream } = e.detail;
|
|
330
|
+
dispatch({
|
|
331
|
+
type: "LOCAL_STREAM_UPDATED",
|
|
332
|
+
payload: {
|
|
333
|
+
stream,
|
|
334
|
+
currentCameraDeviceId: localMedia.getCameraDeviceId(),
|
|
335
|
+
currentMicrophoneDeviceId: localMedia.getMicrophoneDeviceId(),
|
|
336
|
+
},
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
const start = () => __awaiter(this, void 0, void 0, function* () {
|
|
340
|
+
dispatch({ type: "START" });
|
|
341
|
+
try {
|
|
342
|
+
yield localMedia.start();
|
|
343
|
+
dispatch({ type: "START_COMPLETE" });
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
dispatch({ type: "START_ERROR", payload: error });
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
start();
|
|
350
|
+
// Perform cleanup on unmount
|
|
351
|
+
return () => {
|
|
352
|
+
localMedia.stop();
|
|
353
|
+
};
|
|
354
|
+
}, []);
|
|
355
|
+
return {
|
|
356
|
+
state,
|
|
357
|
+
actions: {
|
|
358
|
+
setCameraDevice: (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
359
|
+
dispatch({ type: "SET_CAMERA_DEVICE" });
|
|
360
|
+
try {
|
|
361
|
+
yield localMedia.setCameraDevice(...args);
|
|
362
|
+
dispatch({ type: "SET_CAMERA_DEVICE_COMPLETE" });
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
dispatch({ type: "SET_CAMERA_DEVICE_ERROR", payload: error });
|
|
366
|
+
}
|
|
367
|
+
}),
|
|
368
|
+
setMicrophoneDevice: (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
369
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE" });
|
|
370
|
+
try {
|
|
371
|
+
yield localMedia.setMicrophoneDevice(...args);
|
|
372
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE_COMPLETE" });
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
dispatch({ type: "SET_MICROPHONE_DEVICE_ERROR", payload: error });
|
|
376
|
+
}
|
|
377
|
+
}),
|
|
378
|
+
toggleCameraEnabled: (...args) => {
|
|
379
|
+
return localMedia.toggleCameraEnabled(...args);
|
|
380
|
+
},
|
|
381
|
+
toggleMicrophoneEnabled: (...args) => {
|
|
382
|
+
return localMedia.toggleMichrophoneEnabled(...args);
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
_ref: localMedia,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
|
|
153
389
|
const EVENTS = {
|
|
154
390
|
CLIENT_CONNECTION_STATUS_CHANGED: "client_connection_status_changed",
|
|
155
391
|
STREAM_ADDED: "stream_added",
|
|
@@ -280,10 +516,10 @@ class ServerSocket {
|
|
|
280
516
|
}
|
|
281
517
|
|
|
282
518
|
this._socket = io(hostName, options);
|
|
283
|
-
this._socket.on("reconnect", () => {
|
|
519
|
+
this._socket.io.on("reconnect", () => {
|
|
284
520
|
this._socket.sendBuffer = [];
|
|
285
521
|
});
|
|
286
|
-
this._socket.on("reconnect_attempt", () => {
|
|
522
|
+
this._socket.io.on("reconnect_attempt", () => {
|
|
287
523
|
if (this._wasConnectedUsingWebsocket) {
|
|
288
524
|
this._socket.io.opts.transports = ["websocket"];
|
|
289
525
|
// only fallback to polling if not safari
|
|
@@ -341,6 +577,10 @@ class ServerSocket {
|
|
|
341
577
|
);
|
|
342
578
|
}
|
|
343
579
|
|
|
580
|
+
getManager() {
|
|
581
|
+
return this._socket.io;
|
|
582
|
+
}
|
|
583
|
+
|
|
344
584
|
isConnecting() {
|
|
345
585
|
return this._socket && this._socket.connecting;
|
|
346
586
|
}
|
|
@@ -1974,10 +2214,11 @@ class VegaParser {
|
|
|
1974
2214
|
}
|
|
1975
2215
|
|
|
1976
2216
|
class VegaConnection extends EventEmitter {
|
|
1977
|
-
constructor(wsUrl, logger) {
|
|
2217
|
+
constructor(wsUrl, logger, protocol = "whereby-sfu#v4") {
|
|
1978
2218
|
super();
|
|
1979
2219
|
|
|
1980
2220
|
this.wsUrl = wsUrl;
|
|
2221
|
+
this.protocol = protocol;
|
|
1981
2222
|
this.logger = logger;
|
|
1982
2223
|
|
|
1983
2224
|
// This is the map of sent requests that are waiting for a response
|
|
@@ -1986,7 +2227,7 @@ class VegaConnection extends EventEmitter {
|
|
|
1986
2227
|
}
|
|
1987
2228
|
|
|
1988
2229
|
_setupSocket() {
|
|
1989
|
-
this.socket = new WebSocket(this.wsUrl,
|
|
2230
|
+
this.socket = new WebSocket(this.wsUrl, this.protocol);
|
|
1990
2231
|
this.socket.onopen = this._onOpen.bind(this);
|
|
1991
2232
|
this.socket.onmessage = this._onMessage.bind(this);
|
|
1992
2233
|
this.socket.onclose = this._onClose.bind(this);
|
|
@@ -2006,7 +2247,9 @@ class VegaConnection extends EventEmitter {
|
|
|
2006
2247
|
}
|
|
2007
2248
|
|
|
2008
2249
|
close() {
|
|
2009
|
-
this.socket
|
|
2250
|
+
if (!this.socket) return;
|
|
2251
|
+
|
|
2252
|
+
this.socket.close();
|
|
2010
2253
|
}
|
|
2011
2254
|
|
|
2012
2255
|
_onOpen() {
|
|
@@ -2018,11 +2261,15 @@ class VegaConnection extends EventEmitter {
|
|
|
2018
2261
|
_onMessage(event) {
|
|
2019
2262
|
const socketMessage = VegaParser.parse(event.data);
|
|
2020
2263
|
|
|
2264
|
+
if (!socketMessage) {
|
|
2265
|
+
return this.logger.log("VegaConnectionManager: Received invalid message", event.data);
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2021
2268
|
this.logger.log("VegaConnectionManager: Received message", socketMessage);
|
|
2022
2269
|
|
|
2023
|
-
if (socketMessage
|
|
2270
|
+
if (socketMessage.response) {
|
|
2024
2271
|
this._handleResponse(socketMessage);
|
|
2025
|
-
} else if (socketMessage
|
|
2272
|
+
} else if (socketMessage.message) {
|
|
2026
2273
|
this.emit("message", socketMessage);
|
|
2027
2274
|
}
|
|
2028
2275
|
}
|
|
@@ -2129,7 +2376,7 @@ const VIDEO_SETTINGS_VP9 = {
|
|
|
2129
2376
|
codecOptions: {
|
|
2130
2377
|
videoGoogleStartBitrate: 500,
|
|
2131
2378
|
},
|
|
2132
|
-
encodings: [{ scalabilityMode: "
|
|
2379
|
+
encodings: [{ scalabilityMode: "L3T2_KEY", networkPriority: "high" }],
|
|
2133
2380
|
};
|
|
2134
2381
|
|
|
2135
2382
|
const SCREEN_SHARE_SETTINGS = {
|
|
@@ -2138,13 +2385,13 @@ const SCREEN_SHARE_SETTINGS = {
|
|
|
2138
2385
|
|
|
2139
2386
|
const SCREEN_SHARE_SIMULCAST_SETTINGS = {
|
|
2140
2387
|
encodings: [
|
|
2141
|
-
{ dtx: true, maxBitrate: 500000 },
|
|
2142
|
-
{ dtx: true, maxBitrate: 1500000 },
|
|
2388
|
+
{ scaleResolutionDownBy: 2, dtx: true, maxBitrate: 500000 },
|
|
2389
|
+
{ scaleResolutionDownBy: 1, dtx: true, maxBitrate: 1500000 },
|
|
2143
2390
|
],
|
|
2144
2391
|
};
|
|
2145
2392
|
|
|
2146
2393
|
const SCREEN_SHARE_SETTINGS_VP9 = {
|
|
2147
|
-
encodings: [{ scalabilityMode: "
|
|
2394
|
+
encodings: [{ scalabilityMode: "L1T1", dtx: true, networkPriority: "high" }],
|
|
2148
2395
|
};
|
|
2149
2396
|
|
|
2150
2397
|
const getMediaSettings = (kind, isScreenShare, features) => {
|
|
@@ -2160,8 +2407,8 @@ const getMediaSettings = (kind, isScreenShare, features) => {
|
|
|
2160
2407
|
|
|
2161
2408
|
return SCREEN_SHARE_SETTINGS;
|
|
2162
2409
|
} else {
|
|
2163
|
-
if (lowDataModeEnabled) return VIDEO_SETTINGS_SD;
|
|
2164
2410
|
if (vp9On) return VIDEO_SETTINGS_VP9;
|
|
2411
|
+
if (lowDataModeEnabled) return VIDEO_SETTINGS_SD;
|
|
2165
2412
|
|
|
2166
2413
|
return VIDEO_SETTINGS_HD;
|
|
2167
2414
|
}
|
|
@@ -5020,7 +5267,7 @@ const SIGNAL_BASE_URL = "wss://signal.appearin.net";
|
|
|
5020
5267
|
const NON_PERSON_ROLES = ["recorder", "streamer"];
|
|
5021
5268
|
function createSocket() {
|
|
5022
5269
|
const parsedUrl = new URL(SIGNAL_BASE_URL);
|
|
5023
|
-
const path = `${parsedUrl.pathname.replace(/^\/$/, "")}/protocol/socket.io/
|
|
5270
|
+
const path = `${parsedUrl.pathname.replace(/^\/$/, "")}/protocol/socket.io/v4`;
|
|
5024
5271
|
const SOCKET_HOST = parsedUrl.origin;
|
|
5025
5272
|
const socketConf = {
|
|
5026
5273
|
host: SOCKET_HOST,
|
|
@@ -5036,11 +5283,12 @@ const noop = () => {
|
|
|
5036
5283
|
};
|
|
5037
5284
|
const TypedEventTarget = EventTarget;
|
|
5038
5285
|
class RoomConnection extends TypedEventTarget {
|
|
5039
|
-
constructor(roomUrl, { displayName, localMediaConstraints,
|
|
5286
|
+
constructor(roomUrl, { displayName, localMediaConstraints, logger, localMedia }) {
|
|
5040
5287
|
super();
|
|
5041
5288
|
this.localParticipant = null;
|
|
5042
5289
|
this.remoteParticipants = [];
|
|
5043
5290
|
this.roomConnectionState = "";
|
|
5291
|
+
this._ownsLocalMedia = false;
|
|
5044
5292
|
this.roomUrl = new URL(roomUrl); // Throw if invalid Whereby room url
|
|
5045
5293
|
this.logger = logger || {
|
|
5046
5294
|
debug: noop,
|
|
@@ -5049,10 +5297,19 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5049
5297
|
warn: noop,
|
|
5050
5298
|
};
|
|
5051
5299
|
this.displayName = displayName;
|
|
5052
|
-
this.localStream = localStream;
|
|
5053
5300
|
this.localMediaConstraints = localMediaConstraints;
|
|
5054
5301
|
const urls = fromLocation({ host: this.roomUrl.host });
|
|
5055
|
-
//
|
|
5302
|
+
// Set up local media
|
|
5303
|
+
if (localMedia) {
|
|
5304
|
+
this.localMedia = localMedia;
|
|
5305
|
+
}
|
|
5306
|
+
else if (localMediaConstraints) {
|
|
5307
|
+
this.localMedia = new LocalMedia(localMediaConstraints);
|
|
5308
|
+
this._ownsLocalMedia = true;
|
|
5309
|
+
}
|
|
5310
|
+
else {
|
|
5311
|
+
throw new Error("Missing constraints");
|
|
5312
|
+
}
|
|
5056
5313
|
this.credentialsService = CredentialsService.create({ baseUrl: API_BASE_URL });
|
|
5057
5314
|
this.apiClient = new ApiClient({
|
|
5058
5315
|
fetchDeviceCredentials: this.credentialsService.getCredentials.bind(this.credentialsService),
|
|
@@ -5078,6 +5335,15 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5078
5335
|
this.signalSocket.on("audio_enabled", this._handleClientAudioEnabled.bind(this));
|
|
5079
5336
|
this.signalSocket.on("video_enabled", this._handleClientVideoEnabled.bind(this));
|
|
5080
5337
|
this.signalSocket.on("client_metadata_received", this._handleClientMetadataReceived.bind(this));
|
|
5338
|
+
// Set up local media listeners
|
|
5339
|
+
this.localMedia.addEventListener("camera_enabled", (e) => {
|
|
5340
|
+
const { enabled } = e.detail;
|
|
5341
|
+
this.signalSocket.emit("enable_video", { enabled });
|
|
5342
|
+
});
|
|
5343
|
+
this.localMedia.addEventListener("microphone_enabled", (e) => {
|
|
5344
|
+
const { enabled } = e.detail;
|
|
5345
|
+
this.signalSocket.emit("enable_audio", { enabled });
|
|
5346
|
+
});
|
|
5081
5347
|
}
|
|
5082
5348
|
_handleNewClient({ client }) {
|
|
5083
5349
|
if (NON_PERSON_ROLES.includes(client.role.roleName)) {
|
|
@@ -5135,10 +5401,11 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5135
5401
|
}
|
|
5136
5402
|
}
|
|
5137
5403
|
_handleRtcManagerCreated({ rtcManager }) {
|
|
5138
|
-
var _a
|
|
5404
|
+
var _a;
|
|
5139
5405
|
this.rtcManager = rtcManager;
|
|
5140
|
-
|
|
5141
|
-
|
|
5406
|
+
this.localMedia.addRtcManager(rtcManager);
|
|
5407
|
+
if (this.localMedia.stream) {
|
|
5408
|
+
(_a = this.rtcManager) === null || _a === void 0 ? void 0 : _a.addNewStream("0", this.localMedia.stream, !this.localMedia.isMicrophoneEnabled(), !this.localMedia.isCameraEnabled());
|
|
5142
5409
|
}
|
|
5143
5410
|
}
|
|
5144
5411
|
_handleAcceptStreams(remoteParticipants) {
|
|
@@ -5163,8 +5430,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5163
5430
|
if (!newState) {
|
|
5164
5431
|
return;
|
|
5165
5432
|
}
|
|
5166
|
-
// #endregion
|
|
5167
|
-
// #region doAcceptStreams
|
|
5168
5433
|
if (newState === "to_accept" ||
|
|
5169
5434
|
(newState === "new_accept" && shouldAcceptNewClients) ||
|
|
5170
5435
|
(newState === "old_accept" && !shouldAcceptNewClients)) {
|
|
@@ -5188,7 +5453,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5188
5453
|
else ;
|
|
5189
5454
|
// Update stream state
|
|
5190
5455
|
participant.updateStreamState(streamId, streamState.replace(/to_|new_|old_/, "done_"));
|
|
5191
|
-
// #endregion
|
|
5192
5456
|
});
|
|
5193
5457
|
});
|
|
5194
5458
|
}
|
|
@@ -5200,9 +5464,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5200
5464
|
}
|
|
5201
5465
|
this.dispatchEvent(new CustomEvent("participant_stream_added", { detail: { participantId: clientId, stream, streamId } }));
|
|
5202
5466
|
}
|
|
5203
|
-
/**
|
|
5204
|
-
* Public API
|
|
5205
|
-
*/
|
|
5206
5467
|
join() {
|
|
5207
5468
|
return __awaiter(this, void 0, void 0, function* () {
|
|
5208
5469
|
if (["connected", "connecting"].includes(this.roomConnectionState)) {
|
|
@@ -5211,24 +5472,14 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5211
5472
|
}
|
|
5212
5473
|
this.logger.log("Joining room");
|
|
5213
5474
|
this.roomConnectionState = "connecting";
|
|
5214
|
-
if (
|
|
5215
|
-
|
|
5216
|
-
this.localStream = localStream;
|
|
5217
|
-
}
|
|
5218
|
-
const organization = yield this.organizationServiceCache.fetchOrganization();
|
|
5219
|
-
if (!organization) {
|
|
5220
|
-
throw new Error("Invalid room url");
|
|
5475
|
+
if (this._ownsLocalMedia) {
|
|
5476
|
+
yield this.localMedia.start();
|
|
5221
5477
|
}
|
|
5222
|
-
// TODO: Get room permissions
|
|
5223
|
-
// TODO: Get room features
|
|
5224
5478
|
const webrtcProvider = {
|
|
5225
|
-
getMediaConstraints: () => {
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
video: !!((_b = this.localStream) === null || _b === void 0 ? void 0 : _b.getVideoTracks().find((t) => t.enabled)),
|
|
5230
|
-
});
|
|
5231
|
-
},
|
|
5479
|
+
getMediaConstraints: () => ({
|
|
5480
|
+
audio: this.localMedia.isMicrophoneEnabled(),
|
|
5481
|
+
video: this.localMedia.isCameraEnabled(),
|
|
5482
|
+
}),
|
|
5232
5483
|
deferrable(clientId) {
|
|
5233
5484
|
return !clientId;
|
|
5234
5485
|
},
|
|
@@ -5249,20 +5500,24 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5249
5500
|
simulcastScreenshareOn: false,
|
|
5250
5501
|
},
|
|
5251
5502
|
});
|
|
5503
|
+
const organization = yield this.organizationServiceCache.fetchOrganization();
|
|
5504
|
+
if (!organization) {
|
|
5505
|
+
throw new Error("Invalid room url");
|
|
5506
|
+
}
|
|
5252
5507
|
// Identify device on signal connection
|
|
5253
5508
|
const deviceCredentials = yield this.credentialsService.getCredentials();
|
|
5509
|
+
this.signalSocket.connect();
|
|
5254
5510
|
// TODO: Handle connection and failed connection properly
|
|
5255
|
-
|
|
5511
|
+
this.signalSocket.on("connect", () => {
|
|
5256
5512
|
this.logger.log("Connected to signal socket");
|
|
5257
5513
|
this.signalSocket.emit("identify_device", { deviceCredentials });
|
|
5258
|
-
}
|
|
5514
|
+
});
|
|
5259
5515
|
this.signalSocket.once("device_identified", () => {
|
|
5260
|
-
var _a, _b;
|
|
5261
5516
|
this.signalSocket.emit("join_room", {
|
|
5262
5517
|
avatarUrl: null,
|
|
5263
5518
|
config: {
|
|
5264
|
-
isAudioEnabled:
|
|
5265
|
-
isVideoEnabled:
|
|
5519
|
+
isAudioEnabled: this.localMedia.isMicrophoneEnabled(),
|
|
5520
|
+
isVideoEnabled: this.localMedia.isCameraEnabled(),
|
|
5266
5521
|
},
|
|
5267
5522
|
deviceCapabilities: { canScreenshare: true },
|
|
5268
5523
|
displayName: this.displayName,
|
|
@@ -5273,7 +5528,7 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5273
5528
|
roomKey: null,
|
|
5274
5529
|
roomName: this.roomUrl.pathname,
|
|
5275
5530
|
selfId: "",
|
|
5276
|
-
userAgent: `browser-sdk:${sdkVersion }
|
|
5531
|
+
userAgent: `browser-sdk:${sdkVersion }`,
|
|
5277
5532
|
});
|
|
5278
5533
|
});
|
|
5279
5534
|
this.signalSocket.once("room_joined", (res) => {
|
|
@@ -5281,7 +5536,7 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5281
5536
|
const localClient = clients.find((c) => c.id === selfId);
|
|
5282
5537
|
if (!localClient)
|
|
5283
5538
|
throw new Error("Missing local client");
|
|
5284
|
-
this.localParticipant = new LocalParticipant(Object.assign(Object.assign({}, localClient), { stream: this.
|
|
5539
|
+
this.localParticipant = new LocalParticipant(Object.assign(Object.assign({}, localClient), { stream: this.localMedia.stream || undefined }));
|
|
5285
5540
|
this.remoteParticipants = clients
|
|
5286
5541
|
.filter((c) => c.id !== selfId)
|
|
5287
5542
|
.map((c) => new RemoteParticipant(Object.assign(Object.assign({}, c), { newJoiner: false })));
|
|
@@ -5301,6 +5556,14 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5301
5556
|
}
|
|
5302
5557
|
leave() {
|
|
5303
5558
|
return new Promise((resolve) => {
|
|
5559
|
+
if (this._ownsLocalMedia) {
|
|
5560
|
+
this.localMedia.stop();
|
|
5561
|
+
}
|
|
5562
|
+
if (this.rtcManager) {
|
|
5563
|
+
this.localMedia.removeRtcManager(this.rtcManager);
|
|
5564
|
+
this.rtcManager.disconnectAll();
|
|
5565
|
+
this.rtcManager = undefined;
|
|
5566
|
+
}
|
|
5304
5567
|
if (!this.signalSocket) {
|
|
5305
5568
|
return resolve();
|
|
5306
5569
|
}
|
|
@@ -5315,30 +5578,6 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5315
5578
|
});
|
|
5316
5579
|
});
|
|
5317
5580
|
}
|
|
5318
|
-
toggleCamera(enabled) {
|
|
5319
|
-
var _a;
|
|
5320
|
-
const localVideoTrack = (_a = this.localStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()[0];
|
|
5321
|
-
if (!localVideoTrack) {
|
|
5322
|
-
this.logger.log("Tried toggling non-existing video track");
|
|
5323
|
-
return;
|
|
5324
|
-
}
|
|
5325
|
-
// TODO: Do stopOrResumeVideo
|
|
5326
|
-
const newValue = enabled !== null && enabled !== void 0 ? enabled : !localVideoTrack.enabled;
|
|
5327
|
-
localVideoTrack.enabled = newValue;
|
|
5328
|
-
this.signalSocket.emit("enable_video", { enabled: newValue });
|
|
5329
|
-
}
|
|
5330
|
-
toggleMicrophone(enabled) {
|
|
5331
|
-
var _a;
|
|
5332
|
-
const localAudioTrack = (_a = this.localStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()[0];
|
|
5333
|
-
if (!localAudioTrack) {
|
|
5334
|
-
this.logger.log("Tried toggling non-existing audio track");
|
|
5335
|
-
return;
|
|
5336
|
-
}
|
|
5337
|
-
// TODO: Do stopOrResumeAudio
|
|
5338
|
-
const newValue = enabled !== null && enabled !== void 0 ? enabled : !localAudioTrack.enabled;
|
|
5339
|
-
localAudioTrack.enabled = newValue;
|
|
5340
|
-
this.signalSocket.emit("enable_audio", { enabled: newValue });
|
|
5341
|
-
}
|
|
5342
5581
|
setDisplayName(displayName) {
|
|
5343
5582
|
this.signalSocket.emit("send_client_metadata", {
|
|
5344
5583
|
type: "UserData",
|
|
@@ -5349,6 +5588,11 @@ class RoomConnection extends TypedEventTarget {
|
|
|
5349
5588
|
}
|
|
5350
5589
|
}
|
|
5351
5590
|
|
|
5591
|
+
const initialState = {
|
|
5592
|
+
isJoining: false,
|
|
5593
|
+
joinError: null,
|
|
5594
|
+
remoteParticipants: [],
|
|
5595
|
+
};
|
|
5352
5596
|
function updateParticipant(remoteParticipants, participantId, updates) {
|
|
5353
5597
|
const existingParticipant = remoteParticipants.find((p) => p.id === participantId);
|
|
5354
5598
|
if (!existingParticipant) {
|
|
@@ -5392,18 +5636,14 @@ function reducer(state, action) {
|
|
|
5392
5636
|
default:
|
|
5393
5637
|
throw state;
|
|
5394
5638
|
}
|
|
5395
|
-
}
|
|
5396
|
-
|
|
5639
|
+
}
|
|
5397
5640
|
function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
5398
|
-
const [roomConnection
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5641
|
+
const [roomConnection] = useState(() => {
|
|
5642
|
+
var _a;
|
|
5643
|
+
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 }));
|
|
5644
|
+
});
|
|
5645
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
5403
5646
|
useEffect(() => {
|
|
5404
|
-
if (!roomConnection) {
|
|
5405
|
-
return;
|
|
5406
|
-
}
|
|
5407
5647
|
roomConnection.addEventListener("participant_audio_enabled", (e) => {
|
|
5408
5648
|
const { participantId, isAudioEnabled } = e.detail;
|
|
5409
5649
|
dispatch({ type: "PARTICIPANT_AUDIO_ENABLED", payload: { participantId, isAudioEnabled } });
|
|
@@ -5436,27 +5676,28 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
|
|
|
5436
5676
|
return () => {
|
|
5437
5677
|
roomConnection.leave();
|
|
5438
5678
|
};
|
|
5439
|
-
}, [
|
|
5440
|
-
return
|
|
5679
|
+
}, []);
|
|
5680
|
+
return {
|
|
5441
5681
|
state,
|
|
5442
|
-
{
|
|
5682
|
+
actions: {
|
|
5443
5683
|
toggleCamera: (enabled) => {
|
|
5444
|
-
roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.
|
|
5684
|
+
roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.localMedia.toggleCameraEnabled(enabled);
|
|
5445
5685
|
},
|
|
5446
5686
|
toggleMicrophone: (enabled) => {
|
|
5447
|
-
roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.
|
|
5687
|
+
roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.localMedia.toggleMichrophoneEnabled(enabled);
|
|
5448
5688
|
},
|
|
5449
5689
|
setDisplayName: (displayName) => {
|
|
5450
5690
|
roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.setDisplayName(displayName);
|
|
5451
5691
|
dispatch({ type: "LOCAL_CLIENT_DISPLAY_NAME_CHANGED", payload: { displayName } });
|
|
5452
5692
|
},
|
|
5453
5693
|
},
|
|
5454
|
-
{
|
|
5694
|
+
components: {
|
|
5455
5695
|
VideoView,
|
|
5456
5696
|
},
|
|
5457
|
-
|
|
5697
|
+
_ref: roomConnection,
|
|
5698
|
+
};
|
|
5458
5699
|
}
|
|
5459
5700
|
|
|
5460
|
-
const sdkVersion = "2.0.0-
|
|
5701
|
+
const sdkVersion = "2.0.0-alpha7";
|
|
5461
5702
|
|
|
5462
|
-
export { sdkVersion, useRoomConnection };
|
|
5703
|
+
export { VideoView, sdkVersion, useLocalMedia, useRoomConnection };
|