@100mslive/hms-video-store 0.2.66 → 0.2.70

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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.2.66",
2
+ "version": "0.2.70",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -55,11 +55,11 @@
55
55
  "zustand": "3.5.7"
56
56
  },
57
57
  "peerDependencies": {
58
- "@100mslive/hms-video": "^0.1.0",
58
+ "@100mslive/hms-video": "^0.1.8",
59
59
  "events": "^3.3.0"
60
60
  },
61
61
  "devDependencies": {
62
- "@100mslive/hms-video": "^0.1.0",
62
+ "@100mslive/hms-video": "^0.1.8",
63
63
  "@size-limit/file": "^5.0.3",
64
64
  "events": "^3.3.0",
65
65
  "husky": "^6.0.0",
@@ -25,6 +25,19 @@ export class HMSLogger {
25
25
  this.log(HMSLogLevel.ERROR, ...data);
26
26
  }
27
27
 
28
+ static time(mark: string) {
29
+ this.log(HMSLogLevel.TIME, '[HMSPerformanceTiming]', mark);
30
+ }
31
+
32
+ static timeEnd(mark: string) {
33
+ this.log(HMSLogLevel.TIMEEND, '[HMSPerformanceTiming]', mark, mark);
34
+ }
35
+
36
+ static cleanUp() {
37
+ performance.clearMarks();
38
+ performance.clearMeasures();
39
+ }
40
+
28
41
  /* eslint-disable */
29
42
  private static log(level: HMSLogLevel, ...data: any[]) {
30
43
  if (this.level.valueOf() > level.valueOf()) {
@@ -52,6 +65,24 @@ export class HMSLogger {
52
65
  console.error(HMS_STORE_TAG, ...data);
53
66
  break;
54
67
  }
68
+ case HMSLogLevel.TIME: {
69
+ performance.mark(data[1]);
70
+ break;
71
+ }
72
+ case HMSLogLevel.TIMEEND: {
73
+ const tag = data[0];
74
+ const mark = data[1];
75
+ try {
76
+ const entry = performance.measure(mark, mark);
77
+ //@ts-ignore
78
+ this.log(HMSLogLevel.DEBUG, tag, mark, entry?.duration);
79
+ performance.clearMarks(mark);
80
+ performance.clearMeasures(mark);
81
+ } catch (error) {
82
+ this.log(HMSLogLevel.DEBUG, tag, mark, error);
83
+ }
84
+ break;
85
+ }
55
86
  }
56
87
  }
57
88
  }
@@ -14,7 +14,7 @@ import {
14
14
  HMSTrackID,
15
15
  HMSTrackSource,
16
16
  IHMSPlaylistActions,
17
- HMSChangeMultiTrackStateRequest,
17
+ HMSChangeMultiTrackStateParams,
18
18
  } from './schema';
19
19
  import { HMSRoleChangeRequest } from './selectors';
20
20
  import { RTMPRecordingConfig } from './hmsSDKStore/sdkTypes';
@@ -238,9 +238,9 @@ export interface IHMSActions {
238
238
 
239
239
  /**
240
240
  * Use this to mute/unmute multipe tracks by source, role or type
241
- * @param {HMSChangeMultiTrackStateRequest} params
241
+ * @param {HMSChangeMultiTrackStateParams} params
242
242
  */
243
- setRemoteTracksEnabled(params: HMSChangeMultiTrackStateRequest): Promise<void>;
243
+ setRemoteTracksEnabled(params: HMSChangeMultiTrackStateParams): Promise<void>;
244
244
 
245
245
  /**
246
246
  * Method to be called with some UI interaction after autoplay error is received
@@ -12,6 +12,7 @@ import {
12
12
  HMSException,
13
13
  HMSMessage,
14
14
  HMSTrack,
15
+ HMSTrackID,
15
16
  HMSChangeTrackStateRequest,
16
17
  HMSChangeMultiTrackStateRequest,
17
18
  HMSLeaveRoomRequest,
@@ -56,6 +57,15 @@ export class HMSNotifications implements IHMSNotifications {
56
57
  this.emitEvent(notification);
57
58
  }
58
59
 
60
+ sendPeerList(peers: HMSPeer[]) {
61
+ const notification = this.createNotification(
62
+ HMSNotificationTypes.PEER_LIST,
63
+ peers,
64
+ HMSNotificationSeverity.INFO,
65
+ );
66
+ this.emitEvent(notification);
67
+ }
68
+
59
69
  sendPeerUpdate(type: sdkTypes.HMSPeerUpdate, peer: HMSPeer | null) {
60
70
  const hmsPeer = this.store.getState(selectPeerByID(peer?.id)) || peer;
61
71
  const notificationType = PEER_NOTIFICATION_TYPES[type];
@@ -69,7 +79,7 @@ export class HMSNotifications implements IHMSNotifications {
69
79
  }
70
80
  }
71
81
 
72
- sendTrackUpdate(type: sdkTypes.HMSTrackUpdate, trackID: string) {
82
+ sendTrackUpdate(type: sdkTypes.HMSTrackUpdate, trackID: HMSTrackID) {
73
83
  const hmsTrack = this.store.getState(selectTrackByID(trackID));
74
84
  const notificationType = TRACK_NOTIFICATION_TYPES[type];
75
85
  if (notificationType) {
@@ -144,6 +154,7 @@ export class HMSNotifications implements IHMSNotifications {
144
154
  type: string,
145
155
  data?:
146
156
  | HMSPeer
157
+ | HMSPeer[]
147
158
  | HMSTrack
148
159
  | HMSMessage
149
160
  | HMSException
@@ -487,6 +487,7 @@ export class HMSSDKActions implements IHMSActions {
487
487
  }, reason);
488
488
  this.isRoomJoinCalled = false;
489
489
  this.hmsSDKTracks = {};
490
+ HMSLogger.cleanUp();
490
491
  }
491
492
 
492
493
  private sdkJoinWithListeners(config: sdkTypes.HMSConfig) {
@@ -610,7 +611,7 @@ export class HMSSDKActions implements IHMSActions {
610
611
  * @protected
611
612
  */
612
613
  protected syncRoomState(action?: string) {
613
- console.time('syncRoomState');
614
+ HMSLogger.time(`store-sync-${action}`);
614
615
  const newHmsPeers: Record<HMSPeerID, Partial<HMSPeer>> = {};
615
616
  const newHmsPeerIDs: HMSPeerID[] = []; // to add in room.peers
616
617
  const newHmsTracks: Record<HMSTrackID, Partial<HMSTrack>> = {};
@@ -652,7 +653,7 @@ export class HMSSDKActions implements IHMSActions {
652
653
  const draftPeers = draftStore.peers;
653
654
  const draftTracks = draftStore.tracks;
654
655
  // the order of below statements are important as merge functions are mutating
655
- mergeNewPeersInDraft(draftPeers, newHmsPeers, newHmsTracks, newHmsSDkTracks);
656
+ mergeNewPeersInDraft(draftPeers, newHmsPeers);
656
657
  mergeNewTracksInDraft(draftTracks, newHmsTracks);
657
658
  Object.assign(draftStore.settings, newMediaSettings);
658
659
  this.hmsSDKTracks = newHmsSDkTracks;
@@ -660,7 +661,7 @@ export class HMSSDKActions implements IHMSActions {
660
661
  Object.assign(draftStore.playlist, SDKToHMS.convertPlaylist(this.sdk.getPlaylistManager()));
661
662
  Object.assign(draftStore.room, SDKToHMS.convertRecordingRTMPState(recording, rtmp));
662
663
  }, action);
663
- console.timeEnd('syncRoomState');
664
+ HMSLogger.timeEnd(`store-sync-${action}`);
664
665
  }
665
666
 
666
667
  protected onPreview(sdkRoom: sdkTypes.HMSRoom) {
@@ -711,19 +712,26 @@ export class HMSSDKActions implements IHMSActions {
711
712
  sdkPeer: sdkTypes.HMSPeer | sdkTypes.HMSPeer[],
712
713
  ) {
713
714
  if (
714
- type === sdkTypes.HMSPeerUpdate.BECAME_DOMINANT_SPEAKER ||
715
- type === sdkTypes.HMSPeerUpdate.RESIGNED_DOMINANT_SPEAKER
715
+ [
716
+ sdkTypes.HMSPeerUpdate.BECAME_DOMINANT_SPEAKER,
717
+ sdkTypes.HMSPeerUpdate.RESIGNED_DOMINANT_SPEAKER,
718
+ ].includes(type)
716
719
  ) {
717
720
  return; // ignore, high frequency update so no point of syncing peers
718
- } else if (Array.isArray(sdkPeer)) {
721
+ }
722
+ if (Array.isArray(sdkPeer)) {
719
723
  this.syncRoomState('peersJoined');
724
+ const hmsPeers = [];
720
725
  for (let peer of sdkPeer) {
721
726
  const hmsPeer = this.store.getState(selectPeerByID(peer.peerId));
722
- this.hmsNotifications.sendPeerUpdate(type, hmsPeer);
727
+ if (hmsPeer) {
728
+ hmsPeers.push(hmsPeer);
729
+ }
723
730
  }
724
- } else {
725
- this.peerUpdateInternal(type, sdkPeer);
731
+ this.hmsNotifications.sendPeerList(hmsPeers);
732
+ return;
726
733
  }
734
+ this.sendPeerUpdateNotification(type, sdkPeer);
727
735
  }
728
736
 
729
737
  protected onTrackUpdate(
@@ -739,7 +747,7 @@ export class HMSSDKActions implements IHMSActions {
739
747
  } else {
740
748
  const actionName =
741
749
  type === sdkTypes.HMSTrackUpdate.TRACK_ADDED ? 'trackAdded' : 'trackUpdate';
742
- this.syncRemoteTrackState(actionName, track, peer);
750
+ this.syncRoomState(actionName);
743
751
  this.hmsNotifications.sendTrackUpdate(type, track.trackId);
744
752
  }
745
753
  }
@@ -906,22 +914,23 @@ export class HMSSDKActions implements IHMSActions {
906
914
  this.setState(draftStore => {
907
915
  const hmsPeer = draftStore.peers[sdkPeer.peerId];
908
916
  const draftTracks = draftStore.tracks;
917
+ const trackId = sdkTrack.trackId;
909
918
  // find and remove the exact track from hmsPeer
910
- if (this.isSameStoreSDKTrack(sdkTrack.trackId, hmsPeer?.audioTrack)) {
919
+ if (this.isSameStoreSDKTrack(trackId, hmsPeer?.audioTrack)) {
911
920
  delete hmsPeer?.audioTrack;
912
- } else if (this.isSameStoreSDKTrack(sdkTrack.trackId, hmsPeer?.videoTrack)) {
921
+ } else if (this.isSameStoreSDKTrack(trackId, hmsPeer?.videoTrack)) {
913
922
  delete hmsPeer?.videoTrack;
914
923
  } else {
915
- const auxiliaryIndex = hmsPeer?.auxiliaryTracks.indexOf(sdkTrack.trackId);
924
+ const auxiliaryIndex = hmsPeer?.auxiliaryTracks.indexOf(trackId);
916
925
  if (
917
926
  auxiliaryIndex > -1 &&
918
- this.isSameStoreSDKTrack(sdkTrack.trackId, hmsPeer?.auxiliaryTracks[auxiliaryIndex])
927
+ this.isSameStoreSDKTrack(trackId, hmsPeer?.auxiliaryTracks[auxiliaryIndex])
919
928
  ) {
920
929
  hmsPeer?.auxiliaryTracks.splice(auxiliaryIndex, 1);
921
930
  }
922
931
  }
923
- delete draftTracks[sdkTrack.trackId];
924
- delete this.hmsSDKTracks[sdkTrack.trackId];
932
+ delete draftTracks[trackId];
933
+ delete this.hmsSDKTracks[trackId];
925
934
  }, 'trackRemoved');
926
935
  }
927
936
 
@@ -1113,43 +1122,10 @@ export class HMSSDKActions implements IHMSActions {
1113
1122
  }, action);
1114
1123
  };
1115
1124
 
1116
- /**
1117
- * Handle store update on remote track changes
1118
- * @param {string} action - 'trackAdded' | 'trackUpdate'
1119
- * @param {SDKHMSTrack} track - track added/updated
1120
- * @param {sdkTypes.HMSPeer}peer - peer on which track is added/updated
1121
- */
1122
- private syncRemoteTrackState = (
1123
- action: 'trackAdded' | 'trackUpdate',
1124
- track: SDKHMSTrack,
1125
- peer: sdkTypes.HMSPeer,
1125
+ private sendPeerUpdateNotification = (
1126
+ type: sdkTypes.HMSPeerUpdate,
1127
+ sdkPeer: sdkTypes.HMSPeer,
1126
1128
  ) => {
1127
- this.setState(draftStore => {
1128
- let draftPeer = draftStore.peers[peer.peerId];
1129
- /**
1130
- * in preview -> leave -> join flow or join -> leave -> join flow,
1131
- * since peer will be cleared by leave, set peer again in the store
1132
- **/
1133
- if (!draftPeer) {
1134
- const hmsPeer = SDKToHMS.convertPeer(peer) as HMSPeer;
1135
- draftStore.peers[peer.peerId] = hmsPeer;
1136
- draftPeer = hmsPeer;
1137
- }
1138
- const hmsTrack = SDKToHMS.convertTrack(track, peer.peerId);
1139
- if (action === 'trackAdded') {
1140
- draftStore.tracks[hmsTrack.id] = hmsTrack;
1141
- this.updateTracksInPeer(peer, draftPeer, hmsTrack);
1142
- } else if (draftStore.tracks[hmsTrack.id]) {
1143
- Object.assign(draftStore.tracks[hmsTrack.id], hmsTrack);
1144
- } else {
1145
- this.logPossibleInconsistency(`track ${hmsTrack.id} not present, unable to update track`);
1146
- }
1147
- this.hmsSDKTracks[track.trackId] = track;
1148
- }, action);
1149
- };
1150
-
1151
- private peerUpdateInternal(type: sdkTypes.HMSPeerUpdate, sdkPeer: sdkTypes.HMSPeer) {
1152
- // store peer in case it doesn't exist later(will happen if event is peer leave)
1153
1129
  let peer = this.store.getState(selectPeerByID(sdkPeer.peerId));
1154
1130
  let actionName = 'peerUpdate';
1155
1131
  if (type === sdkTypes.HMSPeerUpdate.PEER_JOINED) {
@@ -1157,41 +1133,13 @@ export class HMSSDKActions implements IHMSActions {
1157
1133
  } else if (type === sdkTypes.HMSPeerUpdate.PEER_LEFT) {
1158
1134
  actionName = 'peerLeft';
1159
1135
  }
1160
- this.setState(draftStore => {
1161
- if (actionName === 'peerLeft') {
1162
- const index = draftStore.room.peers.indexOf(sdkPeer.peerId);
1163
- if (index > -1) {
1164
- draftStore.room.peers.splice(index, 1);
1165
- }
1166
- delete draftStore.peers[sdkPeer.peerId];
1167
- delete this.hmsSDKPeers[sdkPeer.peerId];
1168
- } else {
1169
- const hmsPeer = SDKToHMS.convertPeer(sdkPeer);
1170
- if (draftStore.peers[hmsPeer.id]) {
1171
- Object.assign(draftStore.peers[hmsPeer.id], hmsPeer);
1172
- } else {
1173
- draftStore.peers[hmsPeer.id] = hmsPeer as HMSPeer;
1174
- draftStore.room.peers.push(hmsPeer.id);
1175
- }
1176
- this.hmsSDKPeers[sdkPeer.peerId] = sdkPeer;
1177
- }
1178
- }, actionName);
1136
+ this.syncRoomState(actionName);
1179
1137
  // if peer wasn't available before sync(will happen if event is peer join)
1180
1138
  if (!peer) {
1181
1139
  peer = this.store.getState(selectPeerByID(sdkPeer.peerId));
1182
1140
  }
1183
1141
  this.hmsNotifications.sendPeerUpdate(type, peer);
1184
- }
1185
-
1186
- private updateTracksInPeer(peer: sdkTypes.HMSPeer, draftPeer: HMSPeer, hmsTrack: HMSTrack) {
1187
- if (peer.audioTrack?.trackId === hmsTrack.id) {
1188
- draftPeer.audioTrack = hmsTrack.id;
1189
- } else if (peer.videoTrack?.trackId === hmsTrack.id) {
1190
- draftPeer.videoTrack = hmsTrack.id;
1191
- } else if (!draftPeer.auxiliaryTracks.includes(hmsTrack.id)) {
1192
- draftPeer.auxiliaryTracks.push(hmsTrack.id);
1193
- }
1194
- }
1142
+ };
1195
1143
 
1196
1144
  /**
1197
1145
  * setState is separate so any future changes to how state change can be done from one place.
@@ -33,7 +33,7 @@ export class SDKToHMS {
33
33
  isLocal: sdkPeer.isLocal,
34
34
  videoTrack: sdkPeer.videoTrack?.trackId,
35
35
  audioTrack: sdkPeer.audioTrack?.trackId,
36
- auxiliaryTracks: sdkPeer.auxiliaryTracks.map(t => t.trackId),
36
+ auxiliaryTracks: sdkPeer.auxiliaryTracks.map(track => track.trackId),
37
37
  customerUserId: sdkPeer.customerUserId,
38
38
  customerDescription: sdkPeer.customerDescription,
39
39
  };
@@ -1,5 +1,4 @@
1
1
  import { HMSPeer, HMSPeerID, HMSTrack, HMSTrackID } from '../../schema';
2
- import { HMSTrack as SDKHMSTrack } from '@100mslive/hms-video';
3
2
 
4
3
  /**
5
4
  * updates draftPeers with newPeers ensuring minimal reference changes
@@ -14,8 +13,6 @@ import { HMSTrack as SDKHMSTrack } from '@100mslive/hms-video';
14
13
  export const mergeNewPeersInDraft = (
15
14
  draftPeers: Record<HMSPeerID, HMSPeer>,
16
15
  newPeers: Record<HMSPeerID, Partial<HMSPeer>>,
17
- newHmsTracks: Record<HMSTrackID, Partial<HMSTrack>>,
18
- newHmsSDkTracks: Record<HMSTrackID, SDKHMSTrack>,
19
16
  ) => {
20
17
  const peerIDs = union(Object.keys(draftPeers), Object.keys(newPeers));
21
18
  for (let peerID of peerIDs) {
@@ -25,7 +22,6 @@ export const mergeNewPeersInDraft = (
25
22
  if (areArraysEqual(oldPeer.auxiliaryTracks, newPeer.auxiliaryTracks)) {
26
23
  newPeer.auxiliaryTracks = oldPeer.auxiliaryTracks;
27
24
  }
28
- handleLocalVideoReplaceTrack(oldPeer, newPeer, newHmsTracks, newHmsSDkTracks);
29
25
  Object.assign(oldPeer, newPeer);
30
26
  } else if (isEntityRemoved(oldPeer, newPeer)) {
31
27
  delete draftPeers[peerID];
@@ -100,29 +96,3 @@ const union = <T>(arr1: T[], arr2: T[]): T[] => {
100
96
  }
101
97
  return Array.from(set);
102
98
  };
103
-
104
- /**
105
- * on replace track, use prev video track id in peer object, this is because we
106
- * don't want the peer or peers object reference to change, the fact that the video
107
- * track is changed on mute/unmute because of replace track is abstracted
108
- */
109
- function handleLocalVideoReplaceTrack(
110
- oldPeer: HMSPeer,
111
- newPeer: Partial<HMSPeer>,
112
- newHmsTracks: Record<HMSTrackID, Partial<HMSTrack>>,
113
- newHmsSDkTracks: Record<HMSTrackID, SDKHMSTrack>,
114
- ) {
115
- if (
116
- oldPeer.isLocal &&
117
- oldPeer.videoTrack &&
118
- newPeer.videoTrack &&
119
- oldPeer.videoTrack !== newPeer.videoTrack
120
- ) {
121
- newHmsSDkTracks[oldPeer.videoTrack] = newHmsSDkTracks[newPeer.videoTrack];
122
- delete newHmsSDkTracks[newPeer.videoTrack];
123
- newHmsTracks[oldPeer.videoTrack] = newHmsTracks[newPeer.videoTrack];
124
- newHmsTracks[oldPeer.videoTrack].id = oldPeer.videoTrack;
125
- delete newHmsTracks[newPeer.videoTrack];
126
- newPeer.videoTrack = oldPeer.videoTrack;
127
- }
128
- }
@@ -17,6 +17,7 @@ export enum HMSNotificationSeverity {
17
17
  export enum HMSNotificationTypes {
18
18
  PEER_JOINED = 'PEER_JOINED',
19
19
  PEER_LEFT = 'PEER_LEFT',
20
+ PEER_LIST = 'PEER_LIST',
20
21
  NEW_MESSAGE = 'NEW_MESSAGE',
21
22
  ERROR = 'ERROR',
22
23
  RECONNECTING = 'RECONNECTING',
@@ -98,21 +98,21 @@ describe('peers merge is happening properly', () => {
98
98
  };
99
99
 
100
100
  test('no errors with empty peers', () => {
101
- mergeNewPeersInDraft(draftPeers as peerMap, newPeers, {}, {});
101
+ mergeNewPeersInDraft(draftPeers as peerMap, newPeers);
102
102
  expectNoReferenceChange();
103
103
  expect(draftPeers).toEqual({});
104
104
  });
105
105
 
106
106
  test('peer is deleted from draft if gone', () => {
107
107
  draftPeers[fakePeer.id] = fakePeer;
108
- mergeNewPeersInDraft(draftPeers as peerMap, newPeers, {}, {});
108
+ mergeNewPeersInDraft(draftPeers as peerMap, newPeers);
109
109
  expectNoReferenceChange();
110
110
  expect(draftPeers).toEqual({});
111
111
  });
112
112
 
113
113
  test('new peer is added to draft', () => {
114
114
  newPeers[fakePeer.id] = fakePeer;
115
- mergeNewPeersInDraft(draftPeers as peerMap, newPeers, newTracks, newSDKTracks);
115
+ mergeNewPeersInDraft(draftPeers as peerMap, newPeers);
116
116
  expectNoReferenceChange();
117
117
  expect(draftPeers).toEqual(newPeers);
118
118
  });
@@ -125,7 +125,7 @@ describe('peers merge is happening properly', () => {
125
125
  };
126
126
  draftPeers[fakePeer.id] = fakePeer;
127
127
  newPeers[clonedPeer.id] = clonedPeer;
128
- mergeNewPeersInDraft(draftPeers as peerMap, newPeers, newTracks, newSDKTracks);
128
+ mergeNewPeersInDraft(draftPeers as peerMap, newPeers);
129
129
  expectNoReferenceChange();
130
130
  expect(draftPeers[fakePeer.id]).toBe(fakePeer);
131
131
  expect(draftPeers[fakePeer.id].auxiliaryTracks).toBe(fakePeer.auxiliaryTracks);
@@ -139,7 +139,7 @@ describe('peers merge is happening properly', () => {
139
139
  fakePeer.roleName = 'random';
140
140
  draftPeers[fakePeer.id] = fakePeer;
141
141
  newPeers[clonedPeer.id] = clonedPeer;
142
- mergeNewPeersInDraft(draftPeers as peerMap, newPeers, newTracks, newSDKTracks);
142
+ mergeNewPeersInDraft(draftPeers as peerMap, newPeers);
143
143
  expectNoReferenceChange();
144
144
  expect(fakePeer.roleName).toBe('random');
145
145
  expect(clonedPeer.roleName).toBeUndefined();
@@ -159,7 +159,7 @@ describe('peers merge is happening properly', () => {
159
159
  }
160
160
  newTracks[newVideo.id] = newVideo;
161
161
  newPeers[clonedPeer.id] = clonedPeer;
162
- mergeNewPeersInDraft(draftPeers as peerMap, newPeers, newTracks, newSDKTracks);
162
+ mergeNewPeersInDraft(draftPeers as peerMap, newPeers);
163
163
  expect(draftPeers[fakePeer.id]).toBe(fakePeer);
164
164
  expect(draftPeers[fakePeer.id].videoTrack).toBe(fakePeer.videoTrack);
165
165
  // ensure the unchanged video track id can be used to get the new sdk track