@whereby.com/browser-sdk 2.0.0-alpha → 2.0.0-alpha10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +39 -2
  2. package/dist/lib.cjs +5868 -0
  3. package/dist/lib.esm.js +5850 -0
  4. package/dist/types.d.ts +308 -0
  5. package/dist/v2-alpha10.js +43 -0
  6. package/package.json +12 -6
  7. package/.eslintrc +0 -23
  8. package/.github/actions/build/action.yml +0 -17
  9. package/.github/workflows/deploy.yml +0 -102
  10. package/.github/workflows/test.yml +0 -24
  11. package/.prettierignore +0 -7
  12. package/.prettierrc +0 -4
  13. package/.storybook/main.cjs +0 -16
  14. package/.storybook/preview.js +0 -9
  15. package/jest.config.js +0 -6
  16. package/rollup.config.js +0 -70
  17. package/src/lib/RoomConnection.ts +0 -516
  18. package/src/lib/RoomParticipant.ts +0 -77
  19. package/src/lib/__tests__/embed.unit.ts +0 -77
  20. package/src/lib/api/ApiClient.ts +0 -111
  21. package/src/lib/api/Credentials.ts +0 -45
  22. package/src/lib/api/HttpClient.ts +0 -95
  23. package/src/lib/api/MultipartHttpClient.ts +0 -53
  24. package/src/lib/api/OrganizationApiClient.ts +0 -64
  25. package/src/lib/api/Response.ts +0 -34
  26. package/src/lib/api/credentialsService/index.ts +0 -159
  27. package/src/lib/api/credentialsService/test/index.spec.ts +0 -181
  28. package/src/lib/api/deviceService/index.ts +0 -42
  29. package/src/lib/api/deviceService/tests/index.spec.ts +0 -74
  30. package/src/lib/api/extractUtils.ts +0 -160
  31. package/src/lib/api/index.ts +0 -8
  32. package/src/lib/api/localStorageWrapper/index.ts +0 -15
  33. package/src/lib/api/models/Account.ts +0 -48
  34. package/src/lib/api/models/Meeting.ts +0 -42
  35. package/src/lib/api/models/Organization.ts +0 -186
  36. package/src/lib/api/models/Room.ts +0 -44
  37. package/src/lib/api/models/account/EmbeddedFreeTierStatus.ts +0 -34
  38. package/src/lib/api/models/tests/Account.spec.ts +0 -128
  39. package/src/lib/api/models/tests/Organization.spec.ts +0 -161
  40. package/src/lib/api/models/tests/Room.spec.ts +0 -74
  41. package/src/lib/api/modules/AbstractStore.ts +0 -18
  42. package/src/lib/api/modules/ChromeStorageStore.ts +0 -44
  43. package/src/lib/api/modules/LocalStorageStore.ts +0 -57
  44. package/src/lib/api/modules/tests/ChromeStorageStore.spec.ts +0 -67
  45. package/src/lib/api/modules/tests/LocalStorageStore.spec.ts +0 -79
  46. package/src/lib/api/modules/tests/__mocks__/storage.ts +0 -24
  47. package/src/lib/api/organizationService/index.ts +0 -284
  48. package/src/lib/api/organizationService/tests/index.spec.ts +0 -781
  49. package/src/lib/api/organizationServiceCache/index.ts +0 -28
  50. package/src/lib/api/organizationServiceCache/tests/index.spec.ts +0 -101
  51. package/src/lib/api/parameterAssertUtils.ts +0 -166
  52. package/src/lib/api/roomService/index.ts +0 -310
  53. package/src/lib/api/roomService/tests/index.spec.ts +0 -668
  54. package/src/lib/api/test/ApiClient.spec.ts +0 -139
  55. package/src/lib/api/test/HttpClient.spec.ts +0 -120
  56. package/src/lib/api/test/MultipartHttpClient.spec.ts +0 -145
  57. package/src/lib/api/test/OrganizationApiClient.spec.ts +0 -132
  58. package/src/lib/api/test/extractUtils.spec.ts +0 -357
  59. package/src/lib/api/test/helpers.ts +0 -41
  60. package/src/lib/api/test/parameterAssertUtils.spec.ts +0 -265
  61. package/src/lib/api/types.ts +0 -6
  62. package/src/lib/embed.ts +0 -172
  63. package/src/lib/index.ts +0 -3
  64. package/src/lib/react/VideoElement.tsx +0 -16
  65. package/src/lib/react/index.ts +0 -3
  66. package/src/lib/react/useLocalMedia.ts +0 -25
  67. package/src/lib/react/useRoomConnection.ts +0 -92
  68. package/src/lib/reducer.ts +0 -142
  69. package/src/stories/custom-ui.stories.tsx +0 -133
  70. package/src/stories/prebuilt-ui.stories.tsx +0 -131
  71. package/src/stories/styles.css +0 -74
  72. package/src/types.d.ts +0 -175
  73. package/tsconfig.json +0 -30
@@ -1,516 +0,0 @@
1
- import RtcManagerDispatcher, {
2
- RtcEvents,
3
- RtcManagerCreatedPayload,
4
- RtcStreamAddedPayload,
5
- } from "@whereby/jslib-media/src/webrtc/RtcManagerDispatcher";
6
- import RtcManager from "@whereby/jslib-media/src/webrtc/RtcManager";
7
- import { fromLocation } from "@whereby/jslib-media/src/utils/urls";
8
- import {
9
- ApiClient,
10
- CredentialsService,
11
- OrganizationApiClient,
12
- OrganizationService,
13
- OrganizationServiceCache,
14
- RoomService,
15
- } from "./api";
16
-
17
- import { LocalParticipant, RemoteParticipant, StreamState } from "./RoomParticipant";
18
-
19
- import ServerSocket, {
20
- ClientLeftEvent,
21
- ClientMetadataReceivedEvent,
22
- NewClientEvent,
23
- RoomJoinedEvent as SignalRoomJoinedEvent,
24
- SignalClient,
25
- } from "@whereby/jslib-media/src/utils/ServerSocket";
26
-
27
- type Logger = Pick<Console, "debug" | "error" | "log" | "warn">;
28
-
29
- export interface RoomConnectionOptions {
30
- displayName?: string; // Might not be needed at all
31
- localStream?: MediaStream;
32
- localMediaConstraints?: MediaStreamConstraints;
33
- roomKey?: string;
34
- logger?: Logger;
35
- }
36
-
37
- type RoomJoinedEvent = {
38
- localParticipant: LocalParticipant;
39
- remoteParticipants: RemoteParticipant[];
40
- };
41
-
42
- type ParticipantJoinedEvent = {
43
- remoteParticipant: RemoteParticipant;
44
- };
45
-
46
- type ParticipantLeftEvent = {
47
- participantId: string;
48
- };
49
-
50
- type ParticipantStreamAddedEvent = {
51
- participantId: string;
52
- stream: MediaStream;
53
- };
54
-
55
- type ParticipantAudioEnabledEvent = {
56
- participantId: string;
57
- isAudioEnabled: boolean;
58
- };
59
-
60
- type ParticipantVideoEnabledEvent = {
61
- participantId: string;
62
- isVideoEnabled: boolean;
63
- };
64
-
65
- type ParticipantMetadataChangedEvent = {
66
- participantId: string;
67
- displayName: string;
68
- };
69
-
70
- interface RoomEventsMap {
71
- participant_audio_enabled: CustomEvent<ParticipantAudioEnabledEvent>;
72
- participant_joined: CustomEvent<ParticipantJoinedEvent>;
73
- participant_left: CustomEvent<ParticipantLeftEvent>;
74
- participant_metadata_changed: CustomEvent<ParticipantMetadataChangedEvent>;
75
- participant_stream_added: CustomEvent<ParticipantStreamAddedEvent>;
76
- participant_video_enabled: CustomEvent<ParticipantVideoEnabledEvent>;
77
- room_joined: CustomEvent<RoomJoinedEvent>;
78
- }
79
-
80
- const API_BASE_URL = "https://api.appearin.net";
81
- const SIGNAL_BASE_URL = "wss://signal.appearin.net";
82
-
83
- const NON_PERSON_ROLES = ["recorder", "streamer"];
84
-
85
- function createSocket() {
86
- const parsedUrl = new URL(SIGNAL_BASE_URL);
87
- const path = `${parsedUrl.pathname.replace(/^\/$/, "")}/protocol/socket.io/v1`;
88
- const SOCKET_HOST = parsedUrl.origin;
89
-
90
- const socketConf = {
91
- host: SOCKET_HOST,
92
- path,
93
- reconnectionDelay: 5000,
94
- reconnectionDelayMax: 30000,
95
- timeout: 10000,
96
- };
97
-
98
- return new ServerSocket(SOCKET_HOST, socketConf);
99
- }
100
-
101
- /*
102
- * This is the topmost interface when dealing with Whereby.
103
- *
104
- */
105
- interface RoomEventTarget extends EventTarget {
106
- addEventListener<K extends keyof RoomEventsMap>(
107
- type: K,
108
- listener: (ev: RoomEventsMap[K]) => void,
109
- options?: boolean | AddEventListenerOptions
110
- ): void;
111
- addEventListener(
112
- type: string,
113
- callback: EventListenerOrEventListenerObject | null,
114
- options?: EventListenerOptions | boolean
115
- ): void;
116
- }
117
-
118
- const noop = () => {
119
- return;
120
- };
121
-
122
- const TypedEventTarget = EventTarget as { new (): RoomEventTarget };
123
- export default class RoomConnection extends TypedEventTarget {
124
- public localParticipant: LocalParticipant | null = null;
125
- public roomUrl: URL;
126
- public remoteParticipants: RemoteParticipant[] = [];
127
- public readonly localMediaConstraints?: MediaStreamConstraints;
128
-
129
- private credentialsService: CredentialsService;
130
- private apiClient: ApiClient;
131
- private organizationService: OrganizationService;
132
- private organizationServiceCache: OrganizationServiceCache;
133
- private organizationApiClient: OrganizationApiClient;
134
- private roomService: RoomService;
135
-
136
- private signalSocket: ServerSocket;
137
- private rtcManagerDispatcher?: RtcManagerDispatcher;
138
- private rtcManager?: RtcManager;
139
- private roomConnectionState: "" | "connecting" | "connected" | "disconnected" = "";
140
- private logger: Logger;
141
- private localStream?: MediaStream;
142
- private displayName?: string;
143
-
144
- constructor(roomUrl: string, { displayName, localMediaConstraints, localStream, logger }: RoomConnectionOptions) {
145
- super();
146
- this.roomUrl = new URL(roomUrl); // Throw if invalid Whereby room url
147
- this.logger = logger || {
148
- debug: noop,
149
- error: noop,
150
- log: noop,
151
- warn: noop,
152
- };
153
- this.displayName = displayName;
154
- this.localStream = localStream;
155
- this.localMediaConstraints = localMediaConstraints;
156
-
157
- const urls = fromLocation({ host: this.roomUrl.host });
158
-
159
- // Initialize services
160
- this.credentialsService = CredentialsService.create({ baseUrl: API_BASE_URL });
161
- this.apiClient = new ApiClient({
162
- fetchDeviceCredentials: this.credentialsService.getCredentials.bind(this.credentialsService),
163
- baseUrl: API_BASE_URL,
164
- });
165
- this.organizationService = new OrganizationService({ apiClient: this.apiClient });
166
- this.organizationServiceCache = new OrganizationServiceCache({
167
- organizationService: this.organizationService,
168
- subdomain: urls.subdomain,
169
- });
170
- this.organizationApiClient = new OrganizationApiClient({
171
- apiClient: this.apiClient,
172
- fetchOrganization: async () => {
173
- const organization = await this.organizationServiceCache.fetchOrganization();
174
- return organization || undefined;
175
- },
176
- });
177
- this.roomService = new RoomService({ organizationApiClient: this.organizationApiClient });
178
-
179
- // Create signal socket and set up event listeners
180
- this.signalSocket = createSocket();
181
- this.signalSocket.on("new_client", this._handleNewClient.bind(this));
182
- this.signalSocket.on("client_left", this._handleClientLeft.bind(this));
183
- this.signalSocket.on("audio_enabled", this._handleClientAudioEnabled.bind(this));
184
- this.signalSocket.on("video_enabled", this._handleClientVideoEnabled.bind(this));
185
- this.signalSocket.on("client_metadata_received", this._handleClientMetadataReceived.bind(this));
186
- }
187
-
188
- private _handleNewClient({ client }: NewClientEvent) {
189
- if (NON_PERSON_ROLES.includes(client.role.roleName)) {
190
- return;
191
- }
192
- const remoteParticipant = new RemoteParticipant({ ...client, newJoiner: true });
193
- this.remoteParticipants = [...this.remoteParticipants, remoteParticipant];
194
- this._handleAcceptStreams([remoteParticipant]);
195
- this.dispatchEvent(new CustomEvent("participant_joined", { detail: { remoteParticipant } }));
196
- }
197
-
198
- private _handleClientLeft({ clientId }: ClientLeftEvent) {
199
- const remoteParticipant = this.remoteParticipants.find((p) => p.id === clientId);
200
- this.remoteParticipants = this.remoteParticipants.filter((p) => p.id !== clientId);
201
- if (!remoteParticipant) {
202
- return;
203
- }
204
- this.dispatchEvent(new CustomEvent("participant_left", { detail: { participantId: remoteParticipant.id } }));
205
- }
206
-
207
- private _handleClientAudioEnabled({ clientId, isAudioEnabled }: { clientId: string; isAudioEnabled: boolean }) {
208
- const remoteParticipant = this.remoteParticipants.find((p) => p.id === clientId);
209
- if (!remoteParticipant) {
210
- return;
211
- }
212
- this.dispatchEvent(
213
- new CustomEvent("participant_audio_enabled", {
214
- detail: { participantId: remoteParticipant.id, isAudioEnabled },
215
- })
216
- );
217
- }
218
-
219
- private _handleClientVideoEnabled({ clientId, isVideoEnabled }: { clientId: string; isVideoEnabled: boolean }) {
220
- const remoteParticipant = this.remoteParticipants.find((p) => p.id === clientId);
221
- if (!remoteParticipant) {
222
- return;
223
- }
224
- this.dispatchEvent(
225
- new CustomEvent("participant_video_enabled", {
226
- detail: { participantId: remoteParticipant.id, isVideoEnabled },
227
- })
228
- );
229
- }
230
-
231
- private _handleClientMetadataReceived({ payload: { clientId, displayName } }: ClientMetadataReceivedEvent) {
232
- const remoteParticipant = this.remoteParticipants.find((p) => p.id === clientId);
233
- if (!remoteParticipant) {
234
- return;
235
- }
236
- this.dispatchEvent(
237
- new CustomEvent("participant_metadata_changed", {
238
- detail: { participantId: remoteParticipant.id, displayName },
239
- })
240
- );
241
- }
242
-
243
- private _handleRtcEvent<K extends keyof RtcEvents>(eventName: K, data: RtcEvents[K]) {
244
- if (eventName === "rtc_manager_created") {
245
- return this._handleRtcManagerCreated(data as RtcManagerCreatedPayload);
246
- } else if (eventName === "stream_added") {
247
- return this._handleStreamAdded(data as RtcStreamAddedPayload);
248
- } else {
249
- this.logger.log(`Unhandled RTC event ${eventName}`);
250
- }
251
- }
252
-
253
- private _handleRtcManagerCreated({ rtcManager }: RtcManagerCreatedPayload) {
254
- this.rtcManager = rtcManager;
255
- if (this.localStream) {
256
- this.rtcManager?.addNewStream(
257
- "0",
258
- this.localStream,
259
- !this.localStream?.getAudioTracks().find((t) => t.enabled),
260
- !this.localStream?.getVideoTracks().find((t) => t.enabled)
261
- );
262
- }
263
- }
264
-
265
- private _handleAcceptStreams(remoteParticipants: RemoteParticipant[]) {
266
- if (!this.rtcManager) {
267
- this.logger.log("Unable to accept streams, no rtc manager");
268
- return;
269
- }
270
-
271
- const shouldAcceptNewClients = this.rtcManager.shouldAcceptStreamsFromBothSides?.();
272
- const activeBreakout = false; // TODO: Remove this once breakout is implemented
273
- const myselfBroadcasting = false; // TODO: Remove once breakout is implemented
274
-
275
- remoteParticipants.forEach((participant) => {
276
- const { id: participantId, streams, newJoiner } = participant;
277
-
278
- streams.forEach((stream) => {
279
- const { id: streamId, state: streamState } = stream;
280
- let newState: StreamState | undefined = undefined;
281
-
282
- // Determine the new state of the client, equivalent of "reactAcceptStreams"
283
- // TODO: Replace this with correct logic catering for breakouts etc
284
-
285
- // #region reactAcceptStreams
286
- const isInSameRoomOrGroupOrClientBroadcasting = true; // TODO: Remove once breakout is implemented
287
-
288
- if (isInSameRoomOrGroupOrClientBroadcasting) {
289
- if (streamState !== "done_accept") {
290
- newState = `${newJoiner && streamId === "0" ? "new" : "to"}_accept`;
291
- }
292
- } else if (myselfBroadcasting) {
293
- if (streamState !== "done_accept") {
294
- newState = `${newJoiner && streamId === "0" ? "done" : "old"}_accept`;
295
- }
296
- } else {
297
- if (streamState !== "done_unaccept") {
298
- newState = "to_unaccept";
299
- }
300
- }
301
-
302
- if (!newState) {
303
- return;
304
- }
305
-
306
- // #endregion
307
-
308
- // #region doAcceptStreams
309
- if (
310
- newState === "to_accept" ||
311
- (newState === "new_accept" && shouldAcceptNewClients) ||
312
- (newState === "old_accept" && !shouldAcceptNewClients)
313
- ) {
314
- this.logger.log(`Accepting stream ${streamId} from ${participantId}`);
315
- this.rtcManager?.acceptNewStream({
316
- streamId: streamId === "0" ? participantId : streamId,
317
- clientId: participantId,
318
- shouldAddLocalVideo: streamId === "0",
319
- activeBreakout,
320
- });
321
- } else if (newState === "new_accept" || newState === "old_accept") {
322
- // do nothing - let this be marked as done_accept as the rtcManager
323
- // will trigger accept from other end
324
- } else if (newState === "to_unaccept") {
325
- this.logger.log(`Disconnecting stream ${streamId} from ${participantId}`);
326
- this.rtcManager?.disconnect(streamId === "0" ? participantId : streamId, activeBreakout);
327
- } else if (newState !== "done_accept") {
328
- this.logger.warn(`Stream state not handled: ${newState} for ${participantId}-${streamId}`);
329
- return;
330
- } else {
331
- // done_accept
332
- }
333
-
334
- // Update stream state
335
- participant.updateStreamState(streamId, streamState.replace(/to_|new_|old_/, "done_") as StreamState);
336
-
337
- // #endregion
338
- });
339
- });
340
- }
341
-
342
- private _handleStreamAdded({ clientId, stream, streamId }: RtcStreamAddedPayload) {
343
- const remoteParticipant = this.remoteParticipants.find((p) => p.id === clientId);
344
- if (!remoteParticipant) {
345
- this.logger.log("WARN: Could not find participant for incoming stream");
346
- return;
347
- }
348
-
349
- this.dispatchEvent(
350
- new CustomEvent("participant_stream_added", { detail: { participantId: clientId, stream, streamId } })
351
- );
352
- }
353
-
354
- /**
355
- * Public API
356
- */
357
-
358
- async join() {
359
- if (["connected", "connecting"].includes(this.roomConnectionState)) {
360
- console.warn(`Trying to join room state is ${this.roomConnectionState}`);
361
- return;
362
- }
363
-
364
- this.logger.log("Joining room");
365
- this.roomConnectionState = "connecting";
366
-
367
- if (!this.localStream && this.localMediaConstraints) {
368
- const localStream = await navigator.mediaDevices.getUserMedia(this.localMediaConstraints);
369
- this.localStream = localStream;
370
- }
371
-
372
- const organization = await this.organizationServiceCache.fetchOrganization();
373
- if (!organization) {
374
- throw new Error("Invalid room url");
375
- }
376
-
377
- // TODO: Get room permissions
378
- // TODO: Get room features
379
-
380
- const webrtcProvider = {
381
- getMediaConstraints: () => ({
382
- audio: !!this.localStream?.getAudioTracks().find((t) => t.enabled),
383
- video: !!this.localStream?.getVideoTracks().find((t) => t.enabled),
384
- }),
385
- deferrable(clientId: string) {
386
- return !clientId;
387
- },
388
- };
389
-
390
- this.rtcManagerDispatcher = new RtcManagerDispatcher({
391
- emitter: {
392
- emit: this._handleRtcEvent.bind(this),
393
- },
394
- serverSocket: this.signalSocket,
395
- webrtcProvider,
396
- features: {
397
- lowDataModeEnabled: false,
398
- sfuServerOverrideHost: undefined,
399
- turnServerOverrideHost: undefined,
400
- useOnlyTURN: undefined,
401
- vp9On: false,
402
- h264On: false,
403
- simulcastScreenshareOn: false,
404
- },
405
- });
406
-
407
- // Identify device on signal connection
408
- const deviceCredentials = await this.credentialsService.getCredentials();
409
-
410
- // TODO: Handle connection and failed connection properly
411
- setTimeout(() => {
412
- this.logger.log("Connected to signal socket");
413
- this.signalSocket.emit("identify_device", { deviceCredentials });
414
- }, 2000);
415
-
416
- this.signalSocket.once("device_identified", () => {
417
- this.signalSocket.emit("join_room", {
418
- avatarUrl: null,
419
- config: {
420
- isAudioEnabled: !!this.localStream?.getAudioTracks().find((t) => t.enabled),
421
- isVideoEnabled: !!this.localStream?.getVideoTracks().find((t) => t.enabled),
422
- },
423
- deviceCapabilities: { canScreenshare: true },
424
- displayName: this.displayName,
425
- isCoLocated: false,
426
- isDevicePermissionDenied: false,
427
- kickFromOtherRooms: false,
428
- organizationId: organization.organizationId,
429
- roomKey: null,
430
- roomName: this.roomUrl.pathname,
431
- selfId: "",
432
- });
433
- });
434
-
435
- this.signalSocket.once("room_joined", (res: SignalRoomJoinedEvent) => {
436
- const {
437
- selfId,
438
- room: { clients },
439
- } = res;
440
-
441
- const localClient = clients.find((c) => c.id === selfId);
442
- if (!localClient) throw new Error("Missing local client");
443
-
444
- this.localParticipant = new LocalParticipant({ ...localClient, stream: this.localStream });
445
- this.remoteParticipants = clients
446
- .filter((c) => c.id !== selfId)
447
- .map((c) => new RemoteParticipant({ ...c, newJoiner: false }));
448
-
449
- // Accept remote streams if RTC manager has been initialized
450
- if (this.rtcManager) {
451
- this._handleAcceptStreams(this.remoteParticipants);
452
- }
453
-
454
- this.roomConnectionState = "connected";
455
- this.dispatchEvent(
456
- new CustomEvent("room_joined", {
457
- detail: {
458
- localParticipant: this.localParticipant,
459
- remoteParticipants: this.remoteParticipants,
460
- },
461
- })
462
- );
463
- });
464
- }
465
-
466
- leave(): Promise<void> {
467
- return new Promise<void>((resolve) => {
468
- if (!this.signalSocket) {
469
- return resolve();
470
- }
471
-
472
- this.signalSocket.emit("leave_room");
473
- const leaveTimeout = setTimeout(() => {
474
- resolve();
475
- }, 200);
476
- this.signalSocket.once("room_left", () => {
477
- clearTimeout(leaveTimeout);
478
- this.signalSocket.disconnect();
479
- resolve();
480
- });
481
- });
482
- }
483
-
484
- toggleCamera(enabled?: boolean): void {
485
- const localVideoTrack = this.localStream?.getVideoTracks()[0];
486
- if (!localVideoTrack) {
487
- this.logger.log("Tried toggling non-existing video track");
488
- return;
489
- }
490
- // TODO: Do stopOrResumeVideo
491
- const newValue = enabled ?? !localVideoTrack.enabled;
492
- localVideoTrack.enabled = newValue;
493
- this.signalSocket.emit("enable_video", { enabled: newValue });
494
- }
495
-
496
- toggleMicrophone(enabled?: boolean): void {
497
- const localAudioTrack = this.localStream?.getAudioTracks()[0];
498
- if (!localAudioTrack) {
499
- this.logger.log("Tried toggling non-existing audio track");
500
- return;
501
- }
502
- // TODO: Do stopOrResumeAudio
503
- const newValue = enabled ?? !localAudioTrack.enabled;
504
- localAudioTrack.enabled = newValue;
505
- this.signalSocket.emit("enable_audio", { enabled: newValue });
506
- }
507
-
508
- setDisplayName(displayName: string): void {
509
- this.signalSocket.emit("send_client_metadata", {
510
- type: "UserData",
511
- payload: {
512
- displayName,
513
- },
514
- });
515
- }
516
- }
@@ -1,77 +0,0 @@
1
- interface RoomParticipantData {
2
- displayName: string;
3
- id: string;
4
- stream?: MediaStream;
5
- isAudioEnabled: boolean;
6
- isVideoEnabled: boolean;
7
- }
8
-
9
- export default class RoomParticipant {
10
- public readonly displayName;
11
- public readonly id;
12
- public readonly stream?: MediaStream;
13
- public readonly isAudioEnabled: boolean;
14
- public readonly isLocalParticipant: boolean = false;
15
- public readonly isVideoEnabled: boolean;
16
-
17
- constructor({ displayName, id, stream, isAudioEnabled, isVideoEnabled }: RoomParticipantData) {
18
- this.displayName = displayName;
19
- this.id = id;
20
- this.stream = stream;
21
- this.isAudioEnabled = isAudioEnabled;
22
- this.isVideoEnabled = isVideoEnabled;
23
- }
24
- }
25
-
26
- interface RemoteParticipantData {
27
- newJoiner: boolean;
28
- streams: string[];
29
- }
30
-
31
- export type StreamState =
32
- | "new_accept"
33
- | "to_accept"
34
- | "old_accept"
35
- | "done_accept"
36
- | "to_unaccept"
37
- | "done_unaccept"
38
- | "auto";
39
-
40
- interface Stream {
41
- id: string;
42
- state: StreamState;
43
- }
44
-
45
- export class RemoteParticipant extends RoomParticipant {
46
- public readonly newJoiner: boolean;
47
- public readonly streams: Stream[];
48
-
49
- constructor({
50
- displayName,
51
- id,
52
- newJoiner,
53
- streams,
54
- isAudioEnabled,
55
- isVideoEnabled,
56
- }: RoomParticipantData & RemoteParticipantData) {
57
- super({ displayName, id, isAudioEnabled, isVideoEnabled });
58
- this.newJoiner = newJoiner;
59
-
60
- this.streams = streams.map((streamId) => ({ id: streamId, state: newJoiner ? "new_accept" : "to_accept" }));
61
- }
62
-
63
- updateStreamState(streamId: string, state: StreamState) {
64
- const stream = this.streams.find((s) => s.id === streamId);
65
- if (stream) {
66
- stream.state = state;
67
- }
68
- }
69
- }
70
-
71
- export class LocalParticipant extends RoomParticipant {
72
- public readonly isLocalParticipant = true;
73
-
74
- constructor({ displayName, id, stream, isAudioEnabled, isVideoEnabled }: RoomParticipantData) {
75
- super({ displayName, id, stream, isAudioEnabled, isVideoEnabled });
76
- }
77
- }
@@ -1,77 +0,0 @@
1
- import { jest } from "@jest/globals";
2
-
3
- const define = jest.fn();
4
- const ref = jest.fn();
5
- jest.mock("heresy", () => ({
6
- __esModule: true,
7
- define,
8
- ref,
9
- }));
10
-
11
- describe("@whereby/browser-sdk", () => {
12
- describe("web component", () => {
13
- it("should define <whereby-embed />", async () => {
14
- await import("../embed");
15
- expect(define).toBeCalledWith("WherebyEmbed", expect.any(Object));
16
- });
17
-
18
- it("should expose attributes", async () => {
19
- await import("../embed");
20
- expect(define).toBeCalledWith(
21
- expect.any(String),
22
- expect.objectContaining({
23
- observedAttributes: [
24
- "displayname",
25
- "minimal",
26
- "room",
27
- "subdomain",
28
- "lang",
29
- "metadata",
30
- "groups",
31
- "virtualbackgroundurl",
32
- "avatarurl",
33
- "audio",
34
- "background",
35
- "cameraaccess",
36
- "chat",
37
- "people",
38
- "embed",
39
- "emptyroominvitation",
40
- "help",
41
- "leavebutton",
42
- "precallreview",
43
- "screenshare",
44
- "video",
45
- "floatself",
46
- "recording",
47
- "logo",
48
- "locking",
49
- "participantcount",
50
- "settingsbutton",
51
- "pipbutton",
52
- "morebutton",
53
- "personality",
54
- "subgridlabels",
55
- "lowdata",
56
- "breakout",
57
- ],
58
- })
59
- );
60
- });
61
-
62
- it("should expose commands", async () => {
63
- await import("../embed");
64
-
65
- expect(define).toBeCalledWith(
66
- expect.any(String),
67
- expect.objectContaining({
68
- startRecording: expect.any(Function),
69
- stopRecording: expect.any(Function),
70
- toggleCamera: expect.any(Function),
71
- toggleMicrophone: expect.any(Function),
72
- toggleScreenshare: expect.any(Function),
73
- })
74
- );
75
- });
76
- });
77
- });