|
@@ -1,36 +1,35 @@
|
1
|
|
-// @flow
|
2
|
|
-
|
3
|
1
|
import i18n from 'i18next';
|
4
|
2
|
import { batch } from 'react-redux';
|
5
|
3
|
|
|
4
|
+// @ts-ignore
|
6
|
5
|
import UIEvents from '../../../../service/UI/UIEvents';
|
|
6
|
+import { IStore } from '../../app/types';
|
7
|
7
|
import { approveParticipant } from '../../av-moderation/actions';
|
8
|
8
|
import { UPDATE_BREAKOUT_ROOMS } from '../../breakout-rooms/actionTypes';
|
9
|
9
|
import { getBreakoutRooms } from '../../breakout-rooms/functions';
|
10
|
10
|
import { toggleE2EE } from '../../e2ee/actions';
|
11
|
11
|
import { MAX_MODE } from '../../e2ee/constants';
|
|
12
|
+import { showNotification } from '../../notifications/actions';
|
12
|
13
|
import {
|
13
|
14
|
LOCAL_RECORDING_NOTIFICATION_ID,
|
14
|
15
|
NOTIFICATION_TIMEOUT_TYPE,
|
15
|
|
- RAISE_HAND_NOTIFICATION_ID,
|
16
|
|
- showNotification
|
17
|
|
-} from '../../notifications';
|
|
16
|
+ RAISE_HAND_NOTIFICATION_ID
|
|
17
|
+} from '../../notifications/constants';
|
18
|
18
|
import { isForceMuted } from '../../participants-pane/functions';
|
19
|
|
-import { CALLING, INVITED } from '../../presence-status';
|
|
19
|
+import { CALLING, INVITED } from '../../presence-status/constants';
|
20
|
20
|
import { RAISE_HAND_SOUND_ID } from '../../reactions/constants';
|
21
|
|
-import { RECORDING_OFF_SOUND_ID, RECORDING_ON_SOUND_ID } from '../../recording';
|
22
|
|
-import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
|
23
|
|
-import {
|
24
|
|
- CONFERENCE_WILL_JOIN,
|
25
|
|
- forEachConference,
|
26
|
|
- getCurrentConference
|
27
|
|
-} from '../conference';
|
28
|
|
-import { SET_CONFIG } from '../config';
|
|
21
|
+import { RECORDING_OFF_SOUND_ID, RECORDING_ON_SOUND_ID } from '../../recording/constants';
|
|
22
|
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app/actionTypes';
|
|
23
|
+import { CONFERENCE_WILL_JOIN } from '../conference/actionTypes';
|
|
24
|
+import { forEachConference, getCurrentConference } from '../conference/functions';
|
|
25
|
+import { IJitsiConference } from '../conference/reducer';
|
|
26
|
+import { SET_CONFIG } from '../config/actionTypes';
|
29
|
27
|
import { getDisableRemoveRaisedHandOnFocus } from '../config/functions.any';
|
30
|
28
|
import { JitsiConferenceEvents } from '../lib-jitsi-meet';
|
31
|
|
-import { MEDIA_TYPE } from '../media';
|
32
|
|
-import { MiddlewareRegistry, StateListenerRegistry } from '../redux';
|
33
|
|
-import { playSound, registerSound, unregisterSound } from '../sounds';
|
|
29
|
+import { MEDIA_TYPE } from '../media/constants';
|
|
30
|
+import MiddlewareRegistry from '../redux/MiddlewareRegistry';
|
|
31
|
+import StateListenerRegistry from '../redux/StateListenerRegistry';
|
|
32
|
+import { playSound, registerSound, unregisterSound } from '../sounds/actions';
|
34
|
33
|
|
35
|
34
|
import {
|
36
|
35
|
DOMINANT_SPEAKER_CHANGED,
|
|
@@ -79,9 +78,9 @@ import {
|
79
|
78
|
} from './functions';
|
80
|
79
|
import logger from './logger';
|
81
|
80
|
import { PARTICIPANT_JOINED_FILE, PARTICIPANT_LEFT_FILE } from './sounds';
|
82
|
|
-import './subscriber';
|
|
81
|
+import { IJitsiParticipant } from './types';
|
83
|
82
|
|
84
|
|
-declare var APP: Object;
|
|
83
|
+import './subscriber';
|
85
|
84
|
|
86
|
85
|
/**
|
87
|
86
|
* Middleware that captures CONFERENCE_JOINED and CONFERENCE_LEFT actions and
|
|
@@ -128,8 +127,7 @@ MiddlewareRegistry.register(store => next => action => {
|
128
|
127
|
const participant = getDominantSpeakerParticipant(state);
|
129
|
128
|
|
130
|
129
|
if (
|
131
|
|
- participant
|
132
|
|
- && participant.local
|
|
130
|
+ participant?.local
|
133
|
131
|
&& hasRaisedHand(participant)
|
134
|
132
|
&& action.level > LOWER_HAND_AUDIO_LEVEL
|
135
|
133
|
&& !getDisableRemoveRaisedHandOnFocus(state)
|
|
@@ -142,14 +140,14 @@ MiddlewareRegistry.register(store => next => action => {
|
142
|
140
|
case GRANT_MODERATOR: {
|
143
|
141
|
const { conference } = store.getState()['features/base/conference'];
|
144
|
142
|
|
145
|
|
- conference.grantOwner(action.id);
|
|
143
|
+ conference?.grantOwner(action.id);
|
146
|
144
|
break;
|
147
|
145
|
}
|
148
|
146
|
|
149
|
147
|
case KICK_PARTICIPANT: {
|
150
|
148
|
const { conference } = store.getState()['features/base/conference'];
|
151
|
149
|
|
152
|
|
- conference.kickParticipant(action.id);
|
|
150
|
+ conference?.kickParticipant(action.id);
|
153
|
151
|
break;
|
154
|
152
|
}
|
155
|
153
|
|
|
@@ -164,13 +162,13 @@ MiddlewareRegistry.register(store => next => action => {
|
164
|
162
|
// participant is uniquely identified by the very fact that there is
|
165
|
163
|
// only one local participant.
|
166
|
164
|
|
167
|
|
- id: localId,
|
|
165
|
+ id: localId ?? '',
|
168
|
166
|
local: true,
|
169
|
167
|
raisedHandTimestamp
|
170
|
168
|
}));
|
171
|
169
|
|
172
|
170
|
store.dispatch(raiseHandUpdateQueue({
|
173
|
|
- id: localId,
|
|
171
|
+ id: localId ?? '',
|
174
|
172
|
raisedHandTimestamp
|
175
|
173
|
}));
|
176
|
174
|
|
|
@@ -188,14 +186,16 @@ MiddlewareRegistry.register(store => next => action => {
|
188
|
186
|
const { deploymentInfo } = state['features/base/config'];
|
189
|
187
|
|
190
|
188
|
// if there userRegion set let's use it for the local participant
|
191
|
|
- if (deploymentInfo && deploymentInfo.userRegion) {
|
|
189
|
+ if (deploymentInfo?.userRegion) {
|
192
|
190
|
const localId = getLocalParticipant(state)?.id;
|
193
|
191
|
|
194
|
|
- store.dispatch(participantUpdated({
|
195
|
|
- id: localId,
|
196
|
|
- local: true,
|
197
|
|
- region: deploymentInfo.userRegion
|
198
|
|
- }));
|
|
192
|
+ if (localId) {
|
|
193
|
+ store.dispatch(participantUpdated({
|
|
194
|
+ id: localId,
|
|
195
|
+ local: true,
|
|
196
|
+ region: deploymentInfo.userRegion
|
|
197
|
+ }));
|
|
198
|
+ }
|
199
|
199
|
}
|
200
|
200
|
|
201
|
201
|
return result;
|
|
@@ -207,7 +207,7 @@ MiddlewareRegistry.register(store => next => action => {
|
207
|
207
|
const localId = getLocalParticipant(state)?.id;
|
208
|
208
|
const { localRecording } = state['features/base/config'];
|
209
|
209
|
|
210
|
|
- if (localRecording?.notifyAllParticipants && !onlySelf) {
|
|
210
|
+ if (localRecording?.notifyAllParticipants && !onlySelf && localId) {
|
211
|
211
|
store.dispatch(participantUpdated({
|
212
|
212
|
// XXX Only the local participant is allowed to update without
|
213
|
213
|
// stating the JitsiConference instance (i.e. participant property
|
|
@@ -227,7 +227,7 @@ MiddlewareRegistry.register(store => next => action => {
|
227
|
227
|
case MUTE_REMOTE_PARTICIPANT: {
|
228
|
228
|
const { conference } = store.getState()['features/base/conference'];
|
229
|
229
|
|
230
|
|
- conference.muteParticipant(action.id, action.mediaType);
|
|
230
|
+ conference?.muteParticipant(action.id, action.mediaType);
|
231
|
231
|
break;
|
232
|
232
|
}
|
233
|
233
|
|
|
@@ -319,7 +319,7 @@ MiddlewareRegistry.register(store => next => action => {
|
319
|
319
|
if (breakoutRoom) {
|
320
|
320
|
const rooms = getBreakoutRooms(state);
|
321
|
321
|
const roomCounter = state['features/breakout-rooms'].roomCounter;
|
322
|
|
- const newRooms = {};
|
|
322
|
+ const newRooms: any = {};
|
323
|
323
|
|
324
|
324
|
Object.entries(rooms).forEach(([ key, r ]) => {
|
325
|
325
|
const participants = r?.participants || {};
|
|
@@ -393,7 +393,7 @@ StateListenerRegistry.register(
|
393
|
393
|
/* listener */ ({ leaving }, { dispatch, getState }) => {
|
394
|
394
|
const state = getState();
|
395
|
395
|
const localParticipant = getLocalParticipant(state);
|
396
|
|
- let id;
|
|
396
|
+ let id: string;
|
397
|
397
|
|
398
|
398
|
if (!localParticipant
|
399
|
399
|
|| (id = localParticipant.id)
|
|
@@ -421,37 +421,41 @@ StateListenerRegistry.register(
|
421
|
421
|
state => state['features/base/conference'].conference,
|
422
|
422
|
(conference, store) => {
|
423
|
423
|
if (conference) {
|
424
|
|
- const propertyHandlers = {
|
425
|
|
- 'e2ee.enabled': (participant, value) => _e2eeUpdated(store, conference, participant.getId(), value),
|
426
|
|
- 'features_e2ee': (participant, value) =>
|
|
424
|
+ const propertyHandlers: {
|
|
425
|
+ [key: string]: Function;
|
|
426
|
+ } = {
|
|
427
|
+ 'e2ee.enabled': (participant: IJitsiParticipant, value: string) =>
|
|
428
|
+ _e2eeUpdated(store, conference, participant.getId(), value),
|
|
429
|
+ 'features_e2ee': (participant: IJitsiParticipant, value: boolean) =>
|
427
|
430
|
store.dispatch(participantUpdated({
|
428
|
431
|
conference,
|
429
|
432
|
id: participant.getId(),
|
430
|
433
|
e2eeSupported: value
|
431
|
434
|
})),
|
432
|
|
- 'features_jigasi': (participant, value) =>
|
|
435
|
+ 'features_jigasi': (participant: IJitsiParticipant, value: boolean) =>
|
433
|
436
|
store.dispatch(participantUpdated({
|
434
|
437
|
conference,
|
435
|
438
|
id: participant.getId(),
|
436
|
439
|
isJigasi: value
|
437
|
440
|
})),
|
438
|
|
- 'features_screen-sharing': (participant, value) => // eslint-disable-line no-unused-vars
|
|
441
|
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
442
|
+ 'features_screen-sharing': (participant: IJitsiParticipant, value: string) =>
|
439
|
443
|
store.dispatch(participantUpdated({
|
440
|
444
|
conference,
|
441
|
445
|
id: participant.getId(),
|
442
|
446
|
features: { 'screen-sharing': true }
|
443
|
447
|
})),
|
444
|
|
- 'localRecording': (participant, value) =>
|
|
448
|
+ 'localRecording': (participant: IJitsiParticipant, value: string) =>
|
445
|
449
|
_localRecordingUpdated(store, conference, participant.getId(), value),
|
446
|
|
- 'raisedHand': (participant, value) =>
|
|
450
|
+ 'raisedHand': (participant: IJitsiParticipant, value: string) =>
|
447
|
451
|
_raiseHandUpdated(store, conference, participant.getId(), value),
|
448
|
|
- 'region': (participant, value) =>
|
|
452
|
+ 'region': (participant: IJitsiParticipant, value: string) =>
|
449
|
453
|
store.dispatch(participantUpdated({
|
450
|
454
|
conference,
|
451
|
455
|
id: participant.getId(),
|
452
|
456
|
region: value
|
453
|
457
|
})),
|
454
|
|
- 'remoteControlSessionStatus': (participant, value) =>
|
|
458
|
+ 'remoteControlSessionStatus': (participant: IJitsiParticipant, value: boolean) =>
|
455
|
459
|
store.dispatch(participantUpdated({
|
456
|
460
|
conference,
|
457
|
461
|
id: participant.getId(),
|
|
@@ -460,12 +464,12 @@ StateListenerRegistry.register(
|
460
|
464
|
};
|
461
|
465
|
|
462
|
466
|
// update properties for the participants that are already in the conference
|
463
|
|
- conference.getParticipants().forEach(participant => {
|
|
467
|
+ conference.getParticipants().forEach((participant: any) => {
|
464
|
468
|
Object.keys(propertyHandlers).forEach(propertyName => {
|
465
|
469
|
const value = participant.getProperty(propertyName);
|
466
|
470
|
|
467
|
471
|
if (value !== undefined) {
|
468
|
|
- propertyHandlers[propertyName](participant, value);
|
|
472
|
+ propertyHandlers[propertyName as keyof typeof propertyHandlers](participant, value);
|
469
|
473
|
}
|
470
|
474
|
});
|
471
|
475
|
});
|
|
@@ -473,17 +477,17 @@ StateListenerRegistry.register(
|
473
|
477
|
// We joined a conference
|
474
|
478
|
conference.on(
|
475
|
479
|
JitsiConferenceEvents.PARTICIPANT_PROPERTY_CHANGED,
|
476
|
|
- (participant, propertyName, oldValue, newValue) => {
|
|
480
|
+ (participant: IJitsiParticipant, propertyName: string, oldValue: string, newValue: string) => {
|
477
|
481
|
if (propertyHandlers.hasOwnProperty(propertyName)) {
|
478
|
482
|
propertyHandlers[propertyName](participant, newValue);
|
479
|
483
|
}
|
480
|
484
|
});
|
481
|
485
|
} else {
|
482
|
|
- const localParticipantId = getLocalParticipant(store.getState).id;
|
|
486
|
+ const localParticipantId = getLocalParticipant(store.getState)?.id;
|
483
|
487
|
|
484
|
488
|
// We left the conference, the local participant must be updated.
|
485
|
|
- _e2eeUpdated(store, conference, localParticipantId, false);
|
486
|
|
- _raiseHandUpdated(store, conference, localParticipantId, 0);
|
|
489
|
+ _e2eeUpdated(store, conference, localParticipantId ?? '', false);
|
|
490
|
+ _raiseHandUpdated(store, conference, localParticipantId ?? '', 0);
|
487
|
491
|
}
|
488
|
492
|
}
|
489
|
493
|
);
|
|
@@ -497,7 +501,8 @@ StateListenerRegistry.register(
|
497
|
501
|
* @param {boolean} newValue - The new value of the E2EE enabled status.
|
498
|
502
|
* @returns {void}
|
499
|
503
|
*/
|
500
|
|
-function _e2eeUpdated({ getState, dispatch }, conference, participantId, newValue) {
|
|
504
|
+function _e2eeUpdated({ getState, dispatch }: IStore, conference: IJitsiConference,
|
|
505
|
+ participantId: string, newValue: string | boolean) {
|
501
|
506
|
const e2eeEnabled = newValue === 'true';
|
502
|
507
|
const { e2ee = {} } = getState()['features/base/config'];
|
503
|
508
|
|
|
@@ -530,11 +535,12 @@ function _e2eeUpdated({ getState, dispatch }, conference, participantId, newValu
|
530
|
535
|
* @private
|
531
|
536
|
* @returns {Object} The value returned by {@code next(action)}.
|
532
|
537
|
*/
|
533
|
|
-function _localParticipantJoined({ getState, dispatch }, next, action) {
|
|
538
|
+function _localParticipantJoined({ getState, dispatch }: IStore, next: Function, action: any) {
|
534
|
539
|
const result = next(action);
|
535
|
540
|
|
536
|
541
|
const settings = getState()['features/base/settings'];
|
537
|
542
|
|
|
543
|
+ // @ts-ignore
|
538
|
544
|
dispatch(localParticipantJoined({
|
539
|
545
|
avatarURL: settings.avatarURL,
|
540
|
546
|
email: settings.email,
|
|
@@ -555,7 +561,7 @@ function _localParticipantJoined({ getState, dispatch }, next, action) {
|
555
|
561
|
* @private
|
556
|
562
|
* @returns {Object} The value returned by {@code next(action)}.
|
557
|
563
|
*/
|
558
|
|
-function _localParticipantLeft({ dispatch }, next, action) {
|
|
564
|
+function _localParticipantLeft({ dispatch }: IStore, next: Function, action: any) {
|
559
|
565
|
const result = next(action);
|
560
|
566
|
|
561
|
567
|
dispatch(localParticipantLeft());
|
|
@@ -572,7 +578,7 @@ function _localParticipantLeft({ dispatch }, next, action) {
|
572
|
578
|
* @private
|
573
|
579
|
* @returns {void}
|
574
|
580
|
*/
|
575
|
|
-function _maybePlaySounds({ getState, dispatch }, action) {
|
|
581
|
+function _maybePlaySounds({ getState, dispatch }: IStore, action: any) {
|
576
|
582
|
const state = getState();
|
577
|
583
|
const { startAudioMuted } = state['features/base/config'];
|
578
|
584
|
const { soundsParticipantJoined: joinSound, soundsParticipantLeft: leftSound } = state['features/base/settings'];
|
|
@@ -617,7 +623,7 @@ function _maybePlaySounds({ getState, dispatch }, action) {
|
617
|
623
|
* @private
|
618
|
624
|
* @returns {Object} The value returned by {@code next(action)}.
|
619
|
625
|
*/
|
620
|
|
-function _participantJoinedOrUpdated(store, next, action) {
|
|
626
|
+function _participantJoinedOrUpdated(store: IStore, next: Function, action: any) {
|
621
|
627
|
const { dispatch, getState } = store;
|
622
|
628
|
const { overwrittenNameList } = store.getState()['features/base/participants'];
|
623
|
629
|
const { participant: {
|
|
@@ -639,7 +645,7 @@ function _participantJoinedOrUpdated(store, next, action) {
|
639
|
645
|
const rHand = parseInt(raisedHandTimestamp, 10);
|
640
|
646
|
|
641
|
647
|
// Send raisedHand signalling only if there is a change
|
642
|
|
- if (conference && rHand !== getLocalParticipant(getState()).raisedHandTimestamp) {
|
|
648
|
+ if (conference && rHand !== getLocalParticipant(getState())?.raisedHandTimestamp) {
|
643
|
649
|
conference.setLocalParticipantProperty('raisedHand', rHand);
|
644
|
650
|
}
|
645
|
651
|
}
|
|
@@ -657,7 +663,7 @@ function _participantJoinedOrUpdated(store, next, action) {
|
657
|
663
|
|
658
|
664
|
// Send localRecording signalling only if there is a change
|
659
|
665
|
if (conference
|
660
|
|
- && localRecording !== getLocalParticipant(getState()).localRecording) {
|
|
666
|
+ && localRecording !== getLocalParticipant(getState())?.localRecording) {
|
661
|
667
|
conference.setLocalParticipantProperty('localRecording', localRecording);
|
662
|
668
|
}
|
663
|
669
|
}
|
|
@@ -673,12 +679,12 @@ function _participantJoinedOrUpdated(store, next, action) {
|
673
|
679
|
const { disableThirdPartyRequests } = getState()['features/base/config'];
|
674
|
680
|
|
675
|
681
|
if (!disableThirdPartyRequests && (avatarURL || email || id || name)) {
|
676
|
|
- const participantId = !id && local ? getLocalParticipant(getState()).id : id;
|
|
682
|
+ const participantId = !id && local ? getLocalParticipant(getState())?.id : id;
|
677
|
683
|
const updatedParticipant = getParticipantById(getState(), participantId);
|
678
|
684
|
|
679
|
|
- getFirstLoadableAvatarUrl(updatedParticipant, store)
|
680
|
|
- .then(urlData => {
|
681
|
|
- dispatch(setLoadableAvatarUrl(participantId, urlData?.src, urlData?.isUsingCORS));
|
|
685
|
+ getFirstLoadableAvatarUrl(updatedParticipant ?? { id: '' }, store)
|
|
686
|
+ .then((urlData?: { isUsingCORS: boolean; src: string; }) => {
|
|
687
|
+ dispatch(setLoadableAvatarUrl(participantId, urlData?.src ?? '', Boolean(urlData?.isUsingCORS)));
|
682
|
688
|
});
|
683
|
689
|
}
|
684
|
690
|
}
|
|
@@ -703,7 +709,8 @@ function _participantJoinedOrUpdated(store, next, action) {
|
703
|
709
|
* @param {boolean} newValue - The new value of the local recording status.
|
704
|
710
|
* @returns {void}
|
705
|
711
|
*/
|
706
|
|
-function _localRecordingUpdated({ dispatch, getState }, conference, participantId, newValue) {
|
|
712
|
+function _localRecordingUpdated({ dispatch, getState }: IStore, conference: IJitsiConference,
|
|
713
|
+ participantId: string, newValue: string) {
|
707
|
714
|
const state = getState();
|
708
|
715
|
|
709
|
716
|
dispatch(participantUpdated({
|
|
@@ -732,7 +739,8 @@ function _localRecordingUpdated({ dispatch, getState }, conference, participantI
|
732
|
739
|
* @param {boolean} newValue - The new value of the raise hand status.
|
733
|
740
|
* @returns {void}
|
734
|
741
|
*/
|
735
|
|
-function _raiseHandUpdated({ dispatch, getState }, conference, participantId, newValue) {
|
|
742
|
+function _raiseHandUpdated({ dispatch, getState }: IStore, conference: IJitsiConference,
|
|
743
|
+ participantId: string, newValue: string | number) {
|
736
|
744
|
let raisedHandTimestamp;
|
737
|
745
|
|
738
|
746
|
switch (newValue) {
|
|
@@ -744,7 +752,7 @@ function _raiseHandUpdated({ dispatch, getState }, conference, participantId, ne
|
744
|
752
|
raisedHandTimestamp = Date.now();
|
745
|
753
|
break;
|
746
|
754
|
default:
|
747
|
|
- raisedHandTimestamp = parseInt(newValue, 10);
|
|
755
|
+ raisedHandTimestamp = parseInt(`${newValue}`, 10);
|
748
|
756
|
}
|
749
|
757
|
const state = getState();
|
750
|
758
|
|
|
@@ -811,7 +819,7 @@ function _raiseHandUpdated({ dispatch, getState }, conference, participantId, ne
|
811
|
819
|
* @private
|
812
|
820
|
* @returns {void}
|
813
|
821
|
*/
|
814
|
|
-function _registerSounds({ dispatch }) {
|
|
822
|
+function _registerSounds({ dispatch }: IStore) {
|
815
|
823
|
dispatch(
|
816
|
824
|
registerSound(PARTICIPANT_JOINED_SOUND_ID, PARTICIPANT_JOINED_FILE));
|
817
|
825
|
dispatch(registerSound(PARTICIPANT_LEFT_SOUND_ID, PARTICIPANT_LEFT_FILE));
|
|
@@ -824,7 +832,7 @@ function _registerSounds({ dispatch }) {
|
824
|
832
|
* @private
|
825
|
833
|
* @returns {void}
|
826
|
834
|
*/
|
827
|
|
-function _unregisterSounds({ dispatch }) {
|
|
835
|
+function _unregisterSounds({ dispatch }: IStore) {
|
828
|
836
|
dispatch(unregisterSound(PARTICIPANT_JOINED_SOUND_ID));
|
829
|
837
|
dispatch(unregisterSound(PARTICIPANT_LEFT_SOUND_ID));
|
830
|
838
|
}
|