@whereby.com/browser-sdk 2.0.0-alpha8 → 2.0.0-alpha9

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/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-alpha8", iframeSource: subdomain }, (displayName && { displayName })), (lang && { lang })), (metadata && { metadata })), (groups && { groups })), (virtualBackgroundUrl && { virtualBackgroundUrl })), (avatarUrl && { avatarUrl })), (minimal != null && { embed: minimal })), boolAttrs.reduce(
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-alpha9", 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") {
@@ -5277,7 +5277,7 @@ class LocalParticipant extends RoomParticipant {
5277
5277
  }
5278
5278
  }
5279
5279
 
5280
- const API_BASE_URL = "https://api.appearin.net";
5280
+ const API_BASE_URL = "https://api.whereby.dev";
5281
5281
  const SIGNAL_BASE_URL = "wss://signal.appearin.net";
5282
5282
  const NON_PERSON_ROLES = ["recorder", "streamer"];
5283
5283
  function createSocket() {
@@ -5303,11 +5303,13 @@ class RoomConnection extends TypedEventTarget {
5303
5303
  super();
5304
5304
  this.localParticipant = null;
5305
5305
  this.remoteParticipants = [];
5306
- this.roomConnectionState = "";
5307
5306
  this._ownsLocalMedia = false;
5307
+ this.organizationId = "";
5308
+ this.roomConnectionStatus = "";
5308
5309
  this.roomUrl = new URL(roomUrl); // Throw if invalid Whereby room url
5309
5310
  const searchParams = new URLSearchParams(this.roomUrl.search);
5310
5311
  this._roomKey = roomKey || searchParams.get("roomKey");
5312
+ this.roomName = this.roomUrl.pathname;
5311
5313
  this.logger = logger || {
5312
5314
  debug: noop,
5313
5315
  error: noop,
@@ -5328,6 +5330,7 @@ class RoomConnection extends TypedEventTarget {
5328
5330
  else {
5329
5331
  throw new Error("Missing constraints");
5330
5332
  }
5333
+ // Set up services
5331
5334
  this.credentialsService = CredentialsService.create({ baseUrl: API_BASE_URL });
5332
5335
  this.apiClient = new ApiClient({
5333
5336
  fetchDeviceCredentials: this.credentialsService.getCredentials.bind(this.credentialsService),
@@ -5354,6 +5357,10 @@ class RoomConnection extends TypedEventTarget {
5354
5357
  this.signalSocket.on("audio_enabled", this._handleClientAudioEnabled.bind(this));
5355
5358
  this.signalSocket.on("video_enabled", this._handleClientVideoEnabled.bind(this));
5356
5359
  this.signalSocket.on("client_metadata_received", this._handleClientMetadataReceived.bind(this));
5360
+ this.signalSocket.on("knock_handled", this._handleKnockHandled.bind(this));
5361
+ this.signalSocket.on("knocker_left", this._handleKnockerLeft.bind(this));
5362
+ this.signalSocket.on("room_joined", this._handleRoomJoined.bind(this));
5363
+ this.signalSocket.on("room_knocked", this._handleRoomKnocked.bind(this));
5357
5364
  // Set up local media listeners
5358
5365
  this.localMedia.addEventListener("camera_enabled", (e) => {
5359
5366
  const { enabled } = e.detail;
@@ -5414,6 +5421,70 @@ class RoomConnection extends TypedEventTarget {
5414
5421
  detail: { participantId: remoteParticipant.id, displayName },
5415
5422
  }));
5416
5423
  }
5424
+ _handleKnockHandled(payload) {
5425
+ const { resolution } = payload;
5426
+ if (resolution === "accepted") {
5427
+ this.roomConnectionStatus = "accepted";
5428
+ this._roomKey = payload.metadata.roomKey;
5429
+ this._joinRoom();
5430
+ }
5431
+ else if (resolution === "rejected") {
5432
+ this.roomConnectionStatus = "rejected";
5433
+ this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
5434
+ detail: {
5435
+ roomConnectionStatus: this.roomConnectionStatus,
5436
+ },
5437
+ }));
5438
+ }
5439
+ }
5440
+ _handleKnockerLeft(payload) {
5441
+ const { clientId } = payload;
5442
+ this.dispatchEvent(new CustomEvent("waiting_participant_left", {
5443
+ detail: { participantId: clientId },
5444
+ }));
5445
+ }
5446
+ _handleRoomJoined(event) {
5447
+ const { error, isLocked, room, selfId } = event;
5448
+ if (error === "room_locked" && isLocked) {
5449
+ this.roomConnectionStatus = "room_locked";
5450
+ this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
5451
+ detail: {
5452
+ roomConnectionStatus: this.roomConnectionStatus,
5453
+ },
5454
+ }));
5455
+ return;
5456
+ }
5457
+ // Check if we have an error
5458
+ // Check if it is a room joined error
5459
+ // Set state to connect_failed_locked
5460
+ // Set state to connect_failed_no_host
5461
+ if (room) {
5462
+ const { clients, knockers } = room;
5463
+ const localClient = clients.find((c) => c.id === selfId);
5464
+ if (!localClient)
5465
+ throw new Error("Missing local client");
5466
+ this.localParticipant = new LocalParticipant(Object.assign(Object.assign({}, localClient), { stream: this.localMedia.stream || undefined }));
5467
+ this.remoteParticipants = clients
5468
+ .filter((c) => c.id !== selfId)
5469
+ .map((c) => new RemoteParticipant(Object.assign(Object.assign({}, c), { newJoiner: false })));
5470
+ this.roomConnectionStatus = "connected";
5471
+ this.dispatchEvent(new CustomEvent("room_joined", {
5472
+ detail: {
5473
+ localParticipant: this.localParticipant,
5474
+ remoteParticipants: this.remoteParticipants,
5475
+ waitingParticipants: knockers.map((knocker) => {
5476
+ return { id: knocker.clientId, displayName: knocker.displayName };
5477
+ }),
5478
+ },
5479
+ }));
5480
+ }
5481
+ }
5482
+ _handleRoomKnocked(event) {
5483
+ const { clientId, displayName } = event;
5484
+ this.dispatchEvent(new CustomEvent("waiting_participant_joined", {
5485
+ detail: { participantId: clientId, displayName },
5486
+ }));
5487
+ }
5417
5488
  _handleRtcEvent(eventName, data) {
5418
5489
  if (eventName === "rtc_manager_created") {
5419
5490
  return this._handleRtcManagerCreated(data);
@@ -5432,6 +5503,9 @@ class RoomConnection extends TypedEventTarget {
5432
5503
  if (this.localMedia.stream) {
5433
5504
  (_a = this.rtcManager) === null || _a === void 0 ? void 0 : _a.addNewStream("0", this.localMedia.stream, !this.localMedia.isMicrophoneEnabled(), !this.localMedia.isCameraEnabled());
5434
5505
  }
5506
+ if (this.remoteParticipants.length) {
5507
+ this._handleAcceptStreams(this.remoteParticipants);
5508
+ }
5435
5509
  }
5436
5510
  _handleAcceptStreams(remoteParticipants) {
5437
5511
  var _a, _b;
@@ -5489,14 +5563,43 @@ class RoomConnection extends TypedEventTarget {
5489
5563
  }
5490
5564
  this.dispatchEvent(new CustomEvent("participant_stream_added", { detail: { participantId: clientId, stream, streamId } }));
5491
5565
  }
5566
+ _joinRoom() {
5567
+ this.signalSocket.emit("join_room", {
5568
+ avatarUrl: null,
5569
+ config: {
5570
+ isAudioEnabled: this.localMedia.isMicrophoneEnabled(),
5571
+ isVideoEnabled: this.localMedia.isCameraEnabled(),
5572
+ },
5573
+ deviceCapabilities: { canScreenshare: true },
5574
+ displayName: this.displayName,
5575
+ isCoLocated: false,
5576
+ isDevicePermissionDenied: false,
5577
+ kickFromOtherRooms: false,
5578
+ organizationId: this.organizationId,
5579
+ roomKey: this.roomKey,
5580
+ roomName: this.roomName,
5581
+ selfId: "",
5582
+ userAgent: `browser-sdk:${sdkVersion }`,
5583
+ });
5584
+ }
5492
5585
  join() {
5493
5586
  return tslib.__awaiter(this, void 0, void 0, function* () {
5494
- if (["connected", "connecting"].includes(this.roomConnectionState)) {
5495
- console.warn(`Trying to join room state is ${this.roomConnectionState}`);
5587
+ if (["connected", "connecting"].includes(this.roomConnectionStatus)) {
5588
+ console.warn(`Trying to join when room state is already ${this.roomConnectionStatus}`);
5496
5589
  return;
5497
5590
  }
5498
5591
  this.logger.log("Joining room");
5499
- this.roomConnectionState = "connecting";
5592
+ this.roomConnectionStatus = "connecting";
5593
+ this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
5594
+ detail: {
5595
+ roomConnectionStatus: this.roomConnectionStatus,
5596
+ },
5597
+ }));
5598
+ const organization = yield this.organizationServiceCache.fetchOrganization();
5599
+ if (!organization) {
5600
+ throw new Error("Invalid room url");
5601
+ }
5602
+ this.organizationId = organization.organizationId;
5500
5603
  if (this._ownsLocalMedia) {
5501
5604
  yield this.localMedia.start();
5502
5605
  }
@@ -5525,57 +5628,32 @@ class RoomConnection extends TypedEventTarget {
5525
5628
  simulcastScreenshareOn: false,
5526
5629
  },
5527
5630
  });
5528
- const organization = yield this.organizationServiceCache.fetchOrganization();
5529
- if (!organization) {
5530
- throw new Error("Invalid room url");
5531
- }
5532
5631
  // Identify device on signal connection
5533
5632
  const deviceCredentials = yield this.credentialsService.getCredentials();
5534
- this.logger.log("Connecting to signal socket");
5633
+ this.logger.log("Connected to signal socket");
5535
5634
  this.signalSocket.emit("identify_device", { deviceCredentials });
5536
5635
  this.signalSocket.once("device_identified", () => {
5537
- this.logger.log("Connected to signal socket");
5538
- this.signalSocket.emit("join_room", {
5539
- avatarUrl: null,
5540
- config: {
5541
- isAudioEnabled: this.localMedia.isMicrophoneEnabled(),
5542
- isVideoEnabled: this.localMedia.isCameraEnabled(),
5543
- },
5544
- deviceCapabilities: { canScreenshare: true },
5545
- displayName: this.displayName,
5546
- isCoLocated: false,
5547
- isDevicePermissionDenied: false,
5548
- kickFromOtherRooms: false,
5549
- organizationId: organization.organizationId,
5550
- roomKey: this.roomKey,
5551
- roomName: this.roomUrl.pathname,
5552
- selfId: "",
5553
- userAgent: `browser-sdk:${sdkVersion }`,
5554
- });
5555
- });
5556
- this.signalSocket.once("room_joined", (res) => {
5557
- const { selfId, room: { clients }, } = res;
5558
- const localClient = clients.find((c) => c.id === selfId);
5559
- if (!localClient)
5560
- throw new Error("Missing local client");
5561
- this.localParticipant = new LocalParticipant(Object.assign(Object.assign({}, localClient), { stream: this.localMedia.stream || undefined }));
5562
- this.remoteParticipants = clients
5563
- .filter((c) => c.id !== selfId)
5564
- .map((c) => new RemoteParticipant(Object.assign(Object.assign({}, c), { newJoiner: false })));
5565
- // Accept remote streams if RTC manager has been initialized
5566
- if (this.rtcManager) {
5567
- this._handleAcceptStreams(this.remoteParticipants);
5568
- }
5569
- this.roomConnectionState = "connected";
5570
- this.dispatchEvent(new CustomEvent("room_joined", {
5571
- detail: {
5572
- localParticipant: this.localParticipant,
5573
- remoteParticipants: this.remoteParticipants,
5574
- },
5575
- }));
5636
+ this._joinRoom();
5576
5637
  });
5577
5638
  });
5578
5639
  }
5640
+ knock() {
5641
+ this.roomConnectionStatus = "knocking";
5642
+ this.dispatchEvent(new CustomEvent("room_connection_status_changed", {
5643
+ detail: {
5644
+ roomConnectionStatus: this.roomConnectionStatus,
5645
+ },
5646
+ }));
5647
+ this.signalSocket.emit("knock_room", {
5648
+ displayName: this.displayName,
5649
+ imageUrl: null,
5650
+ kickFromOtherRooms: true,
5651
+ liveVideo: false,
5652
+ organizationId: this.organizationId,
5653
+ roomKey: this._roomKey,
5654
+ roomName: this.roomName,
5655
+ });
5656
+ }
5579
5657
  leave() {
5580
5658
  return new Promise((resolve) => {
5581
5659
  if (this._ownsLocalMedia) {
@@ -5613,14 +5691,30 @@ class RoomConnection extends TypedEventTarget {
5613
5691
  },
5614
5692
  });
5615
5693
  }
5694
+ acceptWaitingParticipant(participantId) {
5695
+ this.signalSocket.emit("handle_knock", {
5696
+ action: "accept",
5697
+ clientId: participantId,
5698
+ response: {},
5699
+ });
5700
+ }
5701
+ rejectWaitingParticipant(participantId) {
5702
+ this.signalSocket.emit("handle_knock", {
5703
+ action: "reject",
5704
+ clientId: participantId,
5705
+ response: {},
5706
+ });
5707
+ }
5616
5708
  }
5617
5709
 
5618
5710
  const initialState = {
5619
5711
  chatMessages: [],
5712
+ roomConnectionStatus: "",
5620
5713
  isJoining: false,
5621
5714
  joinError: null,
5622
5715
  mostRecentChatMessage: null,
5623
5716
  remoteParticipants: [],
5717
+ waitingParticipants: [],
5624
5718
  };
5625
5719
  function updateParticipant(remoteParticipants, participantId, updates) {
5626
5720
  const existingParticipant = remoteParticipants.find((p) => p.id === participantId);
@@ -5639,7 +5733,9 @@ function reducer(state, action) {
5639
5733
  case "CHAT_MESSAGE":
5640
5734
  return Object.assign(Object.assign({}, state), { chatMessages: [...state.chatMessages, action.payload], mostRecentChatMessage: action.payload });
5641
5735
  case "ROOM_JOINED":
5642
- return Object.assign(Object.assign({}, state), { localParticipant: action.payload.localParticipant, remoteParticipants: action.payload.remoteParticipants, roomConnectionStatus: "connected" });
5736
+ return Object.assign(Object.assign({}, state), { localParticipant: action.payload.localParticipant, remoteParticipants: action.payload.remoteParticipants, waitingParticipants: action.payload.waitingParticipants, roomConnectionStatus: "connected" });
5737
+ case "ROOM_CONNECTION_STATUS_CHANGED":
5738
+ return Object.assign(Object.assign({}, state), { roomConnectionStatus: action.payload.roomConnectionStatus });
5643
5739
  case "PARTICIPANT_AUDIO_ENABLED":
5644
5740
  return Object.assign(Object.assign({}, state), { remoteParticipants: updateParticipant(state.remoteParticipants, action.payload.participantId, {
5645
5741
  isAudioEnabled: action.payload.isAudioEnabled,
@@ -5664,6 +5760,13 @@ function reducer(state, action) {
5664
5760
  if (!state.localParticipant)
5665
5761
  return state;
5666
5762
  return Object.assign(Object.assign({}, state), { localParticipant: Object.assign(Object.assign({}, state.localParticipant), { displayName: action.payload.displayName }) });
5763
+ case "WAITING_PARTICIPANT_JOINED":
5764
+ return Object.assign(Object.assign({}, state), { waitingParticipants: [
5765
+ ...state.waitingParticipants,
5766
+ { id: action.payload.participantId, displayName: action.payload.displayName },
5767
+ ] });
5768
+ case "WAITING_PARTICIPANT_LEFT":
5769
+ return Object.assign(Object.assign({}, state), { waitingParticipants: state.waitingParticipants.filter((wp) => wp.id !== action.payload.participantId) });
5667
5770
  default:
5668
5771
  throw state;
5669
5772
  }
@@ -5695,9 +5798,13 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
5695
5798
  const { participantId, stream } = e.detail;
5696
5799
  dispatch({ type: "PARTICIPANT_STREAM_ADDED", payload: { participantId, stream } });
5697
5800
  });
5801
+ roomConnection.addEventListener("room_connection_status_changed", (e) => {
5802
+ const { roomConnectionStatus } = e.detail;
5803
+ dispatch({ type: "ROOM_CONNECTION_STATUS_CHANGED", payload: { roomConnectionStatus } });
5804
+ });
5698
5805
  roomConnection.addEventListener("room_joined", (e) => {
5699
- const { localParticipant, remoteParticipants } = e.detail;
5700
- dispatch({ type: "ROOM_JOINED", payload: { localParticipant, remoteParticipants } });
5806
+ const { localParticipant, remoteParticipants, waitingParticipants } = e.detail;
5807
+ dispatch({ type: "ROOM_JOINED", payload: { localParticipant, remoteParticipants, waitingParticipants } });
5701
5808
  });
5702
5809
  roomConnection.addEventListener("participant_video_enabled", (e) => {
5703
5810
  const { participantId, isVideoEnabled } = e.detail;
@@ -5707,6 +5814,14 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
5707
5814
  const { participantId, displayName } = e.detail;
5708
5815
  dispatch({ type: "PARTICIPANT_METADATA_CHANGED", payload: { participantId, displayName } });
5709
5816
  });
5817
+ roomConnection.addEventListener("waiting_participant_joined", (e) => {
5818
+ const { participantId, displayName } = e.detail;
5819
+ dispatch({ type: "WAITING_PARTICIPANT_JOINED", payload: { participantId, displayName } });
5820
+ });
5821
+ roomConnection.addEventListener("waiting_participant_left", (e) => {
5822
+ const { participantId } = e.detail;
5823
+ dispatch({ type: "WAITING_PARTICIPANT_LEFT", payload: { participantId } });
5824
+ });
5710
5825
  roomConnection.join();
5711
5826
  return () => {
5712
5827
  roomConnection.leave();
@@ -5715,18 +5830,27 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
5715
5830
  return {
5716
5831
  state,
5717
5832
  actions: {
5833
+ knock: () => {
5834
+ roomConnection.knock();
5835
+ },
5718
5836
  sendChatMessage: (text) => {
5719
5837
  roomConnection.sendChatMessage(text);
5720
5838
  },
5721
5839
  setDisplayName: (displayName) => {
5722
- roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.setDisplayName(displayName);
5840
+ roomConnection.setDisplayName(displayName);
5723
5841
  dispatch({ type: "LOCAL_CLIENT_DISPLAY_NAME_CHANGED", payload: { displayName } });
5724
5842
  },
5725
5843
  toggleCamera: (enabled) => {
5726
- roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.localMedia.toggleCameraEnabled(enabled);
5844
+ roomConnection.localMedia.toggleCameraEnabled(enabled);
5727
5845
  },
5728
5846
  toggleMicrophone: (enabled) => {
5729
- roomConnection === null || roomConnection === void 0 ? void 0 : roomConnection.localMedia.toggleMichrophoneEnabled(enabled);
5847
+ roomConnection.localMedia.toggleMichrophoneEnabled(enabled);
5848
+ },
5849
+ acceptWaitingParticipant: (participantId) => {
5850
+ roomConnection.acceptWaitingParticipant(participantId);
5851
+ },
5852
+ rejectWaitingParticipant: (participantId) => {
5853
+ roomConnection.rejectWaitingParticipant(participantId);
5730
5854
  },
5731
5855
  },
5732
5856
  components: {
@@ -5736,7 +5860,7 @@ function useRoomConnection(roomUrl, roomConnectionOptions) {
5736
5860
  };
5737
5861
  }
5738
5862
 
5739
- const sdkVersion = "2.0.0-alpha8";
5863
+ const sdkVersion = "2.0.0-alpha9";
5740
5864
 
5741
5865
  exports.VideoView = VideoView;
5742
5866
  exports.sdkVersion = sdkVersion;