From 43578474a0b047a424aeb67c488a9bbc793d2f90 Mon Sep 17 00:00:00 2001 From: Robert Pintilii Date: Mon, 8 Aug 2022 11:12:22 +0300 Subject: [PATCH] ref: Convert base/participants to TS (#11978) Remove unnecessary ts-ignores --- react/features/av-moderation/reducer.ts | 4 +- .../avatar/{constants.js => constants.ts} | 2 - .../avatar/{functions.js => functions.ts} | 10 +- .../participants/{actions.js => actions.ts} | 87 +++++++++-------- .../{functions.js => functions.ts} | 95 ++++++++++--------- .../participants/{logger.js => logger.ts} | 2 - react/features/base/participants/reducer.ts | 8 +- .../components/native/carmode/TitleBar.tsx | 3 +- .../components/native/DisplayNameLabel.tsx | 2 - .../lobby/components/web/LobbySection.tsx | 3 +- .../web/RoomParticipantContextMenu.tsx | 4 +- .../prejoin/components/Prejoin.native.tsx | 5 +- .../components/web/ReactionsMenu.tsx | 5 +- react/features/reactions/functions.any.ts | 4 +- react/features/reactions/middleware.ts | 8 +- .../security-dialog/web/SecurityDialog.tsx | 3 +- .../web/LocalVideoMenuTriggerButton.tsx | 5 +- .../web/RemoteVideoMenuTriggerButton.tsx | 5 +- 18 files changed, 122 insertions(+), 133 deletions(-) rename react/features/base/avatar/{constants.js => constants.ts} (91%) rename react/features/base/avatar/{functions.js => functions.ts} (89%) rename react/features/base/participants/{actions.js => actions.ts} (86%) rename react/features/base/participants/{functions.js => functions.ts} (87%) rename react/features/base/participants/{logger.js => logger.ts} (91%) diff --git a/react/features/av-moderation/reducer.ts b/react/features/av-moderation/reducer.ts index 34a45de20..d8c9b6207 100644 --- a/react/features/av-moderation/reducer.ts +++ b/react/features/av-moderation/reducer.ts @@ -3,9 +3,7 @@ import type { MediaType } from '../base/media/constants'; import { PARTICIPANT_LEFT, PARTICIPANT_UPDATED - - // @ts-ignore -} from '../base/participants'; +} from '../base/participants/actionTypes'; import ReducerRegistry from '../base/redux/ReducerRegistry'; import { diff --git a/react/features/base/avatar/constants.js b/react/features/base/avatar/constants.ts similarity index 91% rename from react/features/base/avatar/constants.js rename to react/features/base/avatar/constants.ts index 4cc9ceaaf..4825efa29 100644 --- a/react/features/base/avatar/constants.js +++ b/react/features/base/avatar/constants.ts @@ -1,5 +1,3 @@ -// @flow - /** * The base URL for gravatar images. */ diff --git a/react/features/base/avatar/functions.js b/react/features/base/avatar/functions.ts similarity index 89% rename from react/features/base/avatar/functions.js rename to react/features/base/avatar/functions.ts index e5f37850c..a5bf39be0 100644 --- a/react/features/base/avatar/functions.js +++ b/react/features/base/avatar/functions.ts @@ -1,5 +1,3 @@ -// @flow - import GraphemeSplitter from 'grapheme-splitter'; import _ from 'lodash'; @@ -24,7 +22,7 @@ const splitter = new GraphemeSplitter(); * @param {Array} customAvatarBackgrounds - Custom avatar background values. * @returns {string} */ -export function getAvatarColor(initials: ?string, customAvatarBackgrounds: Array) { +export function getAvatarColor(initials: string|undefined, customAvatarBackgrounds: Array) { const hasCustomAvatarBackgronds = customAvatarBackgrounds && customAvatarBackgrounds.length; const colorsBase = hasCustomAvatarBackgronds ? customAvatarBackgrounds : AVATAR_COLORS; @@ -34,7 +32,7 @@ export function getAvatarColor(initials: ?string, customAvatarBackgrounds: Array let nameHash = 0; for (const s of initials) { - nameHash += s.codePointAt(0); + nameHash += Number(s.codePointAt(0)); } colorIndex = nameHash % colorsBase.length; @@ -49,7 +47,7 @@ export function getAvatarColor(initials: ?string, customAvatarBackgrounds: Array * @param {string} word - The string to get grapheme from. * @returns {string} */ -function getFirstGraphemeUpper(word) { +function getFirstGraphemeUpper(word: string) { if (!word?.length) { return ''; } @@ -63,7 +61,7 @@ function getFirstGraphemeUpper(word) { * @param {string?} s - The string to generate initials for. * @returns {string?} */ -export function getInitials(s: ?string) { +export function getInitials(s?: string) { // We don't want to use the domain part of an email address, if it is one const initialsBasis = _.split(s, '@')[0]; const [ firstWord, secondWord ] = initialsBasis.split(wordSplitRegex).filter(Boolean); diff --git a/react/features/base/participants/actions.js b/react/features/base/participants/actions.ts similarity index 86% rename from react/features/base/participants/actions.js rename to react/features/base/participants/actions.ts index d1caefc5b..95996a7e2 100644 --- a/react/features/base/participants/actions.js +++ b/react/features/base/participants/actions.ts @@ -1,5 +1,8 @@ +import { Dispatch } from 'redux'; + +// @ts-ignore import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../../notifications'; -import { set } from '../redux'; +import { set } from '../redux/functions'; import { DOMINANT_SPEAKER_CHANGED, @@ -34,6 +37,7 @@ import { getParticipantById } from './functions'; import logger from './logger'; +import { Participant } from './reducer'; /** * Create an action for when dominant speaker changes. @@ -53,7 +57,7 @@ import logger from './logger'; * } * }} */ -export function dominantSpeakerChanged(dominantSpeaker, previousSpeakers, conference) { +export function dominantSpeakerChanged(dominantSpeaker: string, previousSpeakers: string[], conference: any) { return { type: DOMINANT_SPEAKER_CHANGED, participant: { @@ -73,7 +77,7 @@ export function dominantSpeakerChanged(dominantSpeaker, previousSpeakers, confer * id: string * }} */ -export function grantModerator(id) { +export function grantModerator(id: string) { return { type: GRANT_MODERATOR, id @@ -89,7 +93,7 @@ export function grantModerator(id) { * id: string * }} */ -export function kickParticipant(id) { +export function kickParticipant(id: string) { return { type: KICK_PARTICIPANT, id @@ -105,8 +109,8 @@ export function kickParticipant(id) { * constants. * @returns {Function} */ -export function localParticipantConnectionStatusChanged(connectionStatus) { - return (dispatch, getState) => { +export function localParticipantConnectionStatusChanged(connectionStatus: string) { + return (dispatch: Dispatch, getState: Function) => { const participant = getLocalParticipant(getState); if (participant) { @@ -125,8 +129,8 @@ export function localParticipantConnectionStatusChanged(connectionStatus) { * @param {string} id - New ID for local participant. * @returns {Function} */ -export function localParticipantIdChanged(id) { - return (dispatch, getState) => { +export function localParticipantIdChanged(id: string) { + return (dispatch: Dispatch, getState: Function) => { const participant = getLocalParticipant(getState); if (participant) { @@ -152,7 +156,7 @@ export function localParticipantIdChanged(id) { * participant: Participant * }} */ -export function localParticipantJoined(participant = {}) { +export function localParticipantJoined(participant: Participant = { id: '' }) { return participantJoined(set(participant, 'local', true)); } @@ -162,7 +166,7 @@ export function localParticipantJoined(participant = {}) { * @returns {Function} */ export function localParticipantLeft() { - return (dispatch, getState) => { + return (dispatch: Dispatch, getState: Function) => { const participant = getLocalParticipant(getState); if (participant) { @@ -191,8 +195,8 @@ export function localParticipantLeft() { * @param {string} role - The new role of the local participant. * @returns {Function} */ -export function localParticipantRoleChanged(role) { - return (dispatch, getState) => { +export function localParticipantRoleChanged(role: string) { + return (dispatch: Dispatch, getState: Function) => { const participant = getLocalParticipant(getState); if (participant) { @@ -212,7 +216,7 @@ export function localParticipantRoleChanged(role) { * mediaType: MEDIA_TYPE * }} */ -export function muteRemoteParticipant(id, mediaType) { +export function muteRemoteParticipant(id: string, mediaType: string) { return { type: MUTE_REMOTE_PARTICIPANT, id, @@ -234,7 +238,7 @@ export function muteRemoteParticipant(id, mediaType) { * } * }} */ -export function participantConnectionStatusChanged(id, connectionStatus) { +export function participantConnectionStatusChanged(id: string, connectionStatus: string) { return { type: PARTICIPANT_UPDATED, participant: { @@ -253,7 +257,7 @@ export function participantConnectionStatusChanged(id, connectionStatus) { * participant: Participant * }} */ -export function participantJoined(participant) { +export function participantJoined(participant: Participant) { // Only the local participant is not identified with an id-conference pair. if (participant.local) { return { @@ -271,7 +275,7 @@ export function participantJoined(participant) { 'A remote participant must be associated with a JitsiConference!'); } - return (dispatch, getState) => { + return (dispatch: Dispatch, getState: Function) => { // A remote participant is only expected to join in a joined or joining // conference. The following check is really necessary because a // JitsiConference may have moved into leaving but may still manage to @@ -300,8 +304,8 @@ export function participantJoined(participant) { * participant: Participant * }} */ -export function updateRemoteParticipantFeatures(jitsiParticipant) { - return (dispatch, getState) => { +export function updateRemoteParticipantFeatures(jitsiParticipant: any) { + return (dispatch: Dispatch, getState: Function) => { if (!jitsiParticipant) { return; } @@ -309,7 +313,7 @@ export function updateRemoteParticipantFeatures(jitsiParticipant) { const id = jitsiParticipant.getId(); jitsiParticipant.getFeatures() - .then(features => { + .then((features: Map) => { const supportsRemoteControl = features.has(DISCO_REMOTE_CONTROL_FEATURE); const participant = getParticipantById(getState(), id); @@ -327,7 +331,7 @@ export function updateRemoteParticipantFeatures(jitsiParticipant) { }); } }) - .catch(error => { + .catch((error: any) => { logger.error(`Failed to get participant features for ${id}!`, error); }); }; @@ -345,7 +349,7 @@ export function updateRemoteParticipantFeatures(jitsiParticipant) { * id: string * }} */ -export function hiddenParticipantJoined(id, displayName) { +export function hiddenParticipantJoined(id: string, displayName: string) { return { type: HIDDEN_PARTICIPANT_JOINED, id, @@ -362,7 +366,7 @@ export function hiddenParticipantJoined(id, displayName) { * id: string * }} */ -export function hiddenParticipantLeft(id) { +export function hiddenParticipantLeft(id: string) { return { type: HIDDEN_PARTICIPANT_LEFT, id @@ -387,7 +391,8 @@ export function hiddenParticipantLeft(id) { * } * }} */ -export function participantLeft(id, conference, isReplaced, isVirtualScreenshareParticipant) { +export function participantLeft(id: string, conference: any, + isReplaced?: boolean, isVirtualScreenshareParticipant?: boolean) { return { type: PARTICIPANT_LEFT, participant: { @@ -412,7 +417,7 @@ export function participantLeft(id, conference, isReplaced, isVirtualScreenshare * } * }} */ -export function participantPresenceChanged(id, presence) { +export function participantPresenceChanged(id: string, presence: string) { return participantUpdated({ id, presence @@ -432,7 +437,7 @@ export function participantPresenceChanged(id, presence) { * } * }} */ -export function participantRoleChanged(id, role) { +export function participantRoleChanged(id: string, role: string) { return participantUpdated({ id, role @@ -450,7 +455,7 @@ export function participantRoleChanged(id, role) { * name: string * }} */ -export function screenshareParticipantDisplayNameChanged(id, name) { +export function screenshareParticipantDisplayNameChanged(id: string, name: string) { return { type: SCREENSHARE_PARTICIPANT_NAME_CHANGED, id, @@ -470,7 +475,7 @@ export function screenshareParticipantDisplayNameChanged(id, name) { * participant: Participant * }} */ -export function participantUpdated(participant = {}) { +export function participantUpdated(participant: Participant = { id: '' }) { const participantToUpdate = { ...participant }; @@ -492,8 +497,8 @@ export function participantUpdated(participant = {}) { * @param {JitsiLocalTrack} track - Information about the track that has been muted. * @returns {Promise} */ -export function participantMutedUs(participant, track) { - return (dispatch, getState) => { +export function participantMutedUs(participant: any, track: any) { + return (dispatch: Dispatch, getState: Function) => { if (!participant) { return; } @@ -516,8 +521,8 @@ export function participantMutedUs(participant, track) { * @param {(boolean)} local - JitsiTrack instance. * @returns {Function} */ -export function createVirtualScreenshareParticipant(sourceName, local) { - return (dispatch, getState) => { +export function createVirtualScreenshareParticipant(sourceName: string, local: boolean) { + return (dispatch: Dispatch, getState: Function) => { const state = getState(); const ownerId = getVirtualScreenshareParticipantOwnerId(sourceName); const ownerName = getParticipantDisplayName(state, ownerId); @@ -539,8 +544,8 @@ export function createVirtualScreenshareParticipant(sourceName, local) { * @param {JitsiParticipant} kicked - Information about participant that was kicked. * @returns {Promise} */ -export function participantKicked(kicker, kicked) { - return (dispatch, getState) => { +export function participantKicked(kicker: any, kicked: any) { + return (dispatch: Dispatch, getState: Function) => { dispatch({ type: PARTICIPANT_KICKED, @@ -576,7 +581,7 @@ export function participantKicked(kicker, kicked) { * } * }} */ -export function pinParticipant(id) { +export function pinParticipant(id: string) { return { type: PIN_PARTICIPANT, participant: { @@ -600,7 +605,7 @@ export function pinParticipant(id) { * } * }} */ -export function setLoadableAvatarUrl(participantId, url, useCORS) { +export function setLoadableAvatarUrl(participantId: string, url: string, useCORS: boolean) { return { type: SET_LOADABLE_AVATAR_URL, participant: { @@ -620,7 +625,7 @@ export function setLoadableAvatarUrl(participantId, url, useCORS) { * raisedHandTimestamp: number * }} */ -export function raiseHand(enabled) { +export function raiseHand(enabled: boolean) { return { type: LOCAL_PARTICIPANT_RAISE_HAND, raisedHandTimestamp: enabled ? Date.now() : 0 @@ -636,7 +641,7 @@ export function raiseHand(enabled) { * participant: Object * }} */ -export function raiseHandUpdateQueue(participant) { +export function raiseHandUpdateQueue(participant: Participant) { return { type: RAISE_HAND_UPDATED, participant @@ -652,7 +657,7 @@ export function raiseHandUpdateQueue(participant) { * level: number * }} */ -export function localParticipantAudioLevelChanged(level) { +export function localParticipantAudioLevelChanged(level: number) { return { type: LOCAL_PARTICIPANT_AUDIO_LEVEL_CHANGED, level @@ -666,7 +671,7 @@ export function localParticipantAudioLevelChanged(level) { * @param {string} name - New participant name. * @returns {Object} */ -export function overwriteParticipantName(id, name) { +export function overwriteParticipantName(id: string, name: string) { return { type: OVERWRITE_PARTICIPANT_NAME, id, @@ -680,7 +685,7 @@ export function overwriteParticipantName(id, name) { * @param {Array} participantList - The list of participants to overwrite. * @returns {Object} */ -export function overwriteParticipantsNames(participantList) { +export function overwriteParticipantsNames(participantList: Participant[]) { return { type: OVERWRITE_PARTICIPANTS_NAMES, participantList @@ -697,7 +702,7 @@ export function overwriteParticipantsNames(participantList) { * recording: boolean * }} */ -export function updateLocalRecordingStatus(recording, onlySelf) { +export function updateLocalRecordingStatus(recording: boolean, onlySelf: boolean) { return { type: SET_LOCAL_PARTICIPANT_RECORDING_STATUS, recording, diff --git a/react/features/base/participants/functions.js b/react/features/base/participants/functions.ts similarity index 87% rename from react/features/base/participants/functions.js rename to react/features/base/participants/functions.ts index b056060b3..ae41b1efe 100644 --- a/react/features/base/participants/functions.js +++ b/react/features/base/participants/functions.ts @@ -1,35 +1,42 @@ -// @flow - +/* eslint-disable lines-around-comment */ +// @ts-ignore import { getGravatarURL } from '@jitsi/js-utils/avatar'; -import type { Store } from 'redux'; -import { i18next } from '../../base/i18n'; +import { IStore } from '../../app/types'; +// @ts-ignore import { isStageFilmstripAvailable } from '../../filmstrip/functions'; -import { GRAVATAR_BASE_URL, isCORSAvatarURL } from '../avatar'; +import { GRAVATAR_BASE_URL } from '../avatar/constants'; +import { isCORSAvatarURL } from '../avatar/functions'; +// @ts-ignore import { getMultipleVideoSupportFeatureFlag, getSourceNameSignalingFeatureFlag } from '../config'; +import i18next from '../i18n/i18next'; import { JitsiParticipantConnectionStatus, JitsiTrackStreamingStatus } from '../lib-jitsi-meet'; +// @ts-ignore import { shouldRenderVideoTrack } from '../media'; -import { toState } from '../redux'; +import { toState } from '../redux/functions'; +// @ts-ignore import { getScreenShareTrack, getVideoTrackByParticipant } from '../tracks'; -import { createDeferred } from '../util'; +import { createDeferred } from '../util/helpers'; import { JIGASI_PARTICIPANT_ICON, MAX_DISPLAY_NAME_LENGTH, PARTICIPANT_ROLE } from './constants'; +// @ts-ignore import { preloadImage } from './preloadImage'; +import { Participant } from './reducer'; /** * Temp structures for avatar urls to be checked/preloaded. */ -const AVATAR_QUEUE = []; +const AVATAR_QUEUE: Object[] = []; const AVATAR_CHECKED_URLS = new Map(); /* eslint-disable arrow-body-style, no-unused-vars */ const AVATAR_CHECKER_FUNCTIONS = [ - (participant, _) => { + (participant: Participant) => { return participant && participant.isJigasi ? JIGASI_PARTICIPANT_ICON : null; }, - (participant, _) => { + (participant: Participant) => { return participant && participant.avatarURL ? participant.avatarURL : null; }, - (participant, store) => { + (participant: Participant, store: IStore) => { const config = store.getState()['features/base/config']; const isGravatarDisabled = config.gravatar?.disabled; @@ -54,7 +61,7 @@ const AVATAR_CHECKER_FUNCTIONS = [ * retrieve the state. * @returns {Array} */ -export function getActiveSpeakersToBeDisplayed(stateful: Object | Function) { +export function getActiveSpeakersToBeDisplayed(stateful: IStore | Function) { const state = toState(stateful); const { fakeParticipants, @@ -76,7 +83,7 @@ export function getActiveSpeakersToBeDisplayed(stateful: Object | Function) { if (sortedRemoteVirtualScreenshareParticipants) { availableSlotsForActiveSpeakers -= sortedRemoteVirtualScreenshareParticipants.size * 2; for (const screenshare of Array.from(sortedRemoteVirtualScreenshareParticipants.keys())) { - const ownerId = getVirtualScreenshareParticipantOwnerId(screenshare); + const ownerId = getVirtualScreenshareParticipantOwnerId(screenshare as string); activeSpeakers.delete(ownerId); } @@ -94,7 +101,7 @@ export function getActiveSpeakersToBeDisplayed(stateful: Object | Function) { } const truncatedSpeakersList = Array.from(activeSpeakers).slice(0, availableSlotsForActiveSpeakers); - truncatedSpeakersList.sort((a, b) => a[1].localeCompare(b[1])); + truncatedSpeakersList.sort((a: any, b: any) => a[1].localeCompare(b[1])); return new Map(truncatedSpeakersList); } @@ -106,14 +113,14 @@ export function getActiveSpeakersToBeDisplayed(stateful: Object | Function) { * @param {Store} store - Redux store. * @returns {Promise} */ -export function getFirstLoadableAvatarUrl(participant: Object, store: Store) { - const deferred = createDeferred(); +export function getFirstLoadableAvatarUrl(participant: Participant, store: IStore) { + const deferred: any = createDeferred(); const fullPromise = deferred.promise .then(() => _getFirstLoadableAvatarUrl(participant, store)) - .then(result => { + .then((result: any) => { if (AVATAR_QUEUE.length) { - const next = AVATAR_QUEUE.shift(); + const next: any = AVATAR_QUEUE.shift(); next.resolve(); } @@ -138,7 +145,7 @@ export function getFirstLoadableAvatarUrl(participant: Object, store: Store} - The Map with fake participants. */ -export function getFakeParticipants(stateful: Object | Function) { +export function getFakeParticipants(stateful: IStore | Function) { return toState(stateful)['features/base/participants'].fakeParticipants; } @@ -283,7 +290,7 @@ export function getFakeParticipants(stateful: Object | Function) { * features/base/participants. * @returns {number} */ -export function getRemoteParticipantCount(stateful: Object | Function) { +export function getRemoteParticipantCount(stateful: IStore | Function) { const state = toState(stateful)['features/base/participants']; if (getMultipleVideoSupportFeatureFlag(state)) { @@ -302,7 +309,7 @@ export function getRemoteParticipantCount(stateful: Object | Function) { * features/base/participants. * @returns {number} */ -export function getParticipantCountWithFake(stateful: Object | Function) { +export function getParticipantCountWithFake(stateful: IStore | Function) { const state = toState(stateful); const { local, localScreenShare, remote } = state['features/base/participants']; @@ -321,7 +328,7 @@ export function getParticipantCountWithFake(stateful: Object | Function) { * @param {string} id - The ID of the participant's display name to retrieve. * @returns {string} */ -export function getParticipantDisplayName(stateful: Object | Function, id: string) { +export function getParticipantDisplayName(stateful: IStore | Function, id: string): string { const participant = getParticipantById(stateful, id); const { defaultLocalDisplayName, @@ -353,7 +360,7 @@ export function getParticipantDisplayName(stateful: Object | Function, id: strin * @param {string} id - The ID of the screenshare participant's display name to retrieve. * @returns {string} */ -export function getScreenshareParticipantDisplayName(stateful: Object | Function, id: string) { +export function getScreenshareParticipantDisplayName(stateful: IStore | Function, id: string) { const ownerDisplayName = getParticipantDisplayName(stateful, getVirtualScreenshareParticipantOwnerId(id)); return i18next.t('screenshareDisplayName', { name: ownerDisplayName }); @@ -368,7 +375,7 @@ export function getScreenshareParticipantDisplayName(stateful: Object | Function * @returns {string} - The presence status. */ export function getParticipantPresenceStatus( - stateful: Object | Function, id: string) { + stateful: IStore | Function, id: string) { if (!id) { return undefined; } @@ -388,7 +395,7 @@ export function getParticipantPresenceStatus( * {@code getState} function to be used to retrieve the state. * @returns {boolean} */ -export function haveParticipantWithScreenSharingFeature(stateful: Object | Function) { +export function haveParticipantWithScreenSharingFeature(stateful: IStore | Function) { return toState(stateful)['features/base/participants'].haveParticipantWithScreenSharingFeature; } @@ -400,7 +407,7 @@ export function haveParticipantWithScreenSharingFeature(stateful: Object | Funct * features/base/participants. * @returns {Map} */ -export function getRemoteParticipants(stateful: Object | Function) { +export function getRemoteParticipants(stateful: IStore | Function) { return toState(stateful)['features/base/participants'].remote; } @@ -411,7 +418,7 @@ export function getRemoteParticipants(stateful: Object | Function) { * retrieve the state features/filmstrip. * @returns {Array} */ -export function getRemoteParticipantsSorted(stateful: Object | Function) { +export function getRemoteParticipantsSorted(stateful: IStore | Function) { return toState(stateful)['features/filmstrip'].remoteParticipants; } @@ -423,14 +430,14 @@ export function getRemoteParticipantsSorted(stateful: Object | Function) { * features/base/participants. * @returns {(Participant|undefined)} */ -export function getPinnedParticipant(stateful: Object | Function) { +export function getPinnedParticipant(stateful: IStore | Function) { const state = toState(stateful); const { pinnedParticipant } = state['features/base/participants']; const stageFilmstrip = isStageFilmstripAvailable(state); if (stageFilmstrip) { const { activeParticipants } = state['features/filmstrip']; - const id = activeParticipants.find(p => p.pinned)?.participantId; + const id = activeParticipants.find((p: Participant) => p.pinned)?.participantId; return id ? getParticipantById(stateful, id) : undefined; } @@ -448,7 +455,7 @@ export function getPinnedParticipant(stateful: Object | Function) { * @param {string} participant - Participant object. * @returns {boolean} */ -export function isParticipantModerator(participant: Object) { +export function isParticipantModerator(participant?: Participant) { return participant?.role === PARTICIPANT_ROLE.MODERATOR; } @@ -459,7 +466,7 @@ export function isParticipantModerator(participant: Object) { * {@code getState} function to be used to retrieve the state features/base/participants. * @returns {Participant} - The participant from the redux store. */ -export function getDominantSpeakerParticipant(stateful: Object | Function) { +export function getDominantSpeakerParticipant(stateful: IStore | Function) { const state = toState(stateful)['features/base/participants']; const { dominantSpeaker } = state; @@ -477,7 +484,7 @@ export function getDominantSpeakerParticipant(stateful: Object | Function) { * to the Redux state. * @returns {boolean} */ -export function isEveryoneModerator(stateful: Object | Function) { +export function isEveryoneModerator(stateful: IStore | Function) { const state = toState(stateful)['features/base/participants']; return state.everyoneIsModerator === true; @@ -489,7 +496,7 @@ export function isEveryoneModerator(stateful: Object | Function) { * @param {?string | ?Object} icon - The icon to check. * @returns {boolean} */ -export function isIconUrl(icon: ?string | ?Object) { +export function isIconUrl(icon?: string | Object) { return Boolean(icon) && (typeof icon === 'object' || typeof icon === 'function'); } @@ -501,7 +508,7 @@ export function isIconUrl(icon: ?string | ?Object) { * to the Redux state. * @returns {boolean} */ -export function isLocalParticipantModerator(stateful: Object | Function) { +export function isLocalParticipantModerator(stateful: IStore | Function) { const state = toState(stateful)['features/base/participants']; const { local } = state; @@ -522,7 +529,7 @@ export function isLocalParticipantModerator(stateful: Object | Function) { * @param {string} id - The ID of the participant. * @returns {boolean} */ -export function shouldRenderParticipantVideo(stateful: Object | Function, id: string) { +export function shouldRenderParticipantVideo(stateful: IStore | Function, id: string) { const state = toState(stateful); const participant = getParticipantById(state, id); @@ -577,7 +584,7 @@ export function shouldRenderParticipantVideo(stateful: Object | Function, id: st * @param {Store} store - Redux store. * @returns {?string} */ -async function _getFirstLoadableAvatarUrl(participant, store) { +async function _getFirstLoadableAvatarUrl(participant: Participant, store: IStore) { for (let i = 0; i < AVATAR_CHECKER_FUNCTIONS.length; i++) { const url = AVATAR_CHECKER_FUNCTIONS[i](participant, store); @@ -626,7 +633,7 @@ async function _getFirstLoadableAvatarUrl(participant, store) { * features/base/participants. * @returns {Array} */ -export function getRaiseHandsQueue(stateful: Object | Function): Array { +export function getRaiseHandsQueue(stateful: IStore | Function): Array { const { raisedHandsQueue } = toState(stateful)['features/base/participants']; return raisedHandsQueue; @@ -638,6 +645,6 @@ export function getRaiseHandsQueue(stateful: Object | Function): Array { * @param {Object} participant - The participant. * @returns {boolean} - Whether participant has raise hand or not. */ -export function hasRaisedHand(participant: Object): boolean { +export function hasRaisedHand(participant: Participant): boolean { return Boolean(participant && participant.raisedHandTimestamp); } diff --git a/react/features/base/participants/logger.js b/react/features/base/participants/logger.ts similarity index 91% rename from react/features/base/participants/logger.js rename to react/features/base/participants/logger.ts index 46a9b8b8f..a4277a9b3 100644 --- a/react/features/base/participants/logger.js +++ b/react/features/base/participants/logger.ts @@ -1,5 +1,3 @@ -// @flow - import { getLogger } from '../logging/functions'; export default getLogger('features/base/participants'); diff --git a/react/features/base/participants/reducer.ts b/react/features/base/participants/reducer.ts index 93cbd80cb..de311daa1 100644 --- a/react/features/base/participants/reducer.ts +++ b/react/features/base/participants/reducer.ts @@ -38,7 +38,7 @@ import { isParticipantModerator } from './functions'; * @property {string} email - Participant email. */ -interface Participant { +export interface Participant { avatarURL?: string; botType?: string; conference?: Object; @@ -58,9 +58,11 @@ interface Participant { loadableAvatarUrl?: string; loadableAvatarUrlUseCORS?: boolean; local?: boolean; - name: string; + name?: string; pinned?: boolean; presence?: string; + raisedHandTimestamp?: number; + remoteControlSessionStatus?: boolean; role?: string; supportsRemoteControl?: boolean; } @@ -349,7 +351,7 @@ ReducerRegistry.register('features/base/participants', (state: IParticipantsStat if (isVirtualScreenshareParticipant) { const sortedRemoteVirtualScreenshareParticipants = [ ...state.sortedRemoteVirtualScreenshareParticipants ]; - sortedRemoteVirtualScreenshareParticipants.push([ id, name ]); + sortedRemoteVirtualScreenshareParticipants.push([ id, name ?? '' ]); sortedRemoteVirtualScreenshareParticipants.sort((a, b) => a[1].localeCompare(b[1])); state.sortedRemoteVirtualScreenshareParticipants = new Map(sortedRemoteVirtualScreenshareParticipants); diff --git a/react/features/conference/components/native/carmode/TitleBar.tsx b/react/features/conference/components/native/carmode/TitleBar.tsx index 7108d1f61..63480d711 100644 --- a/react/features/conference/components/native/carmode/TitleBar.tsx +++ b/react/features/conference/components/native/carmode/TitleBar.tsx @@ -9,8 +9,7 @@ import { getConferenceName } from '../../../../base/conference/functions'; import { getFeatureFlag, MEETING_NAME_ENABLED } from '../../../../base/flags'; // @ts-ignore import { JitsiRecordingConstants } from '../../../../base/lib-jitsi-meet'; -// @ts-ignore -import { getLocalParticipant } from '../../../../base/participants'; +import { getLocalParticipant } from '../../../../base/participants/functions'; import { connect } from '../../../../base/redux/functions'; // @ts-ignore import ConnectionIndicator from '../../../../connection-indicator/components/native/ConnectionIndicator'; diff --git a/react/features/display-name/components/native/DisplayNameLabel.tsx b/react/features/display-name/components/native/DisplayNameLabel.tsx index 0ef50e808..328e000a6 100644 --- a/react/features/display-name/components/native/DisplayNameLabel.tsx +++ b/react/features/display-name/components/native/DisplayNameLabel.tsx @@ -4,8 +4,6 @@ import { Text, View } from 'react-native'; import { getParticipantById, getParticipantDisplayName - - // @ts-ignore } from '../../../base/participants/functions'; import { connect } from '../../../base/redux/functions'; diff --git a/react/features/lobby/components/web/LobbySection.tsx b/react/features/lobby/components/web/LobbySection.tsx index 9cfea3c8a..72da0ab4d 100644 --- a/react/features/lobby/components/web/LobbySection.tsx +++ b/react/features/lobby/components/web/LobbySection.tsx @@ -3,8 +3,7 @@ import React, { PureComponent } from 'react'; // @ts-ignore import { translate } from '../../../base/i18n'; -// @ts-ignore -import { isLocalParticipantModerator } from '../../../base/participants'; +import { isLocalParticipantModerator } from '../../../base/participants/functions'; import { connect } from '../../../base/redux/functions'; import Switch from '../../../base/ui/components/web/Switch'; // @ts-ignore diff --git a/react/features/participants-pane/components/breakout-rooms/components/web/RoomParticipantContextMenu.tsx b/react/features/participants-pane/components/breakout-rooms/components/web/RoomParticipantContextMenu.tsx index b2963dec0..b188d9e49 100644 --- a/react/features/participants-pane/components/breakout-rooms/components/web/RoomParticipantContextMenu.tsx +++ b/react/features/participants-pane/components/breakout-rooms/components/web/RoomParticipantContextMenu.tsx @@ -9,9 +9,7 @@ import { Avatar } from '../../../../../base/avatar'; // @ts-ignore import { ContextMenu, ContextMenuItemGroup } from '../../../../../base/components'; - -// @ts-ignore -import { isLocalParticipantModerator } from '../../../../../base/participants'; +import { isLocalParticipantModerator } from '../../../../../base/participants/functions'; import { Theme } from '../../../../../base/ui/types'; // @ts-ignore diff --git a/react/features/prejoin/components/Prejoin.native.tsx b/react/features/prejoin/components/Prejoin.native.tsx index 4f6fbf57c..d55aaf1ac 100644 --- a/react/features/prejoin/components/Prejoin.native.tsx +++ b/react/features/prejoin/components/Prejoin.native.tsx @@ -21,8 +21,7 @@ import { connect } from '../../base/connection/actions.native'; import { IconClose } from '../../base/icons/svg/index'; // @ts-ignore import JitsiScreen from '../../base/modal/components/JitsiScreen'; -// @ts-ignore -import { getLocalParticipant } from '../../base/participants'; +import { getLocalParticipant } from '../../base/participants/functions'; // @ts-ignore import { getFieldValue } from '../../base/react'; // @ts-ignore @@ -60,7 +59,7 @@ const Prejoin: React.FC = ({ navigation }: PrejoinProps) => { const aspectRatio = useSelector( (state: any) => state['features/base/responsive-ui']?.aspectRatio ); - const localParticipant = useSelector(state => getLocalParticipant(state)); + const localParticipant = useSelector((state: any) => getLocalParticipant(state)); const isDisplayNameMandatory = useSelector(state => isDisplayNameRequired(state)); const participantName = localParticipant?.name; const [ displayName, setDisplayName ] diff --git a/react/features/reactions/components/web/ReactionsMenu.tsx b/react/features/reactions/components/web/ReactionsMenu.tsx index 4314ea9bf..4eee14bee 100644 --- a/react/features/reactions/components/web/ReactionsMenu.tsx +++ b/react/features/reactions/components/web/ReactionsMenu.tsx @@ -17,9 +17,8 @@ import { isMobileBrowser } from '../../../base/environment/utils'; // @ts-ignore import { translate } from '../../../base/i18n'; - -// @ts-ignore -import { getLocalParticipant, hasRaisedHand, raiseHand } from '../../../base/participants'; +import { getLocalParticipant, hasRaisedHand } from '../../../base/participants/functions'; +import { raiseHand } from '../../../base/participants/actions'; import { connect } from '../../../base/redux/functions'; import { Theme } from '../../../base/ui/types'; diff --git a/react/features/reactions/functions.any.ts b/react/features/reactions/functions.any.ts index 9fc94ed2d..118a6e73f 100644 --- a/react/features/reactions/functions.any.ts +++ b/react/features/reactions/functions.any.ts @@ -3,9 +3,7 @@ import { v4 as uuidv4 } from 'uuid'; // @ts-ignore import { getFeatureFlag, REACTIONS_ENABLED } from '../base/flags'; - -// @ts-ignore -import { getLocalParticipant } from '../base/participants'; +import { getLocalParticipant } from '../base/participants/functions'; // @ts-ignore import { extractFqnFromPath } from '../dynamic-branding/functions.any'; diff --git a/react/features/reactions/middleware.ts b/react/features/reactions/middleware.ts index c30c8565d..01265b8fe 100644 --- a/react/features/reactions/middleware.ts +++ b/react/features/reactions/middleware.ts @@ -17,9 +17,7 @@ import { getParticipantById, getParticipantCount, isLocalParticipantModerator - - // @ts-ignore -} from '../base/participants'; +} from '../base/participants/functions'; import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; import { SETTINGS_UPDATED } from '../base/settings/actionTypes'; @@ -264,11 +262,11 @@ function _onMuteReactionsCommand(attributes: MuteCommandAttributes = {}, id: str // The Command(s) API will send us our own commands and we don't want // to act upon them. - if (participantSendingCommand.local) { + if (participantSendingCommand?.local) { return; } - if (participantSendingCommand.role !== 'moderator') { + if (participantSendingCommand?.role !== 'moderator') { logger.warn('Received mute-reactions command not from moderator'); return; diff --git a/react/features/security/components/security-dialog/web/SecurityDialog.tsx b/react/features/security/components/security-dialog/web/SecurityDialog.tsx index a2886b4a9..49868b621 100644 --- a/react/features/security/components/security-dialog/web/SecurityDialog.tsx +++ b/react/features/security/components/security-dialog/web/SecurityDialog.tsx @@ -6,8 +6,7 @@ import { connect } from 'react-redux'; import { setPassword as setPass } from '../../../../base/conference'; // @ts-ignore import { Dialog } from '../../../../base/dialog'; -// @ts-ignore -import { isLocalParticipantModerator } from '../../../../base/participants'; +import { isLocalParticipantModerator } from '../../../../base/participants/functions'; // @ts-ignore import { E2EESection } from '../../../../e2ee/components'; // @ts-ignore diff --git a/react/features/video-menu/components/web/LocalVideoMenuTriggerButton.tsx b/react/features/video-menu/components/web/LocalVideoMenuTriggerButton.tsx index a9a3b72c9..50873424d 100644 --- a/react/features/video-menu/components/web/LocalVideoMenuTriggerButton.tsx +++ b/react/features/video-menu/components/web/LocalVideoMenuTriggerButton.tsx @@ -12,10 +12,7 @@ import { isMobileBrowser } from '../../../base/environment/utils'; // @ts-ignore import { translate } from '../../../base/i18n'; import { IconHorizontalPoints } from '../../../base/icons/svg/index'; -import { - getLocalParticipant - // @ts-ignore -} from '../../../base/participants'; +import { getLocalParticipant } from '../../../base/participants/functions'; // @ts-ignore import { Popover } from '../../../base/popover'; // @ts-ignore diff --git a/react/features/video-menu/components/web/RemoteVideoMenuTriggerButton.tsx b/react/features/video-menu/components/web/RemoteVideoMenuTriggerButton.tsx index 8e215f828..b9fa8dad7 100644 --- a/react/features/video-menu/components/web/RemoteVideoMenuTriggerButton.tsx +++ b/react/features/video-menu/components/web/RemoteVideoMenuTriggerButton.tsx @@ -7,8 +7,7 @@ import { isMobileBrowser } from '../../../base/environment/utils'; // @ts-ignore import { translate } from '../../../base/i18n'; import { IconHorizontalPoints } from '../../../base/icons/svg/index'; -// @ts-ignore -import { getParticipantById } from '../../../base/participants'; +import { getParticipantById } from '../../../base/participants/functions'; // @ts-ignore import { Popover } from '../../../base/popover'; // @ts-ignore @@ -268,7 +267,7 @@ class RemoteVideoMenuTriggerButton extends Component { function _mapStateToProps(state: any, ownProps: Partial) { const { participantID, thumbnailType } = ownProps; let _remoteControlState = null; - const participant = getParticipantById(state, participantID); + const participant = getParticipantById(state, participantID ?? ''); const _participantDisplayName = participant?.name; const _isRemoteControlSessionActive = participant?.remoteControlSessionStatus ?? false; const _supportsRemoteControl = participant?.supportsRemoteControl ?? false;