@100mslive/hms-video-store 0.2.82-alpha.1 → 0.2.82-alpha.13

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 (55) hide show
  1. package/dist/core/IHMSActions.d.ts +1 -1
  2. package/dist/core/hmsSDKStore/HMSSDKActions.d.ts +1 -1
  3. package/dist/core/hmsSDKStore/sdkTypes.d.ts +3 -3
  4. package/dist/core/index.d.ts +2 -2
  5. package/dist/core/selectors/selectors.d.ts +3 -9
  6. package/dist/core/selectors/selectorsByID.d.ts +1 -1
  7. package/dist/core/selectors/selectorsByReference.d.ts +1 -1
  8. package/dist/hms-video-store.cjs.js +1 -1
  9. package/dist/hms-video-store.esm.js +1 -1
  10. package/package.json +5 -36
  11. package/src/common/ui-logger.ts +0 -88
  12. package/src/core/IHMSActions.ts +0 -317
  13. package/src/core/IHMSNotifications.ts +0 -16
  14. package/src/core/IHMSStore.ts +0 -59
  15. package/src/core/hmsSDKStore/HMSNotifications.ts +0 -170
  16. package/src/core/hmsSDKStore/HMSPlaylist.ts +0 -77
  17. package/src/core/hmsSDKStore/HMSReactiveStore.ts +0 -262
  18. package/src/core/hmsSDKStore/HMSSDKActions.ts +0 -1113
  19. package/src/core/hmsSDKStore/adapter.ts +0 -234
  20. package/src/core/hmsSDKStore/common/mapping.ts +0 -32
  21. package/src/core/hmsSDKStore/internalTypes.ts +0 -8
  22. package/src/core/hmsSDKStore/sdkTypes.ts +0 -51
  23. package/src/core/hmsSDKStore/sdkUtils/ActionBatcher.ts +0 -60
  24. package/src/core/hmsSDKStore/sdkUtils/sdkUtils.ts +0 -5
  25. package/src/core/hmsSDKStore/sdkUtils/storeMergeUtils.ts +0 -95
  26. package/src/core/index.ts +0 -16
  27. package/src/core/schema/device-change.ts +0 -14
  28. package/src/core/schema/error.ts +0 -13
  29. package/src/core/schema/index.ts +0 -11
  30. package/src/core/schema/message.ts +0 -35
  31. package/src/core/schema/notification.ts +0 -41
  32. package/src/core/schema/peer.ts +0 -72
  33. package/src/core/schema/playlist.ts +0 -114
  34. package/src/core/schema/requests.ts +0 -36
  35. package/src/core/schema/role.ts +0 -5
  36. package/src/core/schema/room.ts +0 -26
  37. package/src/core/schema/schema.ts +0 -94
  38. package/src/core/schema/settings.ts +0 -5
  39. package/src/core/selectors/derivedSelectors.ts +0 -75
  40. package/src/core/selectors/index.ts +0 -5
  41. package/src/core/selectors/playlistselectors.ts +0 -71
  42. package/src/core/selectors/selectorUtils.ts +0 -63
  43. package/src/core/selectors/selectors.ts +0 -347
  44. package/src/core/selectors/selectorsByID.ts +0 -370
  45. package/src/core/selectors/selectorsByReference.ts +0 -34
  46. package/src/index.ts +0 -1
  47. package/src/test/fakeStore.ts +0 -272
  48. package/src/test/fixtures.ts +0 -22
  49. package/src/test/integration/.gitkeep +0 -0
  50. package/src/test/unit/HMSNotifications.test.ts +0 -105
  51. package/src/test/unit/reactiveStore.test.ts +0 -129
  52. package/src/test/unit/roleSelectors.test.ts +0 -78
  53. package/src/test/unit/selectors.test.ts +0 -316
  54. package/src/test/unit/selectorsByReference.test.ts +0 -23
  55. package/src/test/unit/storeMergeUtils.test.ts +0 -165
@@ -1,170 +0,0 @@
1
- import { EventEmitter2 as EventEmitter } from 'eventemitter2';
2
- import { IHMSNotifications } from '../IHMSNotifications';
3
- import { IHMSStore } from '../IHMSStore';
4
- import { selectPeerByID, selectTrackByID } from '../selectors';
5
- import * as sdkTypes from './sdkTypes';
6
- import { PEER_NOTIFICATION_TYPES, TRACK_NOTIFICATION_TYPES } from './common/mapping';
7
- import {
8
- HMSNotification,
9
- HMSNotificationTypes,
10
- HMSNotificationSeverity,
11
- HMSPeer,
12
- HMSException,
13
- HMSMessage,
14
- HMSTrack,
15
- HMSTrackID,
16
- HMSChangeTrackStateRequest,
17
- HMSChangeMultiTrackStateRequest,
18
- HMSLeaveRoomRequest,
19
- HMSDeviceChangeEvent,
20
- HMSPlaylistItem,
21
- } from '../schema';
22
-
23
- const HMS_NOTIFICATION_EVENT = 'hmsNotification';
24
- export class HMSNotifications implements IHMSNotifications {
25
- private id = 0;
26
- private eventEmitter: EventEmitter;
27
- private store: IHMSStore;
28
-
29
- constructor(store: IHMSStore) {
30
- this.store = store;
31
- this.eventEmitter = new EventEmitter();
32
- }
33
-
34
- onNotification = (cb: (notification: HMSNotification) => void): (() => void) => {
35
- this.eventEmitter.addListener(HMS_NOTIFICATION_EVENT, cb);
36
- return () => {
37
- this.eventEmitter.removeListener(HMS_NOTIFICATION_EVENT, cb);
38
- };
39
- };
40
-
41
- sendPlaylistTrackEnded<T>(item: HMSPlaylistItem<T>): void {
42
- const notification = this.createNotification(
43
- HMSNotificationTypes.PLAYLIST_TRACK_ENDED,
44
- item,
45
- HMSNotificationSeverity.INFO,
46
- );
47
- this.emitEvent(notification);
48
- }
49
-
50
- sendDeviceChange(request: HMSDeviceChangeEvent) {
51
- const notification = this.createNotification(
52
- HMSNotificationTypes.DEVICE_CHANGE_UPDATE,
53
- request,
54
- request.error ? HMSNotificationSeverity.ERROR : HMSNotificationSeverity.INFO,
55
- `Selected ${request.type} device - ${request.selection?.label}`,
56
- );
57
- this.emitEvent(notification);
58
- }
59
-
60
- sendLeaveRoom(request: HMSLeaveRoomRequest) {
61
- const peerName = request.requestedBy?.name;
62
- const notification = this.createNotification(
63
- request.roomEnded || !peerName ? HMSNotificationTypes.ROOM_ENDED : HMSNotificationTypes.REMOVED_FROM_ROOM,
64
- request,
65
- HMSNotificationSeverity.INFO,
66
- `${request.roomEnded ? `Room ended` : 'Removed from room'} ${peerName ? `by ${peerName}` : ''}`,
67
- );
68
- this.emitEvent(notification);
69
- }
70
-
71
- sendPeerList(peers: HMSPeer[]) {
72
- const notification = this.createNotification(HMSNotificationTypes.PEER_LIST, peers, HMSNotificationSeverity.INFO);
73
- this.emitEvent(notification);
74
- }
75
-
76
- sendPeerUpdate(type: sdkTypes.HMSPeerUpdate, peer: HMSPeer | null) {
77
- const hmsPeer = this.store.getState(selectPeerByID(peer?.id)) || peer;
78
- const notificationType = PEER_NOTIFICATION_TYPES[type];
79
- if (notificationType) {
80
- const notification = this.createNotification(notificationType, hmsPeer, HMSNotificationSeverity.INFO);
81
- this.emitEvent(notification);
82
- }
83
- }
84
-
85
- sendTrackUpdate(type: sdkTypes.HMSTrackUpdate, trackID: HMSTrackID) {
86
- const hmsTrack = this.store.getState(selectTrackByID(trackID));
87
- const notificationType = TRACK_NOTIFICATION_TYPES[type];
88
- if (notificationType) {
89
- const notification = this.createNotification(notificationType, hmsTrack, HMSNotificationSeverity.INFO);
90
- this.emitEvent(notification);
91
- }
92
- }
93
-
94
- sendMessageReceived(message: HMSMessage) {
95
- const notification = this.createNotification(
96
- HMSNotificationTypes.NEW_MESSAGE,
97
- message,
98
- HMSNotificationSeverity.INFO,
99
- );
100
- this.emitEvent(notification);
101
- }
102
-
103
- sendError(error: HMSException) {
104
- const notification = this.createNotification(HMSNotificationTypes.ERROR, error, HMSNotificationSeverity.ERROR);
105
- this.emitEvent(notification);
106
- }
107
-
108
- sendReconnecting(error: HMSException) {
109
- const notification = this.createNotification(
110
- HMSNotificationTypes.RECONNECTING,
111
- error,
112
- HMSNotificationSeverity.ERROR,
113
- );
114
- this.emitEvent(notification);
115
- }
116
-
117
- sendReconnected() {
118
- const notification = this.createNotification(HMSNotificationTypes.RECONNECTED, null, HMSNotificationSeverity.INFO);
119
- this.emitEvent(notification);
120
- }
121
-
122
- sendChangeTrackStateRequest(request: HMSChangeTrackStateRequest) {
123
- const notification = this.createNotification(
124
- HMSNotificationTypes.CHANGE_TRACK_STATE_REQUEST,
125
- request,
126
- HMSNotificationSeverity.INFO,
127
- );
128
- this.emitEvent(notification);
129
- }
130
-
131
- sendChangeMultiTrackStateRequest(request: HMSChangeMultiTrackStateRequest) {
132
- const notification = this.createNotification(
133
- HMSNotificationTypes.CHANGE_MULTI_TRACK_STATE_REQUEST,
134
- request,
135
- HMSNotificationSeverity.INFO,
136
- );
137
- this.emitEvent(notification);
138
- }
139
-
140
- private emitEvent(notification: HMSNotification) {
141
- this.eventEmitter.emit(HMS_NOTIFICATION_EVENT, notification);
142
- }
143
-
144
- private createNotification<T>(
145
- type: string,
146
- data?:
147
- | HMSPeer
148
- | HMSPeer[]
149
- | HMSTrack
150
- | HMSMessage
151
- | HMSException
152
- | HMSChangeTrackStateRequest
153
- | HMSChangeMultiTrackStateRequest
154
- | HMSLeaveRoomRequest
155
- | HMSDeviceChangeEvent
156
- | HMSPlaylistItem<T>
157
- | null,
158
- severity?: HMSNotificationSeverity,
159
- message = '',
160
- ): HMSNotification {
161
- this.id++;
162
- return {
163
- id: this.id,
164
- type,
165
- message,
166
- data,
167
- severity,
168
- };
169
- }
170
- }
@@ -1,77 +0,0 @@
1
- import { HMSPlaylistItem, HMSPlaylistType, IHMSPlaylistActions } from '../schema';
2
- import { HMSPlaylistManager } from './sdkTypes';
3
- import { HMSLogger } from '../../common/ui-logger';
4
- import { IHMSStore } from '../IHMSStore';
5
- import { selectVideoPlaylist, selectAudioPlaylist } from '../selectors';
6
-
7
- export class HMSPlaylist implements IHMSPlaylistActions {
8
- private type: HMSPlaylistType;
9
- constructor(
10
- private playlistManager: HMSPlaylistManager,
11
- type: HMSPlaylistType,
12
- private syncPlaylistState: (action: string) => void,
13
- private store: IHMSStore,
14
- ) {
15
- this.type = type;
16
- }
17
-
18
- async play(id: string): Promise<void> {
19
- if (!id) {
20
- HMSLogger.w('Please pass id to play');
21
- return;
22
- }
23
- await this.playlistManager.setEnabled(true, { id, type: this.type });
24
- }
25
-
26
- async pause(): Promise<void> {
27
- const selector = this.type === HMSPlaylistType.audio ? selectAudioPlaylist : selectVideoPlaylist;
28
- const selection = this.store.getState(selector.selection);
29
- if (!selection.id) {
30
- HMSLogger.w('No item is currently playing to pause');
31
- return;
32
- }
33
- await this.playlistManager.setEnabled(false, { id: selection.id, type: this.type });
34
- }
35
-
36
- async playNext(): Promise<void> {
37
- await this.playlistManager.playNext(this.type);
38
- }
39
-
40
- async playPrevious(): Promise<void> {
41
- await this.playlistManager.playPrevious(this.type);
42
- }
43
-
44
- seek(seekValue: number): void {
45
- this.playlistManager.seek(seekValue, this.type);
46
- this.syncPlaylistState(`seekOn${this.type}Playlist`);
47
- }
48
-
49
- seekTo(seekValue: number): void {
50
- this.playlistManager.seekTo(seekValue, this.type);
51
- this.syncPlaylistState(`seekToOn${this.type}Playlist`);
52
- }
53
-
54
- setVolume(volume: number): void {
55
- this.playlistManager.setVolume(volume, this.type);
56
- this.syncPlaylistState(`setVolumeOn${this.type}Playlist`);
57
- }
58
-
59
- setList<T>(list: HMSPlaylistItem<T>[]): void {
60
- this.playlistManager.setList(list);
61
- this.syncPlaylistState(`setListOn${this.type}Playlist`);
62
- }
63
-
64
- async stop(): Promise<void> {
65
- await this.playlistManager.stop(this.type);
66
- this.syncPlaylistState(`stop${this.type}Playlist`);
67
- }
68
-
69
- setIsAutoplayOn(autoplay: boolean) {
70
- this.playlistManager.setIsAutoplayOn(this.type, autoplay);
71
- }
72
-
73
- setPlaybackRate(playbackRate: number) {
74
- this.playlistManager.setPlaybackRate(this.type, playbackRate);
75
- this.syncPlaylistState(`set${this.type}PlaybackRate`);
76
- }
77
- }
@@ -1,262 +0,0 @@
1
- import produce from 'immer';
2
- import create, {
3
- StateSelector,
4
- StoreApi,
5
- SetState,
6
- StateSliceListener,
7
- EqualityChecker,
8
- PartialState,
9
- State,
10
- } from 'zustand/vanilla';
11
- import shallow from 'zustand/shallow';
12
- import { HMSSdk } from '@100mslive/hms-video';
13
- import { IHMSActions } from '../IHMSActions';
14
- import { HMSSDKActions } from './HMSSDKActions';
15
- import { IHMSStore, IHMSStoreReadOnly } from '../IHMSStore';
16
- import { createDefaultStoreState, HMSStore } from '../schema';
17
- import { HMSNotifications } from './HMSNotifications';
18
- import { IHMSNotifications } from '../IHMSNotifications';
19
- import { NamedSetState } from './internalTypes';
20
-
21
- export class HMSReactiveStore {
22
- private readonly actions: IHMSActions;
23
- private readonly store: IHMSStore;
24
- private readonly notifications: HMSNotifications;
25
- private initialTriggerOnSubscribe: boolean;
26
-
27
- constructor(hmsStore?: IHMSStore, hmsActions?: IHMSActions, hmsNotifications?: HMSNotifications) {
28
- if (hmsStore) {
29
- this.store = hmsStore;
30
- } else {
31
- this.store = HMSReactiveStore.createNewHMSStore();
32
- }
33
- if (hmsNotifications) {
34
- this.notifications = hmsNotifications;
35
- } else {
36
- this.notifications = new HMSNotifications(this.store);
37
- }
38
- if (hmsActions) {
39
- this.actions = hmsActions;
40
- } else {
41
- this.actions = new HMSSDKActions(this.store, new HMSSdk(), this.notifications);
42
- }
43
- this.initialTriggerOnSubscribe = false;
44
- }
45
-
46
- /**
47
- * By default store.subscribe does not call the handler with the current state at time of subscription,
48
- * this behaviour can be modified by calling this function. What it means is that instead of calling the
49
- * handler only for changes which happen post subscription we'll also call it exactly once at the time
50
- * of subscription with the current state. This behaviour is similar to that of BehaviourSubject in rxjs.
51
- * This will be an irreversible change
52
- *
53
- * Note: you don't need this if you're using our react hooks, it takes care of this requirement.
54
- */
55
- triggerOnSubscribe(): void {
56
- if (this.initialTriggerOnSubscribe) {
57
- // already done
58
- return;
59
- }
60
- HMSReactiveStore.makeStoreTriggerOnSubscribe(this.store);
61
- this.initialTriggerOnSubscribe = true;
62
- }
63
-
64
- /**
65
- * A reactive store which has a subscribe method you can use in combination with selectors
66
- * to subscribe to a subset of the store. The store serves as a single source of truth for
67
- * all data related to the corresponding HMS Room.
68
- */
69
- getStore(): IHMSStoreReadOnly {
70
- return this.store;
71
- }
72
-
73
- /**
74
- * Any action which may modify the store or may need to talk to the SDK will happen
75
- * through the IHMSActions instance returned by this
76
- */
77
- getHMSActions(): IHMSActions {
78
- return this.actions;
79
- }
80
-
81
- /**
82
- * This return notification handler function to which you can pass your callback to
83
- * receive notifications like peer joined, peer left, etc. to show in your UI or use
84
- * for analytics
85
- */
86
- getNotifications(): IHMSNotifications {
87
- return { onNotification: this.notifications.onNotification };
88
- }
89
-
90
- /**
91
- * @internal
92
- */
93
- static createNewHMSStore(): IHMSStore {
94
- const hmsStore = create<HMSStore>(() => createDefaultStoreState());
95
- // make set state immutable, by passing functions through immer
96
- const savedSetState = hmsStore.setState;
97
- hmsStore.setState = (partial: any) => {
98
- const nextState = typeof partial === 'function' ? produce(partial) : partial;
99
- savedSetState(nextState);
100
- };
101
- // add option to pass selector to getState
102
- const prevGetState = hmsStore.getState;
103
- // eslint-disable-next-line complexity
104
- hmsStore.getState = <StateSlice>(selector?: StateSelector<HMSStore, StateSlice>) => {
105
- if (selector) {
106
- const name = selector.name || 'byIDSelector';
107
- // @ts-ignore
108
- if (!window.selectorsCount) {
109
- // @ts-ignore
110
- window.selectorsCount = {};
111
- }
112
- // @ts-ignore
113
- window.selectorsCount[name] = (window.selectorsCount[name] || 0) + 1;
114
- const start = performance.now();
115
- const updatedState = selector(prevGetState());
116
- const diff = performance.now() - start;
117
- // store selectors that take more than 1ms
118
- if (diff > 1) {
119
- // @ts-ignore
120
- window.expensiveSelectors = window.expensiveSelectors || new Map();
121
- // @ts-ignore
122
- window.expensiveSelectors.set(name, diff);
123
- }
124
- return updatedState;
125
- }
126
- return prevGetState();
127
- };
128
- HMSReactiveStore.useShallowCheckInSubscribe(hmsStore);
129
- const namedSetState = HMSReactiveStore.setUpDevtools(hmsStore, 'HMSStore');
130
- return { ...hmsStore, namedSetState };
131
- }
132
-
133
- /**
134
- * @internal
135
- */
136
- static makeStoreTriggerOnSubscribe(store: IHMSStore) {
137
- const prevSubscribe = store.subscribe;
138
- store.subscribe = <StateSlice>(
139
- listener: StateSliceListener<StateSlice>,
140
- selector?: StateSelector<HMSStore, StateSlice>,
141
- equalityFn?: EqualityChecker<StateSlice>,
142
- ): (() => void) => {
143
- // initial call, the prev state will always be null for this
144
- listener(store.getState(selector), undefined as unknown as StateSlice);
145
- // then subscribe
146
- return prevSubscribe(listener, selector!, equalityFn);
147
- };
148
- }
149
-
150
- /**
151
- * use shallow equality check by default for subscribe to optimize for array/object selectors.
152
- * by default zustand does only reference matching so something like, getPeers for eg. would trigger
153
- * the corresponding component even if peers didn't actually change, as selectPeers creates a new array everytime.
154
- * Although the array reference changes, the order of peers and peer objects don't themselves change in this case,
155
- * and a shallow check avoids that triggering.
156
- * @private
157
- */
158
- private static useShallowCheckInSubscribe(hmsStore: StoreApi<HMSStore>) {
159
- const prevSubscribe = hmsStore.subscribe;
160
- hmsStore.subscribe = <StateSlice>(
161
- listener: StateSliceListener<StateSlice>,
162
- selector?: StateSelector<HMSStore, StateSlice>,
163
- equalityFn?: EqualityChecker<StateSlice>,
164
- ): (() => void) => {
165
- if (!selector) {
166
- selector = (store): StateSlice => store as unknown as StateSlice;
167
- }
168
- equalityFn = equalityFn || shallow;
169
- return prevSubscribe(listener, selector, equalityFn);
170
- };
171
- }
172
-
173
- /**
174
- * @private
175
- * @privateRemarks
176
- * sets up redux devtools for the store, so redux extension can be used to visualize the store.
177
- * zustand's default devtool middleware only enhances the set function, we're here creating another nameSetState in
178
- * IHMStore which behaves like setState but takes an extra parameter for action name
179
- * https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Methods.md
180
- * modified version of zustand's devtools - https://github.com/pmndrs/zustand/blob/v3.5.7/src/middleware.ts#L46
181
- */
182
- private static setUpDevtools<T extends State>(api: StoreApi<T>, prefix: string): NamedSetState<HMSStore> {
183
- let extension;
184
- try {
185
- extension = (window as any).__REDUX_DEVTOOLS_EXTENSION__ || (window as any).top.__REDUX_DEVTOOLS_EXTENSION__;
186
- } catch {}
187
- if (!extension) {
188
- return (fn: any) => {
189
- api.setState(fn);
190
- };
191
- }
192
- const devtools = extension.connect(HMSReactiveStore.devtoolsOptions(prefix));
193
- devtools.prefix = prefix ? `${prefix} > ` : '';
194
- const savedSetState = api.setState;
195
- api.setState = (fn: any) => {
196
- savedSetState(fn);
197
- devtools.send(`${devtools.prefix}setState`, api.getState());
198
- };
199
-
200
- devtools.subscribe(HMSReactiveStore.devtoolsSubscribe(devtools, api, savedSetState));
201
-
202
- devtools.send('setUpStore', api.getState());
203
-
204
- return (fn: any, action?: string) => {
205
- savedSetState(fn);
206
- const actionName = action ? action : `${devtools.prefix}action`;
207
- devtools.send(actionName, api.getState());
208
- };
209
- }
210
-
211
- /**
212
- * https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md
213
- */
214
- private static devtoolsOptions(prefix: string) {
215
- return {
216
- name: prefix,
217
- actionsBlacklist: ['audioLevel', 'playlistProgress'], // very high frequency update, pollutes the action history
218
- };
219
- }
220
-
221
- /**
222
- * redux devtools allows for time travel debugging where it sends an action to update the store, users can
223
- * also export and import state in the devtools, listen to the corresponding functions from devtools and take
224
- * required action.
225
- * @param devtools - reference to devtools extension object
226
- * @param api
227
- * @param savedSetState - setState saved before its modified to update devtools
228
- * @private
229
- */
230
- private static devtoolsSubscribe<T extends State>(devtools: any, api: StoreApi<T>, savedSetState: SetState<T>) {
231
- // disabling complexity check instead of refactoring so as to keep the code close to zustand's and make
232
- // any future update based on upstream changes easier.
233
- // eslint-disable-next-line complexity
234
- return (message: any) => {
235
- if (message.type === 'DISPATCH' && message.state) {
236
- const ignoreState = ['JUMP_TO_ACTION', 'JUMP_TO_STATE'].includes(message.payload.type);
237
- if (!ignoreState) {
238
- // manual dispatch from the extension
239
- api.setState(JSON.parse(message.state));
240
- } else {
241
- // for time travel, no need to add new state changes in devtools
242
- savedSetState(JSON.parse(message.state));
243
- }
244
- } else if (message.type === 'DISPATCH' && message.payload?.type === 'COMMIT') {
245
- devtools.init(api.getState());
246
- } else if (message.type === 'DISPATCH' && message.payload?.type === 'IMPORT_STATE') {
247
- const actions = message.payload.nextLiftedState?.actionsById;
248
- const computedStates = message.payload.nextLiftedState?.computedStates || [];
249
-
250
- computedStates.forEach(({ state }: { state: PartialState<T> }, index: number) => {
251
- const action = actions[index] || `${devtools.prefix}setState`;
252
- if (index === 0) {
253
- devtools.init(state);
254
- } else {
255
- savedSetState(state);
256
- devtools.send(action, api.getState());
257
- }
258
- });
259
- }
260
- };
261
- }
262
- }