@whereby.com/core 0.15.1 → 0.16.0
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/index.cjs +525 -170
- package/dist/index.d.cts +2434 -263
- package/dist/index.d.mts +2434 -263
- package/dist/index.d.ts +2434 -263
- package/dist/index.mjs +496 -169
- package/package.json +2 -5
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createAsyncThunk, createListenerMiddleware, addListener, createSlice, createAction, createSelector, isAnyOf, combineReducers, configureStore } from '@reduxjs/toolkit';
|
|
2
2
|
import { ServerSocket, getDeviceData, getStream, getUpdatedDevices, RtcManagerDispatcher, assert, fromLocation } from '@whereby.com/media';
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
3
4
|
import { Chrome111 } from 'mediasoup-client/lib/handlers/Chrome111.js';
|
|
4
5
|
import nodeBtoa from 'btoa';
|
|
5
6
|
import axios from 'axios';
|
|
6
|
-
import EventEmitter from 'events';
|
|
7
7
|
|
|
8
8
|
function createAppAsyncThunk(typePrefix, payloadCreator) {
|
|
9
9
|
return createAsyncThunk(typePrefix, payloadCreator);
|
|
@@ -43,9 +43,9 @@ const createReactor = (selectors, callback) => {
|
|
|
43
43
|
});
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
const coreVersion = "0.
|
|
46
|
+
const coreVersion = "0.16.0";
|
|
47
47
|
|
|
48
|
-
const initialState$
|
|
48
|
+
const initialState$f = {
|
|
49
49
|
isNodeSdk: false,
|
|
50
50
|
isActive: false,
|
|
51
51
|
roomName: null,
|
|
@@ -56,7 +56,7 @@ const initialState$e = {
|
|
|
56
56
|
};
|
|
57
57
|
const appSlice = createSlice({
|
|
58
58
|
name: "app",
|
|
59
|
-
initialState: initialState$
|
|
59
|
+
initialState: initialState$f,
|
|
60
60
|
reducers: {
|
|
61
61
|
doAppStart: (state, action) => {
|
|
62
62
|
const url = new URL(action.payload.roomUrl);
|
|
@@ -101,6 +101,8 @@ const signalEvents = {
|
|
|
101
101
|
roomSessionEnded: createSignalEventAction("roomSessionEnded"),
|
|
102
102
|
screenshareStarted: createSignalEventAction("screenshareStarted"),
|
|
103
103
|
screenshareStopped: createSignalEventAction("screenshareStopped"),
|
|
104
|
+
spotlightAdded: createSignalEventAction("spotlightAdded"),
|
|
105
|
+
spotlightRemoved: createSignalEventAction("spotlightRemoved"),
|
|
104
106
|
streamingStopped: createSignalEventAction("streamingStopped"),
|
|
105
107
|
videoEnabled: createSignalEventAction("videoEnabled"),
|
|
106
108
|
};
|
|
@@ -110,14 +112,16 @@ const ROOM_ACTION_PERMISSIONS_BY_ROLE = {
|
|
|
110
112
|
canRequestAudioEnable: ["host"],
|
|
111
113
|
canKickClient: ["host"],
|
|
112
114
|
canEndMeeting: ["host"],
|
|
115
|
+
canAskToSpeak: ["host"],
|
|
116
|
+
canSpotlight: ["host"],
|
|
113
117
|
};
|
|
114
|
-
const initialState$
|
|
118
|
+
const initialState$e = {
|
|
115
119
|
roomKey: null,
|
|
116
120
|
roleName: "none",
|
|
117
121
|
};
|
|
118
122
|
const authorizationSlice = createSlice({
|
|
119
123
|
name: "authorization",
|
|
120
|
-
initialState: initialState$
|
|
124
|
+
initialState: initialState$e,
|
|
121
125
|
reducers: {
|
|
122
126
|
setRoomKey: (state, action) => {
|
|
123
127
|
return Object.assign(Object.assign({}, state), { roomKey: action.payload });
|
|
@@ -141,6 +145,8 @@ const selectIsAuthorizedToLockRoom = createSelector(selectAuthorizationRoleName,
|
|
|
141
145
|
const selectIsAuthorizedToRequestAudioEnable = createSelector(selectAuthorizationRoleName, (localParticipantRole) => ROOM_ACTION_PERMISSIONS_BY_ROLE.canRequestAudioEnable.includes(localParticipantRole));
|
|
142
146
|
const selectIsAuthorizedToKickClient = createSelector(selectAuthorizationRoleName, (localParticipantRole) => ROOM_ACTION_PERMISSIONS_BY_ROLE.canKickClient.includes(localParticipantRole));
|
|
143
147
|
const selectIsAuthorizedToEndMeeting = createSelector(selectAuthorizationRoleName, (localParticipantRole) => ROOM_ACTION_PERMISSIONS_BY_ROLE.canEndMeeting.includes(localParticipantRole));
|
|
148
|
+
const selectIsAuthorizedToAskToSpeak = createSelector(selectAuthorizationRoleName, (localParticipantRole) => ROOM_ACTION_PERMISSIONS_BY_ROLE.canAskToSpeak.includes(localParticipantRole));
|
|
149
|
+
const selectIsAuthorizedToSpotlight = createSelector(selectAuthorizationRoleName, (localParticipantRole) => ROOM_ACTION_PERMISSIONS_BY_ROLE.canSpotlight.includes(localParticipantRole));
|
|
144
150
|
|
|
145
151
|
/******************************************************************************
|
|
146
152
|
Copyright (c) Microsoft Corporation.
|
|
@@ -186,13 +192,13 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
186
192
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
187
193
|
};
|
|
188
194
|
|
|
189
|
-
const initialState$
|
|
195
|
+
const initialState$d = {
|
|
190
196
|
isFetching: false,
|
|
191
197
|
data: null,
|
|
192
198
|
};
|
|
193
199
|
const deviceCredentialsSlice = createSlice({
|
|
194
200
|
name: "deviceCredentials",
|
|
195
|
-
initialState: initialState$
|
|
201
|
+
initialState: initialState$d,
|
|
196
202
|
reducers: {},
|
|
197
203
|
extraReducers: (builder) => {
|
|
198
204
|
builder.addCase(doGetDeviceCredentials.pending, (state) => {
|
|
@@ -252,6 +258,8 @@ function forwardSocketEvents(socket, dispatch) {
|
|
|
252
258
|
socket.on("cloud_recording_started", (payload) => dispatch(signalEvents.cloudRecordingStarted(payload)));
|
|
253
259
|
socket.on("cloud_recording_stopped", () => dispatch(signalEvents.cloudRecordingStopped()));
|
|
254
260
|
socket.on("streaming_stopped", () => dispatch(signalEvents.streamingStopped()));
|
|
261
|
+
socket.on("spotlight_added", (payload) => dispatch(signalEvents.spotlightAdded(payload)));
|
|
262
|
+
socket.on("spotlight_removed", (payload) => dispatch(signalEvents.spotlightRemoved(payload)));
|
|
255
263
|
}
|
|
256
264
|
const SIGNAL_BASE_URL = "wss://signal.appearin.net" ;
|
|
257
265
|
function createSocket() {
|
|
@@ -262,7 +270,7 @@ function createSocket() {
|
|
|
262
270
|
};
|
|
263
271
|
return new ServerSocket(socketHost, socketOverrides);
|
|
264
272
|
}
|
|
265
|
-
const initialState$
|
|
273
|
+
const initialState$c = {
|
|
266
274
|
deviceIdentified: false,
|
|
267
275
|
isIdentifyingDevice: false,
|
|
268
276
|
status: "ready",
|
|
@@ -270,7 +278,7 @@ const initialState$b = {
|
|
|
270
278
|
};
|
|
271
279
|
const signalConnectionSlice = createSlice({
|
|
272
280
|
name: "signalConnection",
|
|
273
|
-
initialState: initialState$
|
|
281
|
+
initialState: initialState$c,
|
|
274
282
|
reducers: {
|
|
275
283
|
socketConnecting: (state) => {
|
|
276
284
|
return Object.assign(Object.assign({}, state), { status: "connecting" });
|
|
@@ -374,12 +382,12 @@ startAppListening({
|
|
|
374
382
|
},
|
|
375
383
|
});
|
|
376
384
|
|
|
377
|
-
const initialState$
|
|
385
|
+
const initialState$b = {
|
|
378
386
|
chatMessages: [],
|
|
379
387
|
};
|
|
380
388
|
const chatSlice = createSlice({
|
|
381
389
|
name: "chat",
|
|
382
|
-
initialState: initialState$
|
|
390
|
+
initialState: initialState$b,
|
|
383
391
|
reducers: {},
|
|
384
392
|
extraReducers(builder) {
|
|
385
393
|
builder.addCase(signalEvents.chatMessage, (state, action) => {
|
|
@@ -591,9 +599,11 @@ function parseUnverifiedRoomKeyData(roomKey) {
|
|
|
591
599
|
const initialLocalMediaState = {
|
|
592
600
|
busyDeviceIds: [],
|
|
593
601
|
cameraEnabled: false,
|
|
602
|
+
currentSpeakerDeviceId: "default",
|
|
594
603
|
devices: [],
|
|
595
604
|
isSettingCameraDevice: false,
|
|
596
605
|
isSettingMicrophoneDevice: false,
|
|
606
|
+
isSettingSpeakerDevice: false,
|
|
597
607
|
isTogglingCamera: false,
|
|
598
608
|
lowDataMode: false,
|
|
599
609
|
microphoneEnabled: false,
|
|
@@ -625,6 +635,10 @@ const localMediaSlice = createSlice({
|
|
|
625
635
|
setCurrentMicrophoneDeviceId(state, action) {
|
|
626
636
|
return Object.assign(Object.assign({}, state), { currentMicrophoneDeviceId: action.payload.deviceId });
|
|
627
637
|
},
|
|
638
|
+
setCurrentSpeakerDeviceId(state, action) {
|
|
639
|
+
var _a;
|
|
640
|
+
return Object.assign(Object.assign({}, state), { currentSpeakerDeviceId: (_a = action.payload.deviceId) !== null && _a !== void 0 ? _a : "default" });
|
|
641
|
+
},
|
|
628
642
|
toggleLowDataModeEnabled(state, action) {
|
|
629
643
|
var _a;
|
|
630
644
|
return Object.assign(Object.assign({}, state), { lowDataMode: (_a = action.payload.enabled) !== null && _a !== void 0 ? _a : !state.lowDataMode });
|
|
@@ -707,7 +721,7 @@ const localMediaSlice = createSlice({
|
|
|
707
721
|
});
|
|
708
722
|
},
|
|
709
723
|
});
|
|
710
|
-
const { deviceBusy, setCurrentCameraDeviceId, setCurrentMicrophoneDeviceId, toggleCameraEnabled, toggleMicrophoneEnabled, toggleLowDataModeEnabled, setLocalMediaOptions, setLocalMediaStream, localMediaStopped, localStreamMetadataUpdated, } = localMediaSlice.actions;
|
|
724
|
+
const { deviceBusy, setCurrentCameraDeviceId, setCurrentMicrophoneDeviceId, setCurrentSpeakerDeviceId, toggleCameraEnabled, toggleMicrophoneEnabled, toggleLowDataModeEnabled, setLocalMediaOptions, setLocalMediaStream, localMediaStopped, localStreamMetadataUpdated, } = localMediaSlice.actions;
|
|
711
725
|
const doToggleCamera = createAppAsyncThunk("localMedia/doToggleCamera", (_, { getState, rejectWithValue }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
712
726
|
const state = getState();
|
|
713
727
|
const stream = selectLocalMediaStream(state);
|
|
@@ -897,6 +911,7 @@ const selectBusyDeviceIds = (state) => state.localMedia.busyDeviceIds;
|
|
|
897
911
|
const selectCameraDeviceError = (state) => state.localMedia.cameraDeviceError;
|
|
898
912
|
const selectCurrentCameraDeviceId = (state) => state.localMedia.currentCameraDeviceId;
|
|
899
913
|
const selectCurrentMicrophoneDeviceId = (state) => state.localMedia.currentMicrophoneDeviceId;
|
|
914
|
+
const selectCurrentSpeakerDeviceId = (state) => state.localMedia.currentSpeakerDeviceId;
|
|
900
915
|
const selectIsCameraEnabled = (state) => state.localMedia.cameraEnabled;
|
|
901
916
|
const selectIsMicrophoneEnabled = (state) => state.localMedia.microphoneEnabled;
|
|
902
917
|
const selectIsLowDataModeEnabled = (state) => state.localMedia.lowDataMode;
|
|
@@ -1033,7 +1048,7 @@ startAppListening({
|
|
|
1033
1048
|
},
|
|
1034
1049
|
});
|
|
1035
1050
|
|
|
1036
|
-
const initialState$
|
|
1051
|
+
const initialState$a = {
|
|
1037
1052
|
displayName: "",
|
|
1038
1053
|
id: "",
|
|
1039
1054
|
isAudioEnabled: true,
|
|
@@ -1043,34 +1058,14 @@ const initialState$9 = {
|
|
|
1043
1058
|
isScreenSharing: false,
|
|
1044
1059
|
roleName: "none",
|
|
1045
1060
|
clientClaim: undefined,
|
|
1061
|
+
stickyReaction: undefined,
|
|
1046
1062
|
};
|
|
1047
|
-
const doEnableAudio = createAppAsyncThunk("localParticipant/doEnableAudio", (payload, { getState }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1048
|
-
const state = getState();
|
|
1049
|
-
const socket = selectSignalConnectionRaw(state).socket;
|
|
1050
|
-
socket === null || socket === void 0 ? void 0 : socket.emit("enable_audio", { enabled: payload.enabled });
|
|
1051
|
-
return payload.enabled;
|
|
1052
|
-
}));
|
|
1053
|
-
const doEnableVideo = createAppAsyncThunk("localParticipant/doEnableVideo", (payload, { getState }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1054
|
-
const state = getState();
|
|
1055
|
-
const socket = selectSignalConnectionRaw(state).socket;
|
|
1056
|
-
socket === null || socket === void 0 ? void 0 : socket.emit("enable_video", { enabled: payload.enabled });
|
|
1057
|
-
return payload.enabled;
|
|
1058
|
-
}));
|
|
1059
|
-
const doSetDisplayName = createAppAsyncThunk("localParticipant/doSetDisplayName", (payload, { getState }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1060
|
-
const state = getState();
|
|
1061
|
-
const socket = selectSignalConnectionRaw(state).socket;
|
|
1062
|
-
socket === null || socket === void 0 ? void 0 : socket.emit("send_client_metadata", {
|
|
1063
|
-
type: "UserData",
|
|
1064
|
-
payload,
|
|
1065
|
-
});
|
|
1066
|
-
return payload.displayName;
|
|
1067
|
-
}));
|
|
1068
1063
|
const localParticipantSlice = createSlice({
|
|
1069
1064
|
name: "localParticipant",
|
|
1070
|
-
initialState: initialState$
|
|
1065
|
+
initialState: initialState$a,
|
|
1071
1066
|
reducers: {
|
|
1072
|
-
|
|
1073
|
-
return Object.assign(Object.assign({}, state), action.payload);
|
|
1067
|
+
doSetDisplayName: (state, action) => {
|
|
1068
|
+
return Object.assign(Object.assign({}, state), { displayName: action.payload.displayName });
|
|
1074
1069
|
},
|
|
1075
1070
|
},
|
|
1076
1071
|
extraReducers: (builder) => {
|
|
@@ -1083,8 +1078,8 @@ const localParticipantSlice = createSlice({
|
|
|
1083
1078
|
builder.addCase(doEnableVideo.fulfilled, (state, action) => {
|
|
1084
1079
|
return Object.assign(Object.assign({}, state), { isVideoEnabled: action.payload });
|
|
1085
1080
|
});
|
|
1086
|
-
builder.addCase(
|
|
1087
|
-
return Object.assign(Object.assign({}, state), {
|
|
1081
|
+
builder.addCase(doSetLocalStickyReaction.fulfilled, (state, action) => {
|
|
1082
|
+
return Object.assign(Object.assign({}, state), { stickyReaction: action.payload });
|
|
1088
1083
|
});
|
|
1089
1084
|
builder.addCase(signalEvents.roomJoined, (state, action) => {
|
|
1090
1085
|
var _a, _b;
|
|
@@ -1093,11 +1088,64 @@ const localParticipantSlice = createSlice({
|
|
|
1093
1088
|
});
|
|
1094
1089
|
},
|
|
1095
1090
|
});
|
|
1096
|
-
const {
|
|
1091
|
+
const { doSetDisplayName } = localParticipantSlice.actions;
|
|
1092
|
+
const doEnableAudio = createAppAsyncThunk("localParticipant/doEnableAudio", (payload, { dispatch, getState }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1093
|
+
const state = getState();
|
|
1094
|
+
const socket = selectSignalConnectionRaw(state).socket;
|
|
1095
|
+
socket === null || socket === void 0 ? void 0 : socket.emit("enable_audio", { enabled: payload.enabled });
|
|
1096
|
+
if (payload.enabled) {
|
|
1097
|
+
dispatch(doSetLocalStickyReaction({ enabled: false }));
|
|
1098
|
+
}
|
|
1099
|
+
return payload.enabled;
|
|
1100
|
+
}));
|
|
1101
|
+
const doEnableVideo = createAppAsyncThunk("localParticipant/doEnableVideo", (payload, { getState }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1102
|
+
const state = getState();
|
|
1103
|
+
const socket = selectSignalConnectionRaw(state).socket;
|
|
1104
|
+
socket === null || socket === void 0 ? void 0 : socket.emit("enable_video", { enabled: payload.enabled });
|
|
1105
|
+
return payload.enabled;
|
|
1106
|
+
}));
|
|
1107
|
+
const doSetLocalStickyReaction = createAppAsyncThunk("localParticipant/doSetLocalStickyReaction", (payload, { getState, rejectWithValue }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1108
|
+
var _a;
|
|
1109
|
+
const state = getState();
|
|
1110
|
+
const currentStickyReaction = selectLocalParticipantStickyReaction(state);
|
|
1111
|
+
const stickyReactionCurrentlyEnabled = Boolean(currentStickyReaction);
|
|
1112
|
+
const enabled = (_a = payload.enabled) !== null && _a !== void 0 ? _a : !stickyReactionCurrentlyEnabled;
|
|
1113
|
+
if (enabled === stickyReactionCurrentlyEnabled) {
|
|
1114
|
+
return rejectWithValue(currentStickyReaction);
|
|
1115
|
+
}
|
|
1116
|
+
const stickyReaction = enabled ? { reaction: "✋", timestamp: new Date().toISOString() } : null;
|
|
1117
|
+
return stickyReaction;
|
|
1118
|
+
}));
|
|
1119
|
+
const doSendClientMetadata = createAppThunk(() => (_, getState) => {
|
|
1120
|
+
const state = getState();
|
|
1121
|
+
const socket = selectSignalConnectionRaw(state).socket;
|
|
1122
|
+
const payload = {
|
|
1123
|
+
displayName: selectLocalParticipantDisplayName(state),
|
|
1124
|
+
stickyReaction: selectLocalParticipantStickyReaction(state),
|
|
1125
|
+
};
|
|
1126
|
+
socket === null || socket === void 0 ? void 0 : socket.emit("send_client_metadata", {
|
|
1127
|
+
type: "UserData",
|
|
1128
|
+
payload,
|
|
1129
|
+
});
|
|
1130
|
+
});
|
|
1097
1131
|
const selectLocalParticipantRaw = (state) => state.localParticipant;
|
|
1098
1132
|
const selectSelfId = (state) => state.localParticipant.id;
|
|
1133
|
+
const selectLocalParticipantDisplayName = (state) => state.localParticipant.displayName;
|
|
1099
1134
|
const selectLocalParticipantClientClaim = (state) => state.localParticipant.clientClaim;
|
|
1100
1135
|
const selectLocalParticipantIsScreenSharing = (state) => state.localParticipant.isScreenSharing;
|
|
1136
|
+
const selectLocalParticipantStickyReaction = (state) => state.localParticipant.stickyReaction;
|
|
1137
|
+
const selectLocalParticipantView = createSelector(selectLocalParticipantRaw, selectLocalMediaStream, (participant, localStream) => {
|
|
1138
|
+
const clientView = {
|
|
1139
|
+
id: participant.id,
|
|
1140
|
+
clientId: participant.id,
|
|
1141
|
+
displayName: participant.displayName,
|
|
1142
|
+
stream: localStream,
|
|
1143
|
+
isLocalClient: true,
|
|
1144
|
+
isAudioEnabled: participant.isAudioEnabled,
|
|
1145
|
+
isVideoEnabled: participant.isVideoEnabled,
|
|
1146
|
+
};
|
|
1147
|
+
return clientView;
|
|
1148
|
+
});
|
|
1101
1149
|
startAppListening({
|
|
1102
1150
|
actionCreator: toggleCameraEnabled,
|
|
1103
1151
|
effect: ({ payload }, { dispatch, getState }) => {
|
|
@@ -1114,15 +1162,18 @@ startAppListening({
|
|
|
1114
1162
|
dispatch(doEnableAudio({ enabled: enabled || !isAudioEnabled }));
|
|
1115
1163
|
},
|
|
1116
1164
|
});
|
|
1165
|
+
createReactor([selectLocalParticipantDisplayName, selectLocalParticipantStickyReaction], ({ dispatch }) => {
|
|
1166
|
+
dispatch(doSendClientMetadata());
|
|
1167
|
+
});
|
|
1117
1168
|
|
|
1118
|
-
const initialState$
|
|
1169
|
+
const initialState$9 = {
|
|
1119
1170
|
status: "inactive",
|
|
1120
1171
|
stream: null,
|
|
1121
1172
|
error: null,
|
|
1122
1173
|
};
|
|
1123
1174
|
const localScreenshareSlice = createSlice({
|
|
1124
1175
|
name: "localScreenshare",
|
|
1125
|
-
initialState: initialState$
|
|
1176
|
+
initialState: initialState$9,
|
|
1126
1177
|
reducers: {
|
|
1127
1178
|
stopScreenshare(state, action) {
|
|
1128
1179
|
return Object.assign(Object.assign({}, state), { status: "inactive", stream: null });
|
|
@@ -1191,60 +1242,6 @@ startAppListening({
|
|
|
1191
1242
|
},
|
|
1192
1243
|
});
|
|
1193
1244
|
|
|
1194
|
-
const initialState$7 = {
|
|
1195
|
-
data: null,
|
|
1196
|
-
isFetching: false,
|
|
1197
|
-
error: null,
|
|
1198
|
-
};
|
|
1199
|
-
const organizationSlice = createSlice({
|
|
1200
|
-
initialState: initialState$7,
|
|
1201
|
-
name: "organization",
|
|
1202
|
-
reducers: {},
|
|
1203
|
-
extraReducers: (builder) => {
|
|
1204
|
-
builder.addCase(doOrganizationFetch.pending, (state) => {
|
|
1205
|
-
return Object.assign(Object.assign({}, state), { isFetching: true });
|
|
1206
|
-
});
|
|
1207
|
-
builder.addCase(doOrganizationFetch.fulfilled, (state, action) => {
|
|
1208
|
-
if (!action.payload)
|
|
1209
|
-
return Object.assign(Object.assign({}, state), { isFetching: true });
|
|
1210
|
-
return Object.assign(Object.assign({}, state), { isFetching: false, data: action.payload });
|
|
1211
|
-
});
|
|
1212
|
-
builder.addCase(doOrganizationFetch.rejected, (state) => {
|
|
1213
|
-
return Object.assign(Object.assign({}, state), { isFetching: false, error: true });
|
|
1214
|
-
});
|
|
1215
|
-
},
|
|
1216
|
-
});
|
|
1217
|
-
const doOrganizationFetch = createAppAsyncThunk("organization/doOrganizationFetch", (_, { extra, getState }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1218
|
-
try {
|
|
1219
|
-
const roomUrl = selectAppRoomUrl(getState());
|
|
1220
|
-
const organization = yield extra.services.fetchOrganizationFromRoomUrl(roomUrl || "");
|
|
1221
|
-
if (!organization) {
|
|
1222
|
-
throw new Error("Invalid room url");
|
|
1223
|
-
}
|
|
1224
|
-
return organization;
|
|
1225
|
-
}
|
|
1226
|
-
catch (error) {
|
|
1227
|
-
console.error(error);
|
|
1228
|
-
}
|
|
1229
|
-
}));
|
|
1230
|
-
const selectOrganizationRaw = (state) => state.organization;
|
|
1231
|
-
const selectOrganizationId = (state) => { var _a; return (_a = state.organization.data) === null || _a === void 0 ? void 0 : _a.organizationId; };
|
|
1232
|
-
const selectShouldFetchOrganization = createSelector(selectAppIsActive, selectOrganizationRaw, selectDeviceCredentialsRaw, (appIsActive, organization, deviceCredentials) => {
|
|
1233
|
-
if (appIsActive &&
|
|
1234
|
-
!organization.data &&
|
|
1235
|
-
!organization.isFetching &&
|
|
1236
|
-
!organization.error &&
|
|
1237
|
-
!deviceCredentials.isFetching) {
|
|
1238
|
-
return true;
|
|
1239
|
-
}
|
|
1240
|
-
return false;
|
|
1241
|
-
});
|
|
1242
|
-
createReactor([selectShouldFetchOrganization], ({ dispatch }, shouldFetchOrganization) => {
|
|
1243
|
-
if (shouldFetchOrganization) {
|
|
1244
|
-
dispatch(doOrganizationFetch());
|
|
1245
|
-
}
|
|
1246
|
-
});
|
|
1247
|
-
|
|
1248
1245
|
function createRtcEventAction(name) {
|
|
1249
1246
|
return createAction(`rtcConnection/event/${name}`);
|
|
1250
1247
|
}
|
|
@@ -1346,12 +1343,12 @@ function addStream(state, payload) {
|
|
|
1346
1343
|
presentationStream: stream,
|
|
1347
1344
|
});
|
|
1348
1345
|
}
|
|
1349
|
-
const initialState$
|
|
1346
|
+
const initialState$8 = {
|
|
1350
1347
|
remoteParticipants: [],
|
|
1351
1348
|
};
|
|
1352
1349
|
const remoteParticipantsSlice = createSlice({
|
|
1353
1350
|
name: "remoteParticipants",
|
|
1354
|
-
initialState: initialState$
|
|
1351
|
+
initialState: initialState$8,
|
|
1355
1352
|
reducers: {
|
|
1356
1353
|
streamStatusUpdated: (state, action) => {
|
|
1357
1354
|
let newState = state;
|
|
@@ -1410,9 +1407,15 @@ const remoteParticipantsSlice = createSlice({
|
|
|
1410
1407
|
});
|
|
1411
1408
|
});
|
|
1412
1409
|
builder.addCase(signalEvents.clientMetadataReceived, (state, action) => {
|
|
1413
|
-
const {
|
|
1410
|
+
const { error, payload } = action.payload;
|
|
1411
|
+
if (error || !payload) {
|
|
1412
|
+
console.warn(error || "Client metadata error received");
|
|
1413
|
+
return state;
|
|
1414
|
+
}
|
|
1415
|
+
const { clientId, displayName, stickyReaction } = payload;
|
|
1414
1416
|
return updateParticipant(state, clientId, {
|
|
1415
1417
|
displayName,
|
|
1418
|
+
stickyReaction,
|
|
1416
1419
|
});
|
|
1417
1420
|
});
|
|
1418
1421
|
builder.addCase(signalEvents.screenshareStarted, (state, action) => {
|
|
@@ -1428,87 +1431,79 @@ const remoteParticipantsSlice = createSlice({
|
|
|
1428
1431
|
const { participantStreamAdded, participantStreamIdAdded, streamStatusUpdated } = remoteParticipantsSlice.actions;
|
|
1429
1432
|
const doRequestAudioEnable = createAppAuthorizedThunk((state) => selectIsAuthorizedToRequestAudioEnable(state), (payload) => (_, getState) => {
|
|
1430
1433
|
const state = getState();
|
|
1434
|
+
const canEnableRemoteAudio = selectIsAuthorizedToAskToSpeak(state);
|
|
1435
|
+
if (payload.enable && !canEnableRemoteAudio) {
|
|
1436
|
+
console.warn("Not authorized to perform this action");
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1431
1439
|
const socket = selectSignalConnectionRaw(state).socket;
|
|
1432
1440
|
socket === null || socket === void 0 ? void 0 : socket.emit("request_audio_enable", payload);
|
|
1433
1441
|
});
|
|
1434
1442
|
const selectRemoteParticipantsRaw = (state) => state.remoteParticipants;
|
|
1435
1443
|
const selectRemoteParticipants = (state) => state.remoteParticipants.remoteParticipants;
|
|
1436
|
-
const
|
|
1437
|
-
const screenshares = [];
|
|
1438
|
-
if (localScreenshareStream) {
|
|
1439
|
-
screenshares.push({
|
|
1440
|
-
id: localScreenshareStream.id || "local-screenshare",
|
|
1441
|
-
participantId: "local",
|
|
1442
|
-
hasAudioTrack: localScreenshareStream.getTracks().some((track) => track.kind === "audio"),
|
|
1443
|
-
stream: localScreenshareStream,
|
|
1444
|
-
isLocal: true,
|
|
1445
|
-
});
|
|
1446
|
-
}
|
|
1447
|
-
for (const participant of remoteParticipants) {
|
|
1448
|
-
if (participant.presentationStream) {
|
|
1449
|
-
screenshares.push({
|
|
1450
|
-
id: participant.presentationStream.id || `pres-${participant.id}`,
|
|
1451
|
-
participantId: participant.id,
|
|
1452
|
-
hasAudioTrack: participant.presentationStream.getTracks().some((track) => track.kind === "audio"),
|
|
1453
|
-
stream: participant.presentationStream,
|
|
1454
|
-
isLocal: false,
|
|
1455
|
-
});
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
return screenshares;
|
|
1459
|
-
});
|
|
1444
|
+
const selectNumParticipants = createSelector(selectRemoteParticipants, (clients) => clients.filter((c) => !NON_PERSON_ROLES.includes(c.roleName)).length + 1);
|
|
1460
1445
|
|
|
1461
|
-
const initialState$
|
|
1462
|
-
|
|
1446
|
+
const initialState$7 = {
|
|
1447
|
+
data: null,
|
|
1448
|
+
isFetching: false,
|
|
1449
|
+
error: null,
|
|
1463
1450
|
};
|
|
1464
|
-
const
|
|
1465
|
-
|
|
1466
|
-
|
|
1451
|
+
const organizationSlice = createSlice({
|
|
1452
|
+
initialState: initialState$7,
|
|
1453
|
+
name: "organization",
|
|
1467
1454
|
reducers: {},
|
|
1468
1455
|
extraReducers: (builder) => {
|
|
1469
|
-
builder.addCase(
|
|
1470
|
-
|
|
1471
|
-
if (error) {
|
|
1472
|
-
return state;
|
|
1473
|
-
}
|
|
1474
|
-
return Object.assign(Object.assign({}, state), { isLocked: Boolean(isLocked) });
|
|
1456
|
+
builder.addCase(doOrganizationFetch.pending, (state) => {
|
|
1457
|
+
return Object.assign(Object.assign({}, state), { isFetching: true });
|
|
1475
1458
|
});
|
|
1476
|
-
builder.addCase(
|
|
1477
|
-
|
|
1478
|
-
|
|
1459
|
+
builder.addCase(doOrganizationFetch.fulfilled, (state, action) => {
|
|
1460
|
+
if (!action.payload)
|
|
1461
|
+
return Object.assign(Object.assign({}, state), { isFetching: true });
|
|
1462
|
+
return Object.assign(Object.assign({}, state), { isFetching: false, data: action.payload });
|
|
1463
|
+
});
|
|
1464
|
+
builder.addCase(doOrganizationFetch.rejected, (state) => {
|
|
1465
|
+
return Object.assign(Object.assign({}, state), { isFetching: false, error: true });
|
|
1479
1466
|
});
|
|
1480
1467
|
},
|
|
1481
1468
|
});
|
|
1482
|
-
const
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
socket === null || socket === void 0 ? void 0 : socket.emit("kick_client", { clientId: payload.clientId, reasonId: "kick" });
|
|
1491
|
-
});
|
|
1492
|
-
const doEndMeeting = createAppAuthorizedThunk((state) => selectIsAuthorizedToEndMeeting(state), (payload) => (dispatch, getState) => {
|
|
1493
|
-
const state = getState();
|
|
1494
|
-
const clientsToKick = selectRemoteParticipants(state).map((c) => c.id);
|
|
1495
|
-
if (clientsToKick.length) {
|
|
1496
|
-
const { socket } = selectSignalConnectionRaw(state);
|
|
1497
|
-
socket === null || socket === void 0 ? void 0 : socket.emit("kick_client", { clientIds: clientsToKick, reasonId: "end-meeting" });
|
|
1469
|
+
const doOrganizationFetch = createAppAsyncThunk("organization/doOrganizationFetch", (_, { extra, getState }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1470
|
+
try {
|
|
1471
|
+
const roomUrl = selectAppRoomUrl(getState());
|
|
1472
|
+
const organization = yield extra.services.fetchOrganizationFromRoomUrl(roomUrl || "");
|
|
1473
|
+
if (!organization) {
|
|
1474
|
+
throw new Error("Invalid room url");
|
|
1475
|
+
}
|
|
1476
|
+
return organization;
|
|
1498
1477
|
}
|
|
1499
|
-
|
|
1500
|
-
|
|
1478
|
+
catch (error) {
|
|
1479
|
+
console.error(error);
|
|
1480
|
+
}
|
|
1481
|
+
}));
|
|
1482
|
+
const selectOrganizationRaw = (state) => state.organization;
|
|
1483
|
+
const selectOrganizationId = (state) => { var _a; return (_a = state.organization.data) === null || _a === void 0 ? void 0 : _a.organizationId; };
|
|
1484
|
+
const selectShouldFetchOrganization = createSelector(selectAppIsActive, selectOrganizationRaw, selectDeviceCredentialsRaw, (appIsActive, organization, deviceCredentials) => {
|
|
1485
|
+
if (appIsActive &&
|
|
1486
|
+
!organization.data &&
|
|
1487
|
+
!organization.isFetching &&
|
|
1488
|
+
!organization.error &&
|
|
1489
|
+
!deviceCredentials.isFetching) {
|
|
1490
|
+
return true;
|
|
1491
|
+
}
|
|
1492
|
+
return false;
|
|
1493
|
+
});
|
|
1494
|
+
createReactor([selectShouldFetchOrganization], ({ dispatch }, shouldFetchOrganization) => {
|
|
1495
|
+
if (shouldFetchOrganization) {
|
|
1496
|
+
dispatch(doOrganizationFetch());
|
|
1501
1497
|
}
|
|
1502
1498
|
});
|
|
1503
|
-
const selectRoomIsLocked = (state) => state.room.isLocked;
|
|
1504
1499
|
|
|
1505
|
-
const initialState$
|
|
1500
|
+
const initialState$6 = {
|
|
1506
1501
|
session: null,
|
|
1507
1502
|
status: "ready",
|
|
1508
1503
|
error: null,
|
|
1509
1504
|
};
|
|
1510
1505
|
const roomConnectionSlice = createSlice({
|
|
1511
|
-
initialState: initialState$
|
|
1506
|
+
initialState: initialState$6,
|
|
1512
1507
|
name: "roomConnection",
|
|
1513
1508
|
reducers: {
|
|
1514
1509
|
connectionStatusChanged: (state, action) => {
|
|
@@ -1667,6 +1662,249 @@ startAppListening({
|
|
|
1667
1662
|
},
|
|
1668
1663
|
});
|
|
1669
1664
|
|
|
1665
|
+
const emitter = new EventEmitter();
|
|
1666
|
+
function createNotificationEvent(payload) {
|
|
1667
|
+
const notificationEvent = Object.assign(Object.assign({}, payload), { timestamp: Date.now() });
|
|
1668
|
+
return notificationEvent;
|
|
1669
|
+
}
|
|
1670
|
+
const initialNotificationsState = {
|
|
1671
|
+
emitter,
|
|
1672
|
+
events: [],
|
|
1673
|
+
};
|
|
1674
|
+
const notificationsSlice = createSlice({
|
|
1675
|
+
name: "notifications",
|
|
1676
|
+
initialState: initialNotificationsState,
|
|
1677
|
+
reducers: {
|
|
1678
|
+
addNotification: (state, action) => {
|
|
1679
|
+
return Object.assign(Object.assign({}, state), { events: [...state.events, Object.assign({}, action.payload)] });
|
|
1680
|
+
},
|
|
1681
|
+
doClearNotifications: (state) => {
|
|
1682
|
+
return Object.assign(Object.assign({}, state), { events: [] });
|
|
1683
|
+
},
|
|
1684
|
+
},
|
|
1685
|
+
});
|
|
1686
|
+
const { doClearNotifications } = notificationsSlice.actions;
|
|
1687
|
+
const doSetNotification = createAppThunk((payload) => (dispatch, getState) => {
|
|
1688
|
+
dispatch(notificationsSlice.actions.addNotification(payload));
|
|
1689
|
+
const state = getState();
|
|
1690
|
+
const emitter = selectNotificationsEmitter(state);
|
|
1691
|
+
emitter.emit(payload.type, payload);
|
|
1692
|
+
emitter.emit("*", payload);
|
|
1693
|
+
});
|
|
1694
|
+
const selectNotificationsRaw = (state) => state.notifications;
|
|
1695
|
+
const selectNotificationsEvents = (state) => state.notifications.events;
|
|
1696
|
+
const selectNotificationsEmitter = (state) => state.notifications.emitter;
|
|
1697
|
+
startAppListening({
|
|
1698
|
+
actionCreator: signalEvents.chatMessage,
|
|
1699
|
+
effect: ({ payload }, { dispatch, getState }) => {
|
|
1700
|
+
const state = getState();
|
|
1701
|
+
const client = selectRemoteParticipants(state).find(({ id }) => id === payload.senderId);
|
|
1702
|
+
if (!client) {
|
|
1703
|
+
console.warn("Could not find remote client that sent chat message");
|
|
1704
|
+
return;
|
|
1705
|
+
}
|
|
1706
|
+
dispatch(doSetNotification(createNotificationEvent({
|
|
1707
|
+
type: "chatMessageReceived",
|
|
1708
|
+
message: `${client.displayName} says: ${payload.text}`,
|
|
1709
|
+
props: {
|
|
1710
|
+
client,
|
|
1711
|
+
chatMessage: {
|
|
1712
|
+
senderId: payload.senderId,
|
|
1713
|
+
timestamp: payload.timestamp,
|
|
1714
|
+
text: payload.text,
|
|
1715
|
+
},
|
|
1716
|
+
},
|
|
1717
|
+
})));
|
|
1718
|
+
},
|
|
1719
|
+
});
|
|
1720
|
+
startAppListening({
|
|
1721
|
+
actionCreator: signalEvents.audioEnableRequested,
|
|
1722
|
+
effect: ({ payload }, { dispatch, getState }) => {
|
|
1723
|
+
const { enable, requestedByClientId } = payload;
|
|
1724
|
+
const state = getState();
|
|
1725
|
+
const client = selectRemoteParticipants(state).find(({ id }) => id === requestedByClientId);
|
|
1726
|
+
if (!client) {
|
|
1727
|
+
console.warn("Could not find remote client that requested a local audio change");
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1730
|
+
dispatch(doSetNotification(createNotificationEvent({
|
|
1731
|
+
type: enable ? "requestAudioEnable" : "requestAudioDisable",
|
|
1732
|
+
message: enable
|
|
1733
|
+
? `${client.displayName} has requested for you to speak`
|
|
1734
|
+
: `${client.displayName} has muted your microphone`,
|
|
1735
|
+
props: {
|
|
1736
|
+
client,
|
|
1737
|
+
enable,
|
|
1738
|
+
},
|
|
1739
|
+
})));
|
|
1740
|
+
},
|
|
1741
|
+
});
|
|
1742
|
+
startAppListening({
|
|
1743
|
+
actionCreator: signalEvents.clientMetadataReceived,
|
|
1744
|
+
effect: (action, { dispatch, getOriginalState, getState }) => {
|
|
1745
|
+
var _a;
|
|
1746
|
+
const { error, payload } = action.payload;
|
|
1747
|
+
if (error || !payload) {
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
const { clientId, stickyReaction } = payload;
|
|
1751
|
+
const state = getState();
|
|
1752
|
+
const canAskToSpeak = selectIsAuthorizedToAskToSpeak(state);
|
|
1753
|
+
if (!canAskToSpeak) {
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
const client = selectRemoteParticipants(state).find(({ id }) => id === clientId);
|
|
1757
|
+
if (!client) {
|
|
1758
|
+
console.warn("Could not find remote client that provided updated metadata");
|
|
1759
|
+
return;
|
|
1760
|
+
}
|
|
1761
|
+
const previousState = getOriginalState();
|
|
1762
|
+
const previousClient = selectRemoteParticipants(previousState).find(({ id }) => id === clientId);
|
|
1763
|
+
if ((!stickyReaction && !(previousClient === null || previousClient === void 0 ? void 0 : previousClient.stickyReaction)) ||
|
|
1764
|
+
(stickyReaction === null || stickyReaction === void 0 ? void 0 : stickyReaction.timestamp) === ((_a = previousClient === null || previousClient === void 0 ? void 0 : previousClient.stickyReaction) === null || _a === void 0 ? void 0 : _a.timestamp)) {
|
|
1765
|
+
return;
|
|
1766
|
+
}
|
|
1767
|
+
dispatch(doSetNotification(createNotificationEvent({
|
|
1768
|
+
type: stickyReaction ? "remoteHandRaised" : "remoteHandLowered",
|
|
1769
|
+
message: `${client.displayName} ${stickyReaction ? "raised" : "lowered"} their hand`,
|
|
1770
|
+
props: {
|
|
1771
|
+
client,
|
|
1772
|
+
stickyReaction,
|
|
1773
|
+
},
|
|
1774
|
+
})));
|
|
1775
|
+
},
|
|
1776
|
+
});
|
|
1777
|
+
createReactor([selectSignalStatus], ({ dispatch, getState }, signalStatus) => {
|
|
1778
|
+
const state = getState();
|
|
1779
|
+
const roomConnectionStatus = selectRoomConnectionStatus(state);
|
|
1780
|
+
if (["left", "kicked"].includes(roomConnectionStatus)) {
|
|
1781
|
+
return;
|
|
1782
|
+
}
|
|
1783
|
+
if (signalStatus === "disconnected") {
|
|
1784
|
+
dispatch(doSetNotification(createNotificationEvent({
|
|
1785
|
+
type: "signalTrouble",
|
|
1786
|
+
message: `Network connection lost. Trying to reconnect you...`,
|
|
1787
|
+
props: {},
|
|
1788
|
+
})));
|
|
1789
|
+
}
|
|
1790
|
+
else if (signalStatus === "connected") {
|
|
1791
|
+
dispatch(doSetNotification(createNotificationEvent({
|
|
1792
|
+
type: "signalOk",
|
|
1793
|
+
message: `Network connection available`,
|
|
1794
|
+
props: {},
|
|
1795
|
+
})));
|
|
1796
|
+
}
|
|
1797
|
+
});
|
|
1798
|
+
|
|
1799
|
+
function isStreamerClient(client) {
|
|
1800
|
+
return client.roleName === "streamer";
|
|
1801
|
+
}
|
|
1802
|
+
function isRecorderClient(client) {
|
|
1803
|
+
return client.roleName === "recorder";
|
|
1804
|
+
}
|
|
1805
|
+
const initialState$5 = {
|
|
1806
|
+
isLocked: false,
|
|
1807
|
+
};
|
|
1808
|
+
const roomSlice = createSlice({
|
|
1809
|
+
name: "room",
|
|
1810
|
+
initialState: initialState$5,
|
|
1811
|
+
reducers: {},
|
|
1812
|
+
extraReducers: (builder) => {
|
|
1813
|
+
builder.addCase(signalEvents.roomJoined, (state, action) => {
|
|
1814
|
+
const { error, isLocked } = action.payload;
|
|
1815
|
+
if (error) {
|
|
1816
|
+
return state;
|
|
1817
|
+
}
|
|
1818
|
+
return Object.assign(Object.assign({}, state), { isLocked: Boolean(isLocked) });
|
|
1819
|
+
});
|
|
1820
|
+
builder.addCase(signalEvents.roomLocked, (state, action) => {
|
|
1821
|
+
const { isLocked } = action.payload;
|
|
1822
|
+
return Object.assign(Object.assign({}, state), { isLocked: Boolean(isLocked) });
|
|
1823
|
+
});
|
|
1824
|
+
},
|
|
1825
|
+
});
|
|
1826
|
+
const doLockRoom = createAppAuthorizedThunk((state) => selectIsAuthorizedToLockRoom(state), (payload) => (_, getState) => {
|
|
1827
|
+
const state = getState();
|
|
1828
|
+
const { socket } = selectSignalConnectionRaw(state);
|
|
1829
|
+
socket === null || socket === void 0 ? void 0 : socket.emit("set_lock", { locked: payload.locked });
|
|
1830
|
+
});
|
|
1831
|
+
const doKickParticipant = createAppAuthorizedThunk((state) => selectIsAuthorizedToKickClient(state), (payload) => (_, getState) => {
|
|
1832
|
+
const state = getState();
|
|
1833
|
+
const { socket } = selectSignalConnectionRaw(state);
|
|
1834
|
+
socket === null || socket === void 0 ? void 0 : socket.emit("kick_client", { clientId: payload.clientId, reasonId: "kick" });
|
|
1835
|
+
});
|
|
1836
|
+
const doEndMeeting = createAppAuthorizedThunk((state) => selectIsAuthorizedToEndMeeting(state), (payload) => (dispatch, getState) => {
|
|
1837
|
+
const state = getState();
|
|
1838
|
+
const clientsToKick = selectRemoteParticipants(state).map((c) => c.id);
|
|
1839
|
+
if (clientsToKick.length) {
|
|
1840
|
+
const { socket } = selectSignalConnectionRaw(state);
|
|
1841
|
+
socket === null || socket === void 0 ? void 0 : socket.emit("kick_client", { clientIds: clientsToKick, reasonId: "end-meeting" });
|
|
1842
|
+
}
|
|
1843
|
+
if (!payload.stayBehind) {
|
|
1844
|
+
dispatch(doAppStop());
|
|
1845
|
+
}
|
|
1846
|
+
});
|
|
1847
|
+
const selectRoomIsLocked = (state) => state.room.isLocked;
|
|
1848
|
+
const selectScreenshares = createSelector(selectLocalScreenshareStream, selectRemoteParticipants, (localScreenshareStream, remoteParticipants) => {
|
|
1849
|
+
const screenshares = [];
|
|
1850
|
+
if (localScreenshareStream) {
|
|
1851
|
+
screenshares.push({
|
|
1852
|
+
id: localScreenshareStream.id || "local-screenshare",
|
|
1853
|
+
participantId: "local",
|
|
1854
|
+
hasAudioTrack: localScreenshareStream.getTracks().some((track) => track.kind === "audio"),
|
|
1855
|
+
stream: localScreenshareStream,
|
|
1856
|
+
isLocal: true,
|
|
1857
|
+
});
|
|
1858
|
+
}
|
|
1859
|
+
for (const participant of remoteParticipants) {
|
|
1860
|
+
if (participant.presentationStream) {
|
|
1861
|
+
screenshares.push({
|
|
1862
|
+
id: participant.presentationStream.id || `pres-${participant.id}`,
|
|
1863
|
+
participantId: participant.id,
|
|
1864
|
+
hasAudioTrack: participant.presentationStream.getTracks().some((track) => track.kind === "audio"),
|
|
1865
|
+
stream: participant.presentationStream,
|
|
1866
|
+
isLocal: false,
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
return screenshares;
|
|
1871
|
+
});
|
|
1872
|
+
const selectRemoteClientViews = createSelector(selectLocalScreenshareStream, selectLocalParticipantRaw, selectRemoteParticipants, (localScreenshareStream, localParticipant, remoteParticipants) => {
|
|
1873
|
+
const views = [];
|
|
1874
|
+
if (localScreenshareStream) {
|
|
1875
|
+
const isScreenshareAudioEnabled = !!localScreenshareStream.getAudioTracks().length;
|
|
1876
|
+
views.push({
|
|
1877
|
+
clientId: localParticipant.id,
|
|
1878
|
+
displayName: "Your screenshare",
|
|
1879
|
+
id: "local-screenshare",
|
|
1880
|
+
isAudioEnabled: isScreenshareAudioEnabled,
|
|
1881
|
+
isLocalClient: true,
|
|
1882
|
+
isPresentation: true,
|
|
1883
|
+
isVideoEnabled: true,
|
|
1884
|
+
stream: localScreenshareStream,
|
|
1885
|
+
});
|
|
1886
|
+
}
|
|
1887
|
+
for (const c of remoteParticipants) {
|
|
1888
|
+
if (isStreamerClient(c) || isRecorderClient(c)) {
|
|
1889
|
+
continue;
|
|
1890
|
+
}
|
|
1891
|
+
const { presentationStream } = c, clientView = __rest(c, ["presentationStream"]);
|
|
1892
|
+
const displayName = c.displayName || "Guest";
|
|
1893
|
+
const isPresentationActive = presentationStream && presentationStream.active;
|
|
1894
|
+
const presentationId = "pres-" + c.id;
|
|
1895
|
+
const isStreamActive = c.stream && c.stream.active;
|
|
1896
|
+
const isVideoEnabled = c.isVideoEnabled;
|
|
1897
|
+
views.push(Object.assign(Object.assign(Object.assign({}, clientView), { clientId: c.id, displayName, hasActivePresentation: !!isPresentationActive }), (c.isVideoEnabled ? { isVideoEnabled } : {})));
|
|
1898
|
+
if (isPresentationActive) {
|
|
1899
|
+
views.push(Object.assign(Object.assign(Object.assign({}, clientView), { clientId: c.id, stream: c.presentationStream, displayName: `Screenshare (${displayName})`, id: presentationId, isPresentation: true, isVideoEnabled: true }), (isStreamActive && { isRecording: null })));
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
return views;
|
|
1903
|
+
});
|
|
1904
|
+
const selectAllClientViews = createSelector(selectLocalParticipantView, selectRemoteClientViews, (localParticipant, remoteParticipants) => {
|
|
1905
|
+
return [localParticipant, ...remoteParticipants];
|
|
1906
|
+
});
|
|
1907
|
+
|
|
1670
1908
|
const createWebRtcEmitter = (dispatch) => {
|
|
1671
1909
|
return {
|
|
1672
1910
|
emit: (eventName, data) => {
|
|
@@ -1683,7 +1921,7 @@ const createWebRtcEmitter = (dispatch) => {
|
|
|
1683
1921
|
},
|
|
1684
1922
|
};
|
|
1685
1923
|
};
|
|
1686
|
-
const initialState$
|
|
1924
|
+
const initialState$4 = {
|
|
1687
1925
|
dispatcherCreated: false,
|
|
1688
1926
|
error: null,
|
|
1689
1927
|
isCreatingDispatcher: false,
|
|
@@ -1696,7 +1934,7 @@ const initialState$3 = {
|
|
|
1696
1934
|
};
|
|
1697
1935
|
const rtcConnectionSlice = createSlice({
|
|
1698
1936
|
name: "rtcConnection",
|
|
1699
|
-
initialState: initialState$
|
|
1937
|
+
initialState: initialState$4,
|
|
1700
1938
|
reducers: {
|
|
1701
1939
|
isAcceptingStreams: (state, action) => {
|
|
1702
1940
|
return Object.assign(Object.assign({}, state), { isAcceptingStreams: action.payload });
|
|
@@ -1706,7 +1944,7 @@ const rtcConnectionSlice = createSlice({
|
|
|
1706
1944
|
return Object.assign(Object.assign({}, state), { reportedStreamResolutions: Object.assign(Object.assign({}, state.reportedStreamResolutions), { [streamId]: { width, height } }) });
|
|
1707
1945
|
},
|
|
1708
1946
|
rtcDisconnected: () => {
|
|
1709
|
-
return Object.assign({}, initialState$
|
|
1947
|
+
return Object.assign({}, initialState$4);
|
|
1710
1948
|
},
|
|
1711
1949
|
rtcDispatcherCreated: (state, action) => {
|
|
1712
1950
|
return Object.assign(Object.assign({}, state), { dispatcherCreated: true, rtcManagerDispatcher: action.payload });
|
|
@@ -2004,7 +2242,7 @@ const rtcAnalyticsCustomEvents = {
|
|
|
2004
2242
|
getOutput: () => ({}),
|
|
2005
2243
|
},
|
|
2006
2244
|
displayName: {
|
|
2007
|
-
actions: [doSetDisplayName
|
|
2245
|
+
actions: [doSetDisplayName],
|
|
2008
2246
|
rtcEventName: "displayName",
|
|
2009
2247
|
getValue: (state) => selectAppDisplayName(state),
|
|
2010
2248
|
getOutput: (value) => ({ displayName: value }),
|
|
@@ -2071,11 +2309,11 @@ const makeComparable = (value) => {
|
|
|
2071
2309
|
return JSON.stringify(value);
|
|
2072
2310
|
return value;
|
|
2073
2311
|
};
|
|
2074
|
-
const initialState$
|
|
2312
|
+
const initialState$3 = {
|
|
2075
2313
|
reportedValues: {},
|
|
2076
2314
|
};
|
|
2077
2315
|
const rtcAnalyticsSlice = createSlice({
|
|
2078
|
-
initialState: initialState$
|
|
2316
|
+
initialState: initialState$3,
|
|
2079
2317
|
name: "rtcAnalytics",
|
|
2080
2318
|
reducers: {
|
|
2081
2319
|
updateReportedValues(state, action) {
|
|
@@ -2135,6 +2373,92 @@ createReactor([selectRtcManagerInitialized], ({ dispatch }, selectRtcManagerInit
|
|
|
2135
2373
|
}
|
|
2136
2374
|
});
|
|
2137
2375
|
|
|
2376
|
+
function streamIdForClient({ isPresentation, stream }) {
|
|
2377
|
+
var _a, _b;
|
|
2378
|
+
return isPresentation ? (_b = (_a = stream === null || stream === void 0 ? void 0 : stream.outboundId) !== null && _a !== void 0 ? _a : stream === null || stream === void 0 ? void 0 : stream.inboundId) !== null && _b !== void 0 ? _b : stream === null || stream === void 0 ? void 0 : stream.id : "0";
|
|
2379
|
+
}
|
|
2380
|
+
function isClientSpotlighted({ spotlights, isPresentation, clientId, stream, }) {
|
|
2381
|
+
return !!spotlights.find((s) => {
|
|
2382
|
+
const streamId = streamIdForClient({ isPresentation, stream });
|
|
2383
|
+
return s.clientId === clientId && s.streamId === streamId;
|
|
2384
|
+
});
|
|
2385
|
+
}
|
|
2386
|
+
function mergeSpotlight(spotlights, spotlight) {
|
|
2387
|
+
const found = spotlights.find((s) => s.clientId === spotlight.clientId && s.streamId === spotlight.streamId);
|
|
2388
|
+
if (found) {
|
|
2389
|
+
return spotlights;
|
|
2390
|
+
}
|
|
2391
|
+
return spotlights.concat(spotlight);
|
|
2392
|
+
}
|
|
2393
|
+
function mapSpotlightsToClientViews(spotlights, clientViews) {
|
|
2394
|
+
return spotlights.reduce((acc, s) => {
|
|
2395
|
+
const clientView = clientViews.find((c) => s.clientId === c.clientId && s.streamId === streamIdForClient(c));
|
|
2396
|
+
if (clientView && !acc.includes(clientView)) {
|
|
2397
|
+
acc.push(clientView);
|
|
2398
|
+
}
|
|
2399
|
+
return acc;
|
|
2400
|
+
}, []);
|
|
2401
|
+
}
|
|
2402
|
+
const initialState$2 = {
|
|
2403
|
+
sorted: [],
|
|
2404
|
+
};
|
|
2405
|
+
const spotlightsSlice = createSlice({
|
|
2406
|
+
name: "spotlights",
|
|
2407
|
+
initialState: initialState$2,
|
|
2408
|
+
reducers: {},
|
|
2409
|
+
extraReducers: (builder) => {
|
|
2410
|
+
builder.addCase(signalEvents.roomJoined, (state, action) => {
|
|
2411
|
+
if (!action.payload.room) {
|
|
2412
|
+
return state;
|
|
2413
|
+
}
|
|
2414
|
+
const { spotlights } = action.payload.room;
|
|
2415
|
+
return Object.assign(Object.assign({}, state), { sorted: spotlights });
|
|
2416
|
+
});
|
|
2417
|
+
builder.addCase(signalEvents.spotlightAdded, (state, action) => {
|
|
2418
|
+
const { clientId, streamId } = action.payload;
|
|
2419
|
+
return Object.assign(Object.assign({}, state), { sorted: mergeSpotlight(state.sorted, { clientId, streamId }) });
|
|
2420
|
+
});
|
|
2421
|
+
builder.addCase(signalEvents.spotlightRemoved, (state, action) => {
|
|
2422
|
+
const { clientId, streamId } = action.payload;
|
|
2423
|
+
return Object.assign(Object.assign({}, state), { sorted: state.sorted.filter((s) => !(s.clientId === clientId && s.streamId === streamId)) });
|
|
2424
|
+
});
|
|
2425
|
+
builder.addMatcher(isAnyOf(signalEvents.clientKicked, signalEvents.clientLeft), (state, action) => {
|
|
2426
|
+
const { clientId } = action.payload;
|
|
2427
|
+
return Object.assign(Object.assign({}, state), { sorted: state.sorted.filter((s) => s.clientId !== clientId) });
|
|
2428
|
+
});
|
|
2429
|
+
},
|
|
2430
|
+
});
|
|
2431
|
+
const doSpotlightParticipant = createAppAuthorizedThunk((state) => selectIsAuthorizedToSpotlight(state), ({ id }) => (_, getState) => {
|
|
2432
|
+
const state = getState();
|
|
2433
|
+
const clientView = selectAllClientViews(state).find((c) => c.clientId === id);
|
|
2434
|
+
if (!clientView) {
|
|
2435
|
+
return;
|
|
2436
|
+
}
|
|
2437
|
+
const { socket } = selectSignalConnectionRaw(state);
|
|
2438
|
+
const streamId = streamIdForClient(clientView);
|
|
2439
|
+
const payload = { clientId: clientView.id, streamId: streamId !== null && streamId !== void 0 ? streamId : "0" };
|
|
2440
|
+
socket === null || socket === void 0 ? void 0 : socket.emit("add_spotlight", payload);
|
|
2441
|
+
});
|
|
2442
|
+
const doRemoveSpotlight = createAppAuthorizedThunk((state) => selectIsAuthorizedToSpotlight(state), ({ id }) => (_, getState) => {
|
|
2443
|
+
const state = getState();
|
|
2444
|
+
const clientView = selectAllClientViews(state).find((c) => c.clientId === id);
|
|
2445
|
+
if (!clientView) {
|
|
2446
|
+
return;
|
|
2447
|
+
}
|
|
2448
|
+
const { socket } = selectSignalConnectionRaw(state);
|
|
2449
|
+
const streamId = streamIdForClient(clientView);
|
|
2450
|
+
const payload = { clientId: clientView.id, streamId: streamId !== null && streamId !== void 0 ? streamId : "0" };
|
|
2451
|
+
socket === null || socket === void 0 ? void 0 : socket.emit("remove_spotlight", payload);
|
|
2452
|
+
});
|
|
2453
|
+
const selectSpotlightsRaw = (state) => state.spotlights;
|
|
2454
|
+
const selectSpotlights = (state) => state.spotlights.sorted;
|
|
2455
|
+
const selectIsLocalParticipantSpotlighted = createSelector(selectLocalParticipantRaw, selectSpotlights, (localParticipant, spotlights) => {
|
|
2456
|
+
return isClientSpotlighted({ clientId: localParticipant.id, stream: localParticipant.stream, spotlights });
|
|
2457
|
+
});
|
|
2458
|
+
const selectSpotlightedClientViews = createSelector(selectAllClientViews, selectSpotlights, (clientViews, spotlights) => {
|
|
2459
|
+
return mapSpotlightsToClientViews(spotlights, clientViews);
|
|
2460
|
+
});
|
|
2461
|
+
|
|
2138
2462
|
const initialState$1 = {
|
|
2139
2463
|
isStreaming: false,
|
|
2140
2464
|
error: null,
|
|
@@ -2219,6 +2543,7 @@ const appReducer = combineReducers({
|
|
|
2219
2543
|
localMedia: localMediaSlice.reducer,
|
|
2220
2544
|
localParticipant: localParticipantSlice.reducer,
|
|
2221
2545
|
localScreenshare: localScreenshareSlice.reducer,
|
|
2546
|
+
notifications: notificationsSlice.reducer,
|
|
2222
2547
|
organization: organizationSlice.reducer,
|
|
2223
2548
|
remoteParticipants: remoteParticipantsSlice.reducer,
|
|
2224
2549
|
room: roomSlice.reducer,
|
|
@@ -2226,6 +2551,7 @@ const appReducer = combineReducers({
|
|
|
2226
2551
|
rtcAnalytics: rtcAnalyticsSlice.reducer,
|
|
2227
2552
|
rtcConnection: rtcConnectionSlice.reducer,
|
|
2228
2553
|
signalConnection: signalConnectionSlice.reducer,
|
|
2554
|
+
spotlights: spotlightsSlice.reducer,
|
|
2229
2555
|
streaming: streamingSlice.reducer,
|
|
2230
2556
|
waitingParticipants: waitingParticipantsSlice.reducer,
|
|
2231
2557
|
});
|
|
@@ -3233,18 +3559,19 @@ class RoomService {
|
|
|
3233
3559
|
}
|
|
3234
3560
|
|
|
3235
3561
|
class RoomParticipant {
|
|
3236
|
-
constructor({ displayName, id, stream, isAudioEnabled, isVideoEnabled }) {
|
|
3562
|
+
constructor({ displayName, id, stream, isAudioEnabled, isVideoEnabled, stickyReaction }) {
|
|
3237
3563
|
this.isLocalParticipant = false;
|
|
3238
3564
|
this.displayName = displayName;
|
|
3239
3565
|
this.id = id;
|
|
3240
3566
|
this.stream = stream;
|
|
3241
3567
|
this.isAudioEnabled = isAudioEnabled;
|
|
3242
3568
|
this.isVideoEnabled = isVideoEnabled;
|
|
3569
|
+
this.stickyReaction = stickyReaction;
|
|
3243
3570
|
}
|
|
3244
3571
|
}
|
|
3245
3572
|
class LocalParticipant extends RoomParticipant {
|
|
3246
|
-
constructor({ displayName, id, stream, isAudioEnabled, isVideoEnabled }) {
|
|
3247
|
-
super({ displayName, id, stream, isAudioEnabled, isVideoEnabled });
|
|
3573
|
+
constructor({ displayName, id, stream, isAudioEnabled, isVideoEnabled, stickyReaction }) {
|
|
3574
|
+
super({ displayName, id, stream, isAudioEnabled, isVideoEnabled, stickyReaction });
|
|
3248
3575
|
this.isLocalParticipant = true;
|
|
3249
3576
|
}
|
|
3250
3577
|
}
|
|
@@ -3274,4 +3601,4 @@ function createServices() {
|
|
|
3274
3601
|
};
|
|
3275
3602
|
}
|
|
3276
3603
|
|
|
3277
|
-
export { ApiClient, Credentials, CredentialsService, LocalParticipant, OrganizationApiClient, OrganizationService, OrganizationServiceCache, RoomService, addAppListener, appSlice, authorizationSlice, chatSlice, cloudRecordingSlice, createAppAsyncThunk, createAppAuthorizedThunk, createAppThunk, createReactor, createServices, createStore, createWebRtcEmitter, debounce, deviceBusy, deviceCredentialsSlice, deviceIdentified, deviceIdentifying, doAcceptWaitingParticipant, doAppStart, doAppStop, doConnectRoom, doConnectRtc, doDisconnectRtc, doEnableAudio, doEnableVideo, doEndMeeting, doGetDeviceCredentials, doHandleAcceptStreams, doHandleStreamingStarted, doHandleStreamingStopped, doKickParticipant, doKnockRoom, doLockRoom, doOrganizationFetch, doRejectWaitingParticipant, doRequestAudioEnable, doRtcAnalyticsCustomEventsInitialize, doRtcManagerCreated, doRtcManagerInitialize, doRtcReportStreamResolution, doSendChatMessage, doSetDevice, doSetDisplayName,
|
|
3604
|
+
export { ApiClient, Credentials, CredentialsService, LocalParticipant, OrganizationApiClient, OrganizationService, OrganizationServiceCache, RoomService, addAppListener, appSlice, authorizationSlice, chatSlice, cloudRecordingSlice, createAppAsyncThunk, createAppAuthorizedThunk, createAppThunk, createReactor, createServices, createStore, createWebRtcEmitter, debounce, deviceBusy, deviceCredentialsSlice, deviceIdentified, deviceIdentifying, doAcceptWaitingParticipant, doAppStart, doAppStop, doClearNotifications, doConnectRoom, doConnectRtc, doDisconnectRtc, doEnableAudio, doEnableVideo, doEndMeeting, doGetDeviceCredentials, doHandleAcceptStreams, doHandleStreamingStarted, doHandleStreamingStopped, doKickParticipant, doKnockRoom, doLockRoom, doOrganizationFetch, doRejectWaitingParticipant, doRemoveSpotlight, doRequestAudioEnable, doRtcAnalyticsCustomEventsInitialize, doRtcManagerCreated, doRtcManagerInitialize, doRtcReportStreamResolution, doSendChatMessage, doSendClientMetadata, doSetDevice, doSetDisplayName, doSetLocalStickyReaction, doSetNotification, doSignalConnect, doSignalDisconnect, doSignalIdentifyDevice, doSpotlightParticipant, doStartCloudRecording, doStartLocalMedia, doStartScreenshare, doStopCloudRecording, doStopLocalMedia, doStopScreenshare, doSwitchLocalStream, doToggleCamera, doToggleLowDataMode, doUpdateDeviceList, getAudioTrack, getFakeMediaStream, getVideoTrack, hasValue, initialCloudRecordingState, initialLocalMediaState, initialNotificationsState, isAcceptingStreams, isClientSpotlighted, listenerMiddleware, localMediaSlice, localMediaStopped, localParticipantSlice, localScreenshareSlice, localStreamMetadataUpdated, notificationsSlice, observeStore, organizationSlice, parseRoomUrlAndSubdomain, parseUnverifiedRoomKeyData, participantStreamAdded, participantStreamIdAdded, recordingRequestStarted, remoteParticipantsSlice, resolutionReported, roomConnectionSlice, roomSlice, rootReducer, rtcAnalyticsCustomEvents, rtcAnalyticsSlice, rtcConnectionSlice, rtcDisconnected, rtcDispatcherCreated, rtcManagerCreated, rtcManagerDestroyed, rtcManagerInitialized, selectAllClientViews, selectAppDisplayName, selectAppExternalId, selectAppInitialConfig, selectAppIsActive, selectAppIsNodeSdk, selectAppRaw, selectAppRoomName, selectAppRoomUrl, selectAppUserAgent, selectAuthorizationRoleName, selectBusyDeviceIds, selectCameraDeviceError, selectCameraDevices, selectChatMessages, selectChatRaw, selectCloudRecordingError, selectCloudRecordingRaw, selectCloudRecordingStartedAt, selectCloudRecordingStatus, selectCurrentCameraDeviceId, selectCurrentMicrophoneDeviceId, selectCurrentSpeakerDeviceId, selectDeviceCredentialsRaw, selectDeviceId, selectHasFetchedDeviceCredentials, selectIsAcceptingStreams, selectIsAuthorizedToAskToSpeak, selectIsAuthorizedToEndMeeting, selectIsAuthorizedToKickClient, selectIsAuthorizedToLockRoom, selectIsAuthorizedToRequestAudioEnable, selectIsAuthorizedToSpotlight, selectIsCameraEnabled, selectIsCloudRecording, selectIsLocalMediaStarting, selectIsLocalParticipantSpotlighted, selectIsLowDataModeEnabled, selectIsMicrophoneEnabled, selectIsSettingCameraDevice, selectIsSettingMicrophoneDevice, selectIsToggleCamera, selectLocalMediaConstraintsOptions, selectLocalMediaDevices, selectLocalMediaIsSwitchingStream, selectLocalMediaOptions, selectLocalMediaOwnsStream, selectLocalMediaRaw, selectLocalMediaShouldStartWithOptions, selectLocalMediaShouldStop, selectLocalMediaStartError, selectLocalMediaStatus, selectLocalMediaStream, selectLocalParticipantClientClaim, selectLocalParticipantDisplayName, selectLocalParticipantIsScreenSharing, selectLocalParticipantRaw, selectLocalParticipantStickyReaction, selectLocalParticipantView, selectLocalScreenshareRaw, selectLocalScreenshareStatus, selectLocalScreenshareStream, selectMicrophoneDeviceError, selectMicrophoneDevices, selectNotificationsEmitter, selectNotificationsEvents, selectNotificationsRaw, selectNumParticipants, selectOrganizationId, selectOrganizationRaw, selectRemoteClientViews, selectRemoteParticipants, selectRemoteParticipantsRaw, selectRoomConnectionError, selectRoomConnectionRaw, selectRoomConnectionSession, selectRoomConnectionSessionId, selectRoomConnectionStatus, selectRoomIsLocked, selectRoomKey, selectRtcConnectionRaw, selectRtcDispatcherCreated, selectRtcIsCreatingDispatcher, selectRtcManager, selectRtcManagerInitialized, selectRtcStatus, selectScreenshares, selectSelfId, selectShouldConnectRoom, selectShouldConnectRtc, selectShouldConnectSignal, selectShouldDisconnectRtc, selectShouldFetchDeviceCredentials, selectShouldFetchOrganization, selectShouldIdentifyDevice, selectShouldInitializeRtc, selectSignalConnectionDeviceIdentified, selectSignalConnectionRaw, selectSignalConnectionSocket, selectSignalIsIdentifyingDevice, selectSignalStatus, selectSpeakerDevices, selectSpotlightedClientViews, selectSpotlights, selectSpotlightsRaw, selectStreamingRaw, selectStreamsToAccept, selectWaitingParticipants, selectWaitingParticipantsRaw, setCurrentCameraDeviceId, setCurrentMicrophoneDeviceId, setCurrentSpeakerDeviceId, setLocalMediaOptions, setLocalMediaStream, setRoomKey, signalConnectionSlice, signalEvents, socketConnected, socketConnecting, socketDisconnected, socketReconnecting, spotlightsSlice, startAppListening, stopScreenshare, streamIdForClient, streamStatusUpdated, streamingSlice, toggleCameraEnabled, toggleLowDataModeEnabled, toggleMicrophoneEnabled, updateReportedValues, waitingParticipantsSlice };
|