@100mslive/hms-video-store 0.2.82 → 0.2.83
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/common/ui-logger.d.ts +13 -13
- package/dist/core/IHMSActions.d.ts +266 -264
- package/dist/core/IHMSNotifications.d.ts +14 -15
- package/dist/core/IHMSStore.d.ts +54 -56
- package/dist/core/hmsSDKStore/HMSNotifications.d.ts +25 -25
- package/dist/core/hmsSDKStore/HMSPlaylist.d.ts +21 -21
- package/dist/core/hmsSDKStore/HMSReactiveStore.d.ts +79 -79
- package/dist/core/hmsSDKStore/HMSSDKActions.d.ts +157 -157
- package/dist/core/hmsSDKStore/adapter.d.ts +49 -49
- package/dist/core/hmsSDKStore/common/mapping.d.ts +7 -7
- package/dist/core/hmsSDKStore/internalTypes.d.ts +4 -4
- package/dist/core/hmsSDKStore/sdkTypes.d.ts +3 -2
- package/dist/core/hmsSDKStore/sdkUtils/ActionBatcher.d.ts +19 -19
- package/dist/core/hmsSDKStore/sdkUtils/sdkUtils.d.ts +2 -2
- package/dist/core/hmsSDKStore/sdkUtils/storeMergeUtils.d.ts +14 -14
- package/dist/core/index.d.ts +9 -7
- package/dist/core/schema/device-change.d.ts +13 -13
- package/dist/core/schema/error.d.ts +13 -13
- package/dist/core/schema/index.d.ts +11 -11
- package/dist/core/schema/message.d.ts +31 -31
- package/dist/core/schema/notification.d.ts +40 -40
- package/dist/core/schema/peer.d.ts +67 -67
- package/dist/core/schema/playlist.d.ts +127 -109
- package/dist/core/schema/requests.d.ts +31 -31
- package/dist/core/schema/role.d.ts +3 -3
- package/dist/core/schema/room.d.ts +23 -23
- package/dist/core/schema/schema.d.ts +29 -29
- package/dist/core/schema/settings.d.ts +5 -5
- package/dist/core/selectors/derivedSelectors.d.ts +29 -29
- package/dist/core/selectors/index.d.ts +5 -5
- package/dist/core/selectors/playlistselectors.d.ts +3 -3
- package/dist/core/selectors/selectorUtils.d.ts +18 -18
- package/dist/core/selectors/selectors.d.ts +185 -191
- package/dist/core/selectors/selectorsByID.d.ts +127 -128
- package/dist/core/selectors/selectorsByReference.d.ts +3 -3
- package/dist/hms-video-store.cjs.js +1 -0
- package/dist/hms-video-store.esm.js +1 -5376
- package/dist/index.d.ts +1 -1
- package/package.json +21 -84
- package/dist/hms-video-store.cjs.development.js +0 -5468
- package/dist/hms-video-store.cjs.development.js.map +0 -1
- package/dist/hms-video-store.cjs.production.min.js +0 -2
- package/dist/hms-video-store.cjs.production.min.js.map +0 -1
- package/dist/hms-video-store.esm.js.map +0 -1
- package/dist/index.js +0 -8
- package/dist/test/fakeStore.d.ts +0 -23
- package/dist/test/fixtures.d.ts +0 -3
- package/src/common/ui-logger.ts +0 -88
- package/src/core/IHMSActions.ts +0 -318
- package/src/core/IHMSNotifications.ts +0 -16
- package/src/core/IHMSStore.ts +0 -60
- package/src/core/hmsSDKStore/HMSNotifications.ts +0 -194
- package/src/core/hmsSDKStore/HMSPlaylist.ts +0 -78
- package/src/core/hmsSDKStore/HMSReactiveStore.ts +0 -271
- package/src/core/hmsSDKStore/HMSSDKActions.ts +0 -1156
- package/src/core/hmsSDKStore/adapter.ts +0 -244
- package/src/core/hmsSDKStore/common/mapping.ts +0 -32
- package/src/core/hmsSDKStore/internalTypes.ts +0 -8
- package/src/core/hmsSDKStore/sdkTypes.ts +0 -55
- package/src/core/hmsSDKStore/sdkUtils/ActionBatcher.ts +0 -63
- package/src/core/hmsSDKStore/sdkUtils/sdkUtils.ts +0 -5
- package/src/core/hmsSDKStore/sdkUtils/storeMergeUtils.ts +0 -98
- package/src/core/index.ts +0 -18
- package/src/core/schema/device-change.ts +0 -14
- package/src/core/schema/error.ts +0 -13
- package/src/core/schema/index.ts +0 -11
- package/src/core/schema/message.ts +0 -35
- package/src/core/schema/notification.ts +0 -41
- package/src/core/schema/peer.ts +0 -78
- package/src/core/schema/playlist.ts +0 -114
- package/src/core/schema/requests.ts +0 -36
- package/src/core/schema/role.ts +0 -5
- package/src/core/schema/room.ts +0 -26
- package/src/core/schema/schema.ts +0 -94
- package/src/core/schema/settings.ts +0 -5
- package/src/core/selectors/derivedSelectors.ts +0 -81
- package/src/core/selectors/index.ts +0 -5
- package/src/core/selectors/playlistselectors.ts +0 -67
- package/src/core/selectors/selectorUtils.ts +0 -63
- package/src/core/selectors/selectors.ts +0 -400
- package/src/core/selectors/selectorsByID.ts +0 -401
- package/src/core/selectors/selectorsByReference.ts +0 -45
- package/src/index.ts +0 -1
- package/src/test/fakeStore.ts +0 -272
- package/src/test/fixtures.ts +0 -22
- package/src/test/integration/.gitkeep +0 -0
- package/src/test/unit/HMSNotifications.test.ts +0 -123
- package/src/test/unit/reactiveStore.test.ts +0 -129
- package/src/test/unit/roleSelectors.test.ts +0 -85
- package/src/test/unit/selectors.test.ts +0 -316
- package/src/test/unit/selectorsByReference.test.ts +0 -27
- package/src/test/unit/storeMergeUtils.test.ts +0 -168
|
@@ -1,194 +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: number = 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
|
|
64
|
-
? HMSNotificationTypes.ROOM_ENDED
|
|
65
|
-
: HMSNotificationTypes.REMOVED_FROM_ROOM,
|
|
66
|
-
request,
|
|
67
|
-
HMSNotificationSeverity.INFO,
|
|
68
|
-
`${request.roomEnded ? `Room ended` : 'Removed from room'} ${
|
|
69
|
-
peerName ? `by ${peerName}` : ''
|
|
70
|
-
}`,
|
|
71
|
-
);
|
|
72
|
-
this.emitEvent(notification);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
sendPeerList(peers: HMSPeer[]) {
|
|
76
|
-
const notification = this.createNotification(
|
|
77
|
-
HMSNotificationTypes.PEER_LIST,
|
|
78
|
-
peers,
|
|
79
|
-
HMSNotificationSeverity.INFO,
|
|
80
|
-
);
|
|
81
|
-
this.emitEvent(notification);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
sendPeerUpdate(type: sdkTypes.HMSPeerUpdate, peer: HMSPeer | null) {
|
|
85
|
-
const hmsPeer = this.store.getState(selectPeerByID(peer?.id)) || peer;
|
|
86
|
-
const notificationType = PEER_NOTIFICATION_TYPES[type];
|
|
87
|
-
if (notificationType) {
|
|
88
|
-
const notification = this.createNotification(
|
|
89
|
-
notificationType,
|
|
90
|
-
hmsPeer,
|
|
91
|
-
HMSNotificationSeverity.INFO,
|
|
92
|
-
);
|
|
93
|
-
this.emitEvent(notification);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
sendTrackUpdate(type: sdkTypes.HMSTrackUpdate, trackID: HMSTrackID) {
|
|
98
|
-
const hmsTrack = this.store.getState(selectTrackByID(trackID));
|
|
99
|
-
const notificationType = TRACK_NOTIFICATION_TYPES[type];
|
|
100
|
-
if (notificationType) {
|
|
101
|
-
const notification = this.createNotification(
|
|
102
|
-
notificationType,
|
|
103
|
-
hmsTrack,
|
|
104
|
-
HMSNotificationSeverity.INFO,
|
|
105
|
-
);
|
|
106
|
-
this.emitEvent(notification);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
sendMessageReceived(message: HMSMessage) {
|
|
111
|
-
const notification = this.createNotification(
|
|
112
|
-
HMSNotificationTypes.NEW_MESSAGE,
|
|
113
|
-
message,
|
|
114
|
-
HMSNotificationSeverity.INFO,
|
|
115
|
-
);
|
|
116
|
-
this.emitEvent(notification);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
sendError(error: HMSException) {
|
|
120
|
-
const notification = this.createNotification(
|
|
121
|
-
HMSNotificationTypes.ERROR,
|
|
122
|
-
error,
|
|
123
|
-
HMSNotificationSeverity.ERROR,
|
|
124
|
-
);
|
|
125
|
-
this.emitEvent(notification);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
sendReconnecting(error: HMSException) {
|
|
129
|
-
const notification = this.createNotification(
|
|
130
|
-
HMSNotificationTypes.RECONNECTING,
|
|
131
|
-
error,
|
|
132
|
-
HMSNotificationSeverity.ERROR,
|
|
133
|
-
);
|
|
134
|
-
this.emitEvent(notification);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
sendReconnected() {
|
|
138
|
-
const notification = this.createNotification(
|
|
139
|
-
HMSNotificationTypes.RECONNECTED,
|
|
140
|
-
null,
|
|
141
|
-
HMSNotificationSeverity.INFO,
|
|
142
|
-
);
|
|
143
|
-
this.emitEvent(notification);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
sendChangeTrackStateRequest(request: HMSChangeTrackStateRequest) {
|
|
147
|
-
const notification = this.createNotification(
|
|
148
|
-
HMSNotificationTypes.CHANGE_TRACK_STATE_REQUEST,
|
|
149
|
-
request,
|
|
150
|
-
HMSNotificationSeverity.INFO,
|
|
151
|
-
);
|
|
152
|
-
this.emitEvent(notification);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
sendChangeMultiTrackStateRequest(request: HMSChangeMultiTrackStateRequest) {
|
|
156
|
-
const notification = this.createNotification(
|
|
157
|
-
HMSNotificationTypes.CHANGE_MULTI_TRACK_STATE_REQUEST,
|
|
158
|
-
request,
|
|
159
|
-
HMSNotificationSeverity.INFO,
|
|
160
|
-
);
|
|
161
|
-
this.emitEvent(notification);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
private emitEvent(notification: HMSNotification) {
|
|
165
|
-
this.eventEmitter.emit(HMS_NOTIFICATION_EVENT, notification);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
private createNotification<T>(
|
|
169
|
-
type: string,
|
|
170
|
-
data?:
|
|
171
|
-
| HMSPeer
|
|
172
|
-
| HMSPeer[]
|
|
173
|
-
| HMSTrack
|
|
174
|
-
| HMSMessage
|
|
175
|
-
| HMSException
|
|
176
|
-
| HMSChangeTrackStateRequest
|
|
177
|
-
| HMSChangeMultiTrackStateRequest
|
|
178
|
-
| HMSLeaveRoomRequest
|
|
179
|
-
| HMSDeviceChangeEvent
|
|
180
|
-
| HMSPlaylistItem<T>
|
|
181
|
-
| null,
|
|
182
|
-
severity?: HMSNotificationSeverity,
|
|
183
|
-
message: string = '',
|
|
184
|
-
): HMSNotification {
|
|
185
|
-
this.id++;
|
|
186
|
-
return {
|
|
187
|
-
id: this.id,
|
|
188
|
-
type,
|
|
189
|
-
message,
|
|
190
|
-
data,
|
|
191
|
-
severity,
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
}
|
|
@@ -1,78 +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 =
|
|
28
|
-
this.type === HMSPlaylistType.audio ? selectAudioPlaylist : selectVideoPlaylist;
|
|
29
|
-
const selection = this.store.getState(selector.selection);
|
|
30
|
-
if (!selection.id) {
|
|
31
|
-
HMSLogger.w('No item is currently playing to pause');
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
await this.playlistManager.setEnabled(false, { id: selection.id, type: this.type });
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async playNext(): Promise<void> {
|
|
38
|
-
await this.playlistManager.playNext(this.type);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async playPrevious(): Promise<void> {
|
|
42
|
-
await this.playlistManager.playPrevious(this.type);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
seek(seekValue: number): void {
|
|
46
|
-
this.playlistManager.seek(seekValue, this.type);
|
|
47
|
-
this.syncPlaylistState(`seekOn${this.type}Playlist`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
seekTo(seekValue: number): void {
|
|
51
|
-
this.playlistManager.seekTo(seekValue, this.type);
|
|
52
|
-
this.syncPlaylistState(`seekToOn${this.type}Playlist`);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
setVolume(volume: number): void {
|
|
56
|
-
this.playlistManager.setVolume(volume, this.type);
|
|
57
|
-
this.syncPlaylistState(`setVolumeOn${this.type}Playlist`);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
setList<T>(list: HMSPlaylistItem<T>[]): void {
|
|
61
|
-
this.playlistManager.setList(list);
|
|
62
|
-
this.syncPlaylistState(`setListOn${this.type}Playlist`);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async stop(): Promise<void> {
|
|
66
|
-
await this.playlistManager.stop(this.type);
|
|
67
|
-
this.syncPlaylistState(`stop${this.type}Playlist`);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
setIsAutoplayOn(autoplay: boolean) {
|
|
71
|
-
this.playlistManager.setIsAutoplayOn(this.type, autoplay);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
setPlaybackRate(playbackRate: number) {
|
|
75
|
-
this.playlistManager.setPlaybackRate(this.type, playbackRate);
|
|
76
|
-
this.syncPlaylistState(`set${this.type}PlaybackRate`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
@@ -1,271 +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>(
|
|
183
|
-
api: StoreApi<T>,
|
|
184
|
-
prefix: string,
|
|
185
|
-
): NamedSetState<HMSStore> {
|
|
186
|
-
let extension;
|
|
187
|
-
try {
|
|
188
|
-
extension =
|
|
189
|
-
(window as any).__REDUX_DEVTOOLS_EXTENSION__ ||
|
|
190
|
-
(window as any).top.__REDUX_DEVTOOLS_EXTENSION__;
|
|
191
|
-
} catch {}
|
|
192
|
-
if (!extension) {
|
|
193
|
-
return (fn: any) => {
|
|
194
|
-
api.setState(fn);
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
const devtools = extension.connect(HMSReactiveStore.devtoolsOptions(prefix));
|
|
198
|
-
devtools.prefix = prefix ? `${prefix} > ` : '';
|
|
199
|
-
const savedSetState = api.setState;
|
|
200
|
-
api.setState = (fn: any) => {
|
|
201
|
-
savedSetState(fn);
|
|
202
|
-
devtools.send(`${devtools.prefix}setState`, api.getState());
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
devtools.subscribe(HMSReactiveStore.devtoolsSubscribe(devtools, api, savedSetState));
|
|
206
|
-
|
|
207
|
-
devtools.send('setUpStore', api.getState());
|
|
208
|
-
|
|
209
|
-
return (fn: any, action?: string) => {
|
|
210
|
-
savedSetState(fn);
|
|
211
|
-
const actionName = action ? action : `${devtools.prefix}action`;
|
|
212
|
-
devtools.send(actionName, api.getState());
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md
|
|
218
|
-
*/
|
|
219
|
-
private static devtoolsOptions(prefix: string) {
|
|
220
|
-
return {
|
|
221
|
-
name: prefix,
|
|
222
|
-
actionsBlacklist: ['audioLevel', 'playlistProgress'], // very high frequency update, pollutes the action history
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* redux devtools allows for time travel debugging where it sends an action to update the store, users can
|
|
228
|
-
* also export and import state in the devtools, listen to the corresponding functions from devtools and take
|
|
229
|
-
* required action.
|
|
230
|
-
* @param devtools - reference to devtools extension object
|
|
231
|
-
* @param api
|
|
232
|
-
* @param savedSetState - setState saved before its modified to update devtools
|
|
233
|
-
* @private
|
|
234
|
-
*/
|
|
235
|
-
private static devtoolsSubscribe<T extends State>(
|
|
236
|
-
devtools: any,
|
|
237
|
-
api: StoreApi<T>,
|
|
238
|
-
savedSetState: SetState<T>,
|
|
239
|
-
) {
|
|
240
|
-
// disabling complexity check instead of refactoring so as to keep the code close to zustand's and make
|
|
241
|
-
// any future update based on upstream changes easier.
|
|
242
|
-
// eslint-disable-next-line complexity
|
|
243
|
-
return (message: any) => {
|
|
244
|
-
if (message.type === 'DISPATCH' && message.state) {
|
|
245
|
-
const ignoreState = ['JUMP_TO_ACTION', 'JUMP_TO_STATE'].includes(message.payload.type);
|
|
246
|
-
if (!ignoreState) {
|
|
247
|
-
// manual dispatch from the extension
|
|
248
|
-
api.setState(JSON.parse(message.state));
|
|
249
|
-
} else {
|
|
250
|
-
// for time travel, no need to add new state changes in devtools
|
|
251
|
-
savedSetState(JSON.parse(message.state));
|
|
252
|
-
}
|
|
253
|
-
} else if (message.type === 'DISPATCH' && message.payload?.type === 'COMMIT') {
|
|
254
|
-
devtools.init(api.getState());
|
|
255
|
-
} else if (message.type === 'DISPATCH' && message.payload?.type === 'IMPORT_STATE') {
|
|
256
|
-
const actions = message.payload.nextLiftedState?.actionsById;
|
|
257
|
-
const computedStates = message.payload.nextLiftedState?.computedStates || [];
|
|
258
|
-
|
|
259
|
-
computedStates.forEach(({ state }: { state: PartialState<T> }, index: number) => {
|
|
260
|
-
const action = actions[index] || `${devtools.prefix}setState`;
|
|
261
|
-
if (index === 0) {
|
|
262
|
-
devtools.init(state);
|
|
263
|
-
} else {
|
|
264
|
-
savedSetState(state);
|
|
265
|
-
devtools.send(action, api.getState());
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
}
|