From 643cc2db8115062b097b6163c9cbfe23144fbdf1 Mon Sep 17 00:00:00 2001 From: Robert Pintilii Date: Wed, 23 Nov 2022 11:12:26 +0200 Subject: [PATCH] ref(TS) Convert some features to TS (#12591) --- globals.d.ts | 1 + react/features/base/conference/functions.ts | 8 +-- react/features/base/conference/reducer.ts | 6 +- react/features/base/tracks/functions.any.ts | 2 +- .../web/StageParticipantNameLabel.tsx | 5 +- .../{actions.js => actions.ts} | 0 .../{middleware.js => middleware.ts} | 9 +-- .../{actions.any.js => actions.any.ts} | 24 +++---- .../{actions.native.js => actions.native.ts} | 2 - .../{actions.web.js => actions.web.ts} | 22 +++--- react/features/large-video/functions.js | 15 ---- react/features/large-video/functions.ts | 14 ++++ .../large-video/{logger.js => logger.ts} | 2 - .../{middleware.js => middleware.ts} | 15 ++-- ...scriber.native.js => subscriber.native.ts} | 0 .../{subscriber.web.js => subscriber.web.ts} | 9 ++- .../lobby/{actions.any.js => actions.any.ts} | 71 +++++++++---------- .../{actions.native.js => actions.native.ts} | 5 +- .../lobby/{actions.web.js => actions.web.ts} | 11 +-- .../lobby/{functions.js => functions.ts} | 26 +++---- react/features/lobby/{logger.js => logger.ts} | 2 - .../lobby/{middleware.js => middleware.ts} | 64 +++++++++-------- react/features/lobby/reducer.ts | 6 +- react/features/lobby/{sounds.js => sounds.ts} | 0 react/features/lobby/types.ts | 5 ++ .../{functions.js => functions.ts} | 4 +- .../{middleware.js => middleware.tsx} | 16 ++--- .../components/web/LobbyParticipants.tsx | 4 +- .../{hooks.ts => hooks.web.ts} | 8 +-- tsconfig.native.json | 1 + 30 files changed, 166 insertions(+), 191 deletions(-) rename react/features/keyboard-shortcuts/{actions.js => actions.ts} (100%) rename react/features/keyboard-shortcuts/{middleware.js => middleware.ts} (69%) rename react/features/large-video/{actions.any.js => actions.any.ts} (90%) rename react/features/large-video/{actions.native.js => actions.native.ts} (75%) rename react/features/large-video/{actions.web.js => actions.web.ts} (86%) delete mode 100644 react/features/large-video/functions.js create mode 100644 react/features/large-video/functions.ts rename react/features/large-video/{logger.js => logger.ts} (91%) rename react/features/large-video/{middleware.js => middleware.ts} (83%) rename react/features/large-video/{subscriber.native.js => subscriber.native.ts} (100%) rename react/features/large-video/{subscriber.web.js => subscriber.web.ts} (85%) rename react/features/lobby/{actions.any.js => actions.any.ts} (81%) rename react/features/lobby/{actions.native.js => actions.native.ts} (76%) rename react/features/lobby/{actions.web.js => actions.web.ts} (66%) rename react/features/lobby/{functions.js => functions.ts} (70%) rename react/features/lobby/{logger.js => logger.ts} (90%) rename react/features/lobby/{middleware.js => middleware.ts} (89%) rename react/features/lobby/{sounds.js => sounds.ts} (100%) create mode 100644 react/features/lobby/types.ts rename react/features/old-client-notification/{functions.js => functions.ts} (88%) rename react/features/old-client-notification/{middleware.js => middleware.tsx} (73%) rename react/features/participants-pane/{hooks.ts => hooks.web.ts} (93%) diff --git a/globals.d.ts b/globals.d.ts index e61ea3118d..604799444b 100644 --- a/globals.d.ts +++ b/globals.d.ts @@ -13,6 +13,7 @@ declare global { keyboardshortcut: { registerShortcut: Function; unregisterShortcut: Function; + openDialog: Function; } }; const interfaceConfig: any; diff --git a/react/features/base/conference/functions.ts b/react/features/base/conference/functions.ts index e5b5e5d3db..8ff73c5b73 100644 --- a/react/features/base/conference/functions.ts +++ b/react/features/base/conference/functions.ts @@ -454,18 +454,18 @@ export function sendLocalParticipant( name } = getLocalParticipant(stateful) ?? {}; - avatarURL && conference.sendCommand(AVATAR_URL_COMMAND, { + avatarURL && conference?.sendCommand(AVATAR_URL_COMMAND, { value: avatarURL }); - email && conference.sendCommand(EMAIL_COMMAND, { + email && conference?.sendCommand(EMAIL_COMMAND, { value: email }); if (features && features['screen-sharing'] === 'true') { - conference.setLocalParticipantProperty('features_screen-sharing', true); + conference?.setLocalParticipantProperty('features_screen-sharing', true); } - conference.setDisplayName(name); + conference?.setDisplayName(name); } /** diff --git a/react/features/base/conference/reducer.ts b/react/features/base/conference/reducer.ts index 46d888add8..a79d338b86 100644 --- a/react/features/base/conference/reducer.ts +++ b/react/features/base/conference/reducer.ts @@ -65,6 +65,7 @@ export interface IJitsiConference { isStartAudioMuted: Function; isStartVideoMuted: Function; join: Function; + joinLobby: Function; kickParticipant: Function; lock: Function; muteParticipant: Function; @@ -104,7 +105,7 @@ export interface IConferenceState { leaving?: Object; localSubject?: string; locked?: string; - membersOnly?: Object; + membersOnly?: IJitsiConference; obfuscatedRoom?: string; obfuscatedRoomSource?: string; p2p?: Object; @@ -227,7 +228,8 @@ function _authStatusChanged(state: IConferenceState, * @returns {Object} The new state of the feature base/conference after the * reduction of the specified action. */ -function _conferenceFailed(state: IConferenceState, { conference, error }: { conference: Object; error: Error; }) { +function _conferenceFailed(state: IConferenceState, { conference, error }: { + conference: IJitsiConference; error: Error; }) { // The current (similar to getCurrentConference in // base/conference/functions.any.js) conference which is joining or joined: const conference_ = state.conference || state.joining; diff --git a/react/features/base/tracks/functions.any.ts b/react/features/base/tracks/functions.any.ts index 1490a27bee..0e681da469 100644 --- a/react/features/base/tracks/functions.any.ts +++ b/react/features/base/tracks/functions.any.ts @@ -214,7 +214,7 @@ export function getVideoTrackByParticipant( export function getTrackByMediaTypeAndParticipant( tracks: ITrack[], mediaType: MediaType, - participantId: string) { + participantId?: string) { return tracks.find( t => Boolean(t.jitsiTrack) && t.participantId === participantId && t.mediaType === mediaType ); diff --git a/react/features/display-name/components/web/StageParticipantNameLabel.tsx b/react/features/display-name/components/web/StageParticipantNameLabel.tsx index fe829a0187..6e574366b4 100644 --- a/react/features/display-name/components/web/StageParticipantNameLabel.tsx +++ b/react/features/display-name/components/web/StageParticipantNameLabel.tsx @@ -11,7 +11,6 @@ import { getParticipantDisplayName, isWhiteboardParticipant } from '../../../base/participants/functions'; -import { IParticipant } from '../../../base/participants/types'; import { withPixelLineHeight } from '../../../base/styles/functions.web'; // @ts-ignore import { getLargeVideoParticipant } from '../../../large-video/functions'; @@ -50,9 +49,9 @@ const useStyles = makeStyles()(theme => { */ const StageParticipantNameLabel = () => { const { classes, cx } = useStyles(); - const largeVideoParticipant: IParticipant = useSelector(getLargeVideoParticipant); + const largeVideoParticipant = useSelector(getLargeVideoParticipant); const selectedId = largeVideoParticipant?.id; - const nameToDisplay = useSelector((state: IReduxState) => getParticipantDisplayName(state, selectedId)); + const nameToDisplay = useSelector((state: IReduxState) => getParticipantDisplayName(state, selectedId ?? '')); const localParticipant = useSelector(getLocalParticipant); const localId = localParticipant?.id; diff --git a/react/features/keyboard-shortcuts/actions.js b/react/features/keyboard-shortcuts/actions.ts similarity index 100% rename from react/features/keyboard-shortcuts/actions.js rename to react/features/keyboard-shortcuts/actions.ts diff --git a/react/features/keyboard-shortcuts/middleware.js b/react/features/keyboard-shortcuts/middleware.ts similarity index 69% rename from react/features/keyboard-shortcuts/middleware.js rename to react/features/keyboard-shortcuts/middleware.ts index 951cf63ea8..95bb3ef51d 100644 --- a/react/features/keyboard-shortcuts/middleware.js +++ b/react/features/keyboard-shortcuts/middleware.ts @@ -1,19 +1,14 @@ -// @flow - -import { MiddlewareRegistry } from '../base/redux'; +import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; import { OPEN_KEYBOARD_SHORTCUTS_DIALOG } from './actionTypes'; -declare var APP: Object; - /** * Implements the middleware of the feature keyboard-shortcuts. * * @param {Store} store - The redux store. * @returns {Function} */ -// eslint-disable-next-line no-unused-vars -MiddlewareRegistry.register(store => next => action => { +MiddlewareRegistry.register(_store => next => action => { switch (action.type) { case OPEN_KEYBOARD_SHORTCUTS_DIALOG: if (typeof APP === 'object') { diff --git a/react/features/large-video/actions.any.js b/react/features/large-video/actions.any.ts similarity index 90% rename from react/features/large-video/actions.any.js rename to react/features/large-video/actions.any.ts index 9fb04026e2..4bf2c3eba7 100644 --- a/react/features/large-video/actions.any.js +++ b/react/features/large-video/actions.any.ts @@ -1,8 +1,5 @@ -// @flow - -import type { Dispatch } from 'redux'; - -import { MEDIA_TYPE } from '../base/media'; +import { IReduxState, IStore } from '../app/types'; +import { MEDIA_TYPE } from '../base/media/constants'; import { getDominantSpeakerParticipant, getLocalParticipant, @@ -10,9 +7,10 @@ import { getPinnedParticipant, getRemoteParticipants, getVirtualScreenshareParticipantByOwnerId -} from '../base/participants'; +} from '../base/participants/functions'; +import { ITrack } from '../base/tracks/types'; import { isStageFilmstripAvailable } from '../filmstrip/functions'; -import { getAutoPinSetting } from '../video-layout'; +import { getAutoPinSetting } from '../video-layout/functions'; import { SELECT_LARGE_VIDEO_PARTICIPANT, @@ -30,8 +28,8 @@ import { * displayed on the large video. * @returns {Function} */ -export function selectParticipantInLargeVideo(participant: ?string) { - return (dispatch: Dispatch, getState: Function) => { +export function selectParticipantInLargeVideo(participant?: string) { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const state = getState(); if (isStageFilmstripAvailable(state, 2)) { @@ -48,7 +46,7 @@ export function selectParticipantInLargeVideo(participant: ?string) { const remoteScreenShares = state['features/video-layout'].remoteScreenShares; let latestScreenshareParticipantId; - if (remoteScreenShares && remoteScreenShares.length) { + if (remoteScreenShares?.length) { latestScreenshareParticipantId = remoteScreenShares[remoteScreenShares.length - 1]; } @@ -94,7 +92,7 @@ export function updateKnownLargeVideoResolution(resolution: number) { * width: number * }} */ -export function setLargeVideoDimensions(height, width) { +export function setLargeVideoDimensions(height: number, width: number) { return { type: SET_LARGE_VIDEO_DIMENSIONS, height, @@ -109,7 +107,7 @@ export function setLargeVideoDimensions(height, width) { * @private * @returns {(Track|undefined)} */ -function _electLastVisibleRemoteVideo(tracks) { +function _electLastVisibleRemoteVideo(tracks: ITrack[]) { // First we try to get most recent remote video track. for (let i = tracks.length - 1; i >= 0; --i) { const track = tracks[i]; @@ -129,7 +127,7 @@ function _electLastVisibleRemoteVideo(tracks) { * @private * @returns {(string|undefined)} */ -function _electParticipantInLargeVideo(state) { +function _electParticipantInLargeVideo(state: IReduxState) { // If a participant is pinned, they will be shown in the LargeVideo (regardless of whether they are local or // remote) when the filmstrip on stage is disabled. let participant = getPinnedParticipant(state); diff --git a/react/features/large-video/actions.native.js b/react/features/large-video/actions.native.ts similarity index 75% rename from react/features/large-video/actions.native.js rename to react/features/large-video/actions.native.ts index 7e5279fe73..02b37d475d 100644 --- a/react/features/large-video/actions.native.js +++ b/react/features/large-video/actions.native.ts @@ -1,3 +1 @@ -// @flow - export * from './actions.any'; diff --git a/react/features/large-video/actions.web.js b/react/features/large-video/actions.web.ts similarity index 86% rename from react/features/large-video/actions.web.js rename to react/features/large-video/actions.web.ts index 4e9743e21e..a35a6f09ae 100644 --- a/react/features/large-video/actions.web.js +++ b/react/features/large-video/actions.web.ts @@ -1,10 +1,8 @@ -// @flow - -import type { Dispatch } from 'redux'; - +// @ts-expect-error import VideoLayout from '../../../modules/UI/videolayout/VideoLayout'; -import { MEDIA_TYPE } from '../base/media'; -import { getTrackByMediaTypeAndParticipant } from '../base/tracks'; +import { IStore } from '../app/types'; +import { MEDIA_TYPE } from '../base/media/constants'; +import { getTrackByMediaTypeAndParticipant } from '../base/tracks/functions.web'; import { SET_SEE_WHAT_IS_BEING_SHARED, UPDATE_LAST_LARGE_VIDEO_MEDIA_EVENT } from './actionTypes'; @@ -16,7 +14,7 @@ export * from './actions.any'; * @returns {Function} */ export function captureLargeVideoScreenshot() { - return (dispatch: Dispatch, getState: Function): Promise => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const state = getState(); const largeVideo = state['features/large-video']; const promise = Promise.resolve(); @@ -28,7 +26,7 @@ export function captureLargeVideoScreenshot() { const participantTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, largeVideo.participantId); // Participants that join the call video muted do not have a jitsiTrack attached. - if (!(participantTrack && participantTrack.jitsiTrack)) { + if (!participantTrack?.jitsiTrack) { return promise; } const videoStream = participantTrack.jitsiTrack.getOriginalStream(); @@ -39,7 +37,7 @@ export function captureLargeVideoScreenshot() { // Get the video element for the large video, cast HTMLElement to HTMLVideoElement to make flow happy. /* eslint-disable-next-line no-extra-parens*/ - const videoElement = ((document.getElementById('largeVideo'): any): HTMLVideoElement); + const videoElement = (document.getElementById('largeVideo') as any); if (!videoElement) { return promise; @@ -54,11 +52,11 @@ export function captureLargeVideoScreenshot() { canvasElement.style.display = 'none'; canvasElement.height = parseInt(height, 10); canvasElement.width = parseInt(width, 10); - ctx.drawImage(videoElement, 0, 0); + ctx?.drawImage(videoElement, 0, 0); const dataURL = canvasElement.toDataURL('image/png', 1.0); // Cleanup. - ctx.clearRect(0, 0, canvasElement.width, canvasElement.height); + ctx?.clearRect(0, 0, canvasElement.width, canvasElement.height); canvasElement.remove(); return Promise.resolve(dataURL); @@ -73,7 +71,7 @@ export function captureLargeVideoScreenshot() { * @returns {Function} */ export function resizeLargeVideo(width: number, height: number) { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const state = getState(); const largeVideo = state['features/large-video']; diff --git a/react/features/large-video/functions.js b/react/features/large-video/functions.js deleted file mode 100644 index e14bfbddc9..0000000000 --- a/react/features/large-video/functions.js +++ /dev/null @@ -1,15 +0,0 @@ -// @flow - -import { getParticipantById } from '../base/participants'; - -/** - * Selector for the participant currently displaying on the large video. - * - * @param {Object} state - The redux state. - * @returns {Object} - */ -export function getLargeVideoParticipant(state: Object) { - const { participantId } = state['features/large-video']; - - return getParticipantById(state, participantId); -} diff --git a/react/features/large-video/functions.ts b/react/features/large-video/functions.ts new file mode 100644 index 0000000000..e326585111 --- /dev/null +++ b/react/features/large-video/functions.ts @@ -0,0 +1,14 @@ +import { IReduxState } from '../app/types'; +import { getParticipantById } from '../base/participants/functions'; + +/** + * Selector for the participant currently displaying on the large video. + * + * @param {Object} state - The redux state. + * @returns {Object} + */ +export function getLargeVideoParticipant(state: IReduxState) { + const { participantId } = state['features/large-video']; + + return getParticipantById(state, participantId ?? ''); +} diff --git a/react/features/large-video/logger.js b/react/features/large-video/logger.ts similarity index 91% rename from react/features/large-video/logger.js rename to react/features/large-video/logger.ts index 173fafbf62..261c6c9a94 100644 --- a/react/features/large-video/logger.js +++ b/react/features/large-video/logger.ts @@ -1,5 +1,3 @@ -// @flow - import { getLogger } from '../base/logging/functions'; export default getLogger('features/large-video'); diff --git a/react/features/large-video/middleware.js b/react/features/large-video/middleware.ts similarity index 83% rename from react/features/large-video/middleware.js rename to react/features/large-video/middleware.ts index 6ab55f46bd..ccbad268fc 100644 --- a/react/features/large-video/middleware.js +++ b/react/features/large-video/middleware.ts @@ -1,19 +1,16 @@ -// @flow - import { DOMINANT_SPEAKER_CHANGED, PARTICIPANT_JOINED, PARTICIPANT_LEFT, - PIN_PARTICIPANT, - getDominantSpeakerParticipant, - getLocalParticipant -} from '../base/participants'; -import { MiddlewareRegistry } from '../base/redux'; -import { isTestModeEnabled } from '../base/testing'; + PIN_PARTICIPANT +} from '../base/participants/actionTypes'; +import { getDominantSpeakerParticipant, getLocalParticipant } from '../base/participants/functions'; +import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; +import { isTestModeEnabled } from '../base/testing/functions'; import { TRACK_ADDED, TRACK_REMOVED -} from '../base/tracks'; +} from '../base/tracks/actionTypes'; import { TOGGLE_DOCUMENT_EDITING } from '../etherpad/actionTypes'; import { selectParticipantInLargeVideo } from './actions'; diff --git a/react/features/large-video/subscriber.native.js b/react/features/large-video/subscriber.native.ts similarity index 100% rename from react/features/large-video/subscriber.native.js rename to react/features/large-video/subscriber.native.ts diff --git a/react/features/large-video/subscriber.web.js b/react/features/large-video/subscriber.web.ts similarity index 85% rename from react/features/large-video/subscriber.web.js rename to react/features/large-video/subscriber.web.ts index a92b603bf6..f165b7cbdd 100644 --- a/react/features/large-video/subscriber.web.js +++ b/react/features/large-video/subscriber.web.ts @@ -1,8 +1,7 @@ -// @flow - +// @ts-expect-error import VideoLayout from '../../../modules/UI/videolayout/VideoLayout'; -import { StateListenerRegistry } from '../base/redux'; -import { getVideoTrackByParticipant } from '../base/tracks'; +import StateListenerRegistry from '../base/redux/StateListenerRegistry'; +import { getVideoTrackByParticipant } from '../base/tracks/functions.web'; import { getLargeVideoParticipant } from './functions'; @@ -29,7 +28,7 @@ StateListenerRegistry.register( streamingStatus: videoTrack?.streamingStatus }; }, - /* listener */ ({ participantId, streamingStatus }, previousState = {}) => { + /* listener */ ({ participantId, streamingStatus }, previousState: any = {}) => { if (streamingStatus !== previousState.streamingStatus) { VideoLayout.updateLargeVideo(participantId, true); } diff --git a/react/features/lobby/actions.any.js b/react/features/lobby/actions.any.ts similarity index 81% rename from react/features/lobby/actions.any.js rename to react/features/lobby/actions.any.ts index 43488d241b..5b35131f8a 100644 --- a/react/features/lobby/actions.any.js +++ b/react/features/lobby/actions.any.ts @@ -1,19 +1,13 @@ -// @flow - -import { type Dispatch } from 'redux'; - -import { - conferenceWillJoin, - getCurrentConference, - sendLocalParticipant, - setPassword -} from '../base/conference'; -import { getLocalParticipant } from '../base/participants'; +import { IStore } from '../app/types'; +import { conferenceWillJoin, setPassword } from '../base/conference/actions'; +import { getCurrentConference, sendLocalParticipant } from '../base/conference/functions'; +import { getLocalParticipant } from '../base/participants/functions'; +import { IParticipant } from '../base/participants/types'; import { onLobbyChatInitialized, removeLobbyChatParticipant, sendMessage } from '../chat/actions.any'; import { LOBBY_CHAT_MESSAGE } from '../chat/constants'; import { handleLobbyMessageReceived } from '../chat/middleware'; -import { LOBBY_NOTIFICATION_ID, hideNotification } from '../notifications'; -import { showNotification } from '../notifications/actions'; +import { hideNotification, showNotification } from '../notifications/actions'; +import { LOBBY_NOTIFICATION_ID } from '../notifications/constants'; import { KNOCKING_PARTICIPANT_ARRIVED_OR_UPDATED, @@ -27,6 +21,7 @@ import { } from './actionTypes'; import { LOBBY_CHAT_INITIALIZED, MODERATOR_IN_CHAT_WITH_LEFT } from './constants'; import { getKnockingParticipants, getLobbyEnabled } from './functions'; +import { IKnockingParticipant } from './types'; /** * Tries to join with a preset password. @@ -35,7 +30,7 @@ import { getKnockingParticipants, getLobbyEnabled } from './functions'; * @returns {Function} */ export function joinWithPassword(password: string) { - return async (dispatch: Dispatch, getState: Function) => { + return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const conference = getCurrentConference(getState); dispatch(setPassword(conference, conference.join, password)); @@ -67,7 +62,7 @@ export function knockingParticipantLeft(id: string) { * type: KNOCKING_PARTICIPANT_ARRIVED_OR_UPDATED * }} */ -export function participantIsKnockingOrUpdated(participant: Object) { +export function participantIsKnockingOrUpdated(participant: IKnockingParticipant | Object) { return { participant, type: KNOCKING_PARTICIPANT_ARRIVED_OR_UPDATED @@ -82,7 +77,7 @@ export function participantIsKnockingOrUpdated(participant: Object) { * @returns {Function} */ export function answerKnockingParticipant(id: string, approved: boolean) { - return async (dispatch: Dispatch) => { + return async (dispatch: IStore['dispatch']) => { dispatch(setKnockingParticipantApproval(id, approved)); dispatch(hideNotification(LOBBY_NOTIFICATION_ID)); }; @@ -96,7 +91,7 @@ export function answerKnockingParticipant(id: string, approved: boolean) { * @returns {Function} */ export function setKnockingParticipantApproval(id: string, approved: boolean) { - return async (dispatch: Dispatch, getState: Function) => { + return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const conference = getCurrentConference(getState); if (conference) { @@ -115,8 +110,8 @@ export function setKnockingParticipantApproval(id: string, approved: boolean) { * @param {Array} participants - A list of knocking participants. * @returns {void} */ -export function admitMultiple(participants: Array) { - return (dispatch: Function, getState: Function) => { +export function admitMultiple(participants: Array) { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const conference = getCurrentConference(getState); participants.forEach(p => { @@ -132,10 +127,10 @@ export function admitMultiple(participants: Array) { * @returns {Function} */ export function approveKnockingParticipant(id: string) { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const conference = getCurrentConference(getState); - conference && conference.lobbyApproveAccess(id); + conference?.lobbyApproveAccess(id); }; } @@ -146,10 +141,10 @@ export function approveKnockingParticipant(id: string) { * @returns {Function} */ export function rejectKnockingParticipant(id: string) { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const conference = getCurrentConference(getState); - conference && conference.lobbyDenyAccess(id); + conference?.lobbyDenyAccess(id); }; } @@ -207,18 +202,20 @@ export function setPasswordJoinFailed(failed: boolean) { * @returns {Function} */ export function startKnocking() { - return async (dispatch: Dispatch, getState: Function) => { + return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const state = getState(); const { membersOnly } = state['features/base/conference']; const localParticipant = getLocalParticipant(state); + // @ts-ignore dispatch(conferenceWillJoin(membersOnly)); // We need to update the conference object with the current display name, if approved // we want to send that display name, it was not updated in case when pre-join is disabled + // @ts-ignore sendLocalParticipant(state, membersOnly); - membersOnly.joinLobby(localParticipant.name, localParticipant.email); + membersOnly?.joinLobby(localParticipant?.name, localParticipant?.email); dispatch(setLobbyMessageListener()); dispatch(setKnockingState(true)); }; @@ -231,7 +228,7 @@ export function startKnocking() { * @returns {Function} */ export function toggleLobbyMode(enabled: boolean) { - return async (dispatch: Dispatch, getState: Function) => { + return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const conference = getCurrentConference(getState); if (enabled) { @@ -275,8 +272,8 @@ export function hideLobbyScreen() { * * @returns {Promise} */ -export function handleLobbyChatInitialized(payload: Object) { - return async (dispatch: Dispatch, getState: Function) => { +export function handleLobbyChatInitialized(payload: { attendee: IParticipant; moderator: IParticipant; }) { + return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const state = getState(); const conference = getCurrentConference(state); @@ -296,8 +293,8 @@ export function handleLobbyChatInitialized(payload: Object) { dispatch(showNotification({ titleKey: 'lobby.lobbyChatStartedNotification', titleArguments: { - moderator: payload.moderator.name, - attendee: payload.attendee.name + moderator: payload.moderator.name ?? '', + attendee: payload.attendee.name ?? '' } })); } @@ -312,7 +309,7 @@ export function handleLobbyChatInitialized(payload: Object) { * @returns {Promise} */ export function onSendMessage(message: string) { - return async (dispatch: Dispatch) => { + return async (dispatch: IStore['dispatch']) => { dispatch(sendMessage(message)); }; } @@ -325,7 +322,7 @@ export function onSendMessage(message: string) { * @returns {Promise} */ export function sendLobbyChatMessage(message: Object) { - return async (dispatch: Dispatch, getState: Function) => { + return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const conference = getCurrentConference(getState); conference.sendLobbyMessage(message); @@ -338,7 +335,7 @@ export function sendLobbyChatMessage(message: Object) { * @returns {Function} */ export function maybeSetLobbyChatMessageListener() { - return async (dispatch: Dispatch, getState: Function) => { + return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const state = getState(); const lobbyEnabled = getLobbyEnabled(state); @@ -355,7 +352,7 @@ export function maybeSetLobbyChatMessageListener() { * @returns {Function} */ export function updateLobbyParticipantOnLeave(participantId: string) { - return async (dispatch: Dispatch, getState: Function) => { + return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const state = getState(); const { knocking, knockingParticipants } = state['features/lobby']; const { lobbyMessageRecipient } = state['features/chat']; @@ -370,7 +367,7 @@ export function updateLobbyParticipantOnLeave(participantId: string) { const participantToNotify = knockingParticipants.find(p => p.chattingWithModerator === participantId); if (participantToNotify) { - conference.sendLobbyMessage({ + conference?.sendLobbyMessage({ type: MODERATOR_IN_CHAT_WITH_LEFT, moderatorId: participantToNotify.chattingWithModerator }, participantToNotify.id); @@ -389,7 +386,7 @@ export function updateLobbyParticipantOnLeave(participantId: string) { * @returns {Function} */ export function setLobbyMessageListener() { - return async (dispatch: Dispatch, getState: Function) => { + return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const state = getState(); const conference = getCurrentConference(state); const { enableLobbyChat = true } = state['features/base/config']; @@ -398,7 +395,7 @@ export function setLobbyMessageListener() { return; } - conference.addLobbyMessageListener((message: Object, participantId: string) => { + conference.addLobbyMessageListener((message: any, participantId: string) => { if (message.type === LOBBY_CHAT_MESSAGE) { return dispatch(handleLobbyMessageReceived(message.message, participantId)); } diff --git a/react/features/lobby/actions.native.js b/react/features/lobby/actions.native.ts similarity index 76% rename from react/features/lobby/actions.native.js rename to react/features/lobby/actions.native.ts index b8528f9733..862cbcd91c 100644 --- a/react/features/lobby/actions.native.js +++ b/react/features/lobby/actions.native.ts @@ -1,6 +1,7 @@ import { batch } from 'react-redux'; -import { appNavigate } from '../app/actions'; +import { appNavigate } from '../app/actions.native'; +import { IStore } from '../app/types'; import { hideLobbyScreen, setKnockingState } from './actions.any'; @@ -12,7 +13,7 @@ export * from './actions.any'; * @returns {Function} */ export function cancelKnocking() { - return dispatch => { + return (dispatch: IStore['dispatch']) => { batch(() => { dispatch(setKnockingState(false)); dispatch(hideLobbyScreen()); diff --git a/react/features/lobby/actions.web.js b/react/features/lobby/actions.web.ts similarity index 66% rename from react/features/lobby/actions.web.js rename to react/features/lobby/actions.web.ts index 63d4b07f00..94cfe76082 100644 --- a/react/features/lobby/actions.web.js +++ b/react/features/lobby/actions.web.ts @@ -1,20 +1,15 @@ -// @flow - -import { type Dispatch } from 'redux'; - -import { maybeRedirectToWelcomePage } from '../app/actions'; +import { maybeRedirectToWelcomePage } from '../app/actions.web'; +import { IStore } from '../app/types'; export * from './actions.any'; -declare var APP: Object; - /** * Cancels the ongoing knocking and abandons the join flow. * * @returns {Function} */ export function cancelKnocking() { - return async (dispatch: Dispatch) => { + return async (dispatch: IStore['dispatch']) => { // when we are redirecting the library should handle any // unload and clean of the connection. APP.API.notifyReadyToClose(); diff --git a/react/features/lobby/functions.js b/react/features/lobby/functions.ts similarity index 70% rename from react/features/lobby/functions.js rename to react/features/lobby/functions.ts index b04fefffa8..1c3fb11656 100644 --- a/react/features/lobby/functions.js +++ b/react/features/lobby/functions.ts @@ -1,44 +1,46 @@ -// @flow +import { IReduxState } from '../app/types'; +import { getCurrentConference } from '../base/conference/functions'; + +import { IKnockingParticipant } from './types'; -import { getCurrentConference } from '../base/conference'; /** * Selector to return lobby enable state. * -* @param {any} state - State object. +* @param {IReduxState} state - State object. * @returns {boolean} */ -export function getLobbyEnabled(state: any) { +export function getLobbyEnabled(state: IReduxState) { return state['features/lobby'].lobbyEnabled; } /** * Selector to return a list of knocking participants. * -* @param {any} state - State object. +* @param {IReduxState} state - State object. * @returns {Array} */ -export function getKnockingParticipants(state: any) { +export function getKnockingParticipants(state: IReduxState) { return state['features/lobby'].knockingParticipants; } /** * Selector to return lobby visibility. * - * @param {any} state - State object. + * @param {IReduxState} state - State object. * @returns {any} */ -export function getIsLobbyVisible(state: any) { +export function getIsLobbyVisible(state: IReduxState) { return state['features/lobby'].lobbyVisible; } /** * Selector to return array with knocking participant ids. * - * @param {any} state - State object. + * @param {IReduxState} state - State object. * @returns {Array} */ -export function getKnockingParticipantsById(state: any) { +export function getKnockingParticipantsById(state: IReduxState) { return getKnockingParticipants(state).map(participant => participant.id); } @@ -50,9 +52,9 @@ export function getKnockingParticipantsById(state: any) { * @returns {Function} */ export function showLobbyChatButton( - participant: Object + participant: IKnockingParticipant ) { - return function(state: Object) { + return function(state: IReduxState) { const { enableLobbyChat = true } = state['features/base/config']; const { lobbyMessageRecipient, isLobbyChatActive } = state['features/chat']; diff --git a/react/features/lobby/logger.js b/react/features/lobby/logger.ts similarity index 90% rename from react/features/lobby/logger.js rename to react/features/lobby/logger.ts index 964c0263da..28acff891d 100644 --- a/react/features/lobby/logger.js +++ b/react/features/lobby/logger.ts @@ -1,5 +1,3 @@ -// @flow - import { getLogger } from '../base/logging/functions'; export default getLogger('features/lobby'); diff --git a/react/features/lobby/middleware.js b/react/features/lobby/middleware.ts similarity index 89% rename from react/features/lobby/middleware.js rename to react/features/lobby/middleware.ts index 184f8baa67..abb379e809 100644 --- a/react/features/lobby/middleware.js +++ b/react/features/lobby/middleware.ts @@ -1,39 +1,41 @@ -// @flow - import i18n from 'i18next'; import { batch } from 'react-redux'; +import { AnyAction } from 'redux'; -import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app'; -import { - CONFERENCE_FAILED, - CONFERENCE_JOINED, - conferenceWillJoin -} from '../base/conference'; +import { IStore } from '../app/types'; +import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app/actionTypes'; +import { CONFERENCE_FAILED, CONFERENCE_JOINED } from '../base/conference/actionTypes'; +import { conferenceWillJoin } from '../base/conference/actions'; import { JitsiConferenceErrors, JitsiConferenceEvents } from '../base/lib-jitsi-meet'; -import { getFirstLoadableAvatarUrl, getParticipantDisplayName } from '../base/participants'; -import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux'; -import { playSound, registerSound, unregisterSound } from '../base/sounds'; -import { isTestModeEnabled } from '../base/testing'; +import { getFirstLoadableAvatarUrl, getParticipantDisplayName } from '../base/participants/functions'; +import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; +import StateListenerRegistry from '../base/redux/StateListenerRegistry'; +import { playSound, registerSound, unregisterSound } from '../base/sounds/actions'; +import { isTestModeEnabled } from '../base/testing/functions'; import { handleLobbyChatInitialized, removeLobbyChatParticipant } from '../chat/actions.any'; -import { approveKnockingParticipant, rejectKnockingParticipant } from '../lobby/actions'; +import { + hideNotification, + showNotification +} from '../notifications/actions'; import { LOBBY_NOTIFICATION_ID, NOTIFICATION_ICON, NOTIFICATION_TIMEOUT_TYPE, - NOTIFICATION_TYPE, - hideNotification, - showNotification -} from '../notifications'; + NOTIFICATION_TYPE +} from '../notifications/constants'; +import { INotificationProps } from '../notifications/types'; import { open as openParticipantsPane } from '../participants-pane/actions'; import { getParticipantsPaneOpen } from '../participants-pane/functions'; import { shouldAutoKnock } from '../prejoin/functions'; import { KNOCKING_PARTICIPANT_ARRIVED_OR_UPDATED, KNOCKING_PARTICIPANT_LEFT } from './actionTypes'; import { + approveKnockingParticipant, hideLobbyScreen, knockingParticipantLeft, openLobbyScreen, participantIsKnockingOrUpdated, + rejectKnockingParticipant, setLobbyMessageListener, setLobbyModeEnabled, setPasswordJoinFailed, @@ -43,8 +45,7 @@ import { updateLobbyParticipantOnLeave } from './actions.any'; import { KNOCKING_PARTICIPANT_SOUND_ID } from './constants'; import { getKnockingParticipants, showLobbyChatButton } from './functions'; import { KNOCKING_PARTICIPANT_FILE } from './sounds'; - -declare var APP: Object; +import { IKnockingParticipant } from './types'; MiddlewareRegistry.register(store => next => action => { switch (action.type) { @@ -88,14 +89,14 @@ StateListenerRegistry.register( state => state['features/base/conference'].conference, (conference, { dispatch, getState }, previousConference) => { if (conference && !previousConference) { - conference.on(JitsiConferenceEvents.MEMBERS_ONLY_CHANGED, enabled => { + conference.on(JitsiConferenceEvents.MEMBERS_ONLY_CHANGED, (enabled: boolean) => { dispatch(setLobbyModeEnabled(enabled)); if (enabled) { dispatch(setLobbyMessageListener()); } }); - conference.on(JitsiConferenceEvents.LOBBY_USER_JOINED, (id, name) => { + conference.on(JitsiConferenceEvents.LOBBY_USER_JOINED, (id: string, name: string) => { const { soundsParticipantKnocking } = getState()['features/base/settings']; batch(() => { @@ -180,7 +181,7 @@ StateListenerRegistry.register( }); }); - conference.on(JitsiConferenceEvents.LOBBY_USER_UPDATED, (id, participant) => { + conference.on(JitsiConferenceEvents.LOBBY_USER_UPDATED, (id: string, participant: IKnockingParticipant) => { dispatch( participantIsKnockingOrUpdated({ ...participant, @@ -189,7 +190,7 @@ StateListenerRegistry.register( ); }); - conference.on(JitsiConferenceEvents.LOBBY_USER_LEFT, id => { + conference.on(JitsiConferenceEvents.LOBBY_USER_LEFT, (id: string) => { batch(() => { dispatch(knockingParticipantLeft(id)); dispatch(removeLobbyChatParticipant()); @@ -197,7 +198,7 @@ StateListenerRegistry.register( }); }); - conference.on(JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED, (origin, sender) => + conference.on(JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED, (origin: any, sender: any) => _maybeSendLobbyNotification(origin, sender, { dispatch, getState @@ -213,7 +214,7 @@ StateListenerRegistry.register( * @param {Object} store - The Redux store. * @returns {void} */ -function _handleLobbyNotification(store) { +function _handleLobbyNotification(store: IStore) { const { dispatch, getState } = store; const knockingParticipants = getKnockingParticipants(getState()); @@ -275,7 +276,7 @@ function _handleLobbyNotification(store) { * @param {Object} action - The Redux action. * @returns {Object} */ -function _conferenceFailed({ dispatch, getState }, next, action) { +function _conferenceFailed({ dispatch, getState }: IStore, next: Function, action: AnyAction) { const { error } = action; const state = getState(); const { membersOnly } = state['features/base/conference']; @@ -296,6 +297,7 @@ function _conferenceFailed({ dispatch, getState }, next, action) { // In case of wrong password we need to be in the right state if in the meantime someone allows us to join if (nonFirstFailure) { + // @ts-ignore dispatch(conferenceWillJoin(membersOnly)); } @@ -328,7 +330,7 @@ function _conferenceFailed({ dispatch, getState }, next, action) { * @param {Object} action - The Redux action. * @returns {Object} */ -function _conferenceJoined({ dispatch }, next, action) { +function _conferenceJoined({ dispatch }: IStore, next: Function, action: AnyAction) { dispatch(hideLobbyScreen()); return next(action); @@ -341,13 +343,13 @@ function _conferenceJoined({ dispatch }, next, action) { * @param {Object} participant - The knocking participant. * @returns {void} */ -function _findLoadableAvatarForKnockingParticipant(store, { id }) { +function _findLoadableAvatarForKnockingParticipant(store: IStore, { id }: { id: string; }) { const { dispatch, getState } = store; const updatedParticipant = getState()['features/lobby'].knockingParticipants.find(p => p.id === id); const { disableThirdPartyRequests } = getState()['features/base/config']; if (!disableThirdPartyRequests && updatedParticipant && !updatedParticipant.loadableAvatarUrl) { - getFirstLoadableAvatarUrl(updatedParticipant, store).then(result => { + getFirstLoadableAvatarUrl(updatedParticipant, store).then((result: { isUsingCORS: boolean; src: string; }) => { if (result) { const { isUsingCORS, src } = result; @@ -372,12 +374,12 @@ function _findLoadableAvatarForKnockingParticipant(store, { id }) { * @param {Object} store - The Redux store. * @returns {void} */ -function _maybeSendLobbyNotification(origin, message, { dispatch, getState }) { +function _maybeSendLobbyNotification(origin: any, message: any, { dispatch, getState }: IStore) { if (!origin?._id || message?.type !== 'lobby-notify') { return; } - const notificationProps: any = { + const notificationProps: INotificationProps = { descriptionArguments: { originParticipantName: getParticipantDisplayName(getState, origin._id), targetParticipantName: message.name diff --git a/react/features/lobby/reducer.ts b/react/features/lobby/reducer.ts index c7283612fb..a2d494a6da 100644 --- a/react/features/lobby/reducer.ts +++ b/react/features/lobby/reducer.ts @@ -1,5 +1,4 @@ import { CONFERENCE_JOINED, CONFERENCE_LEFT, SET_PASSWORD } from '../base/conference/actionTypes'; -import { IParticipant } from '../base/participants/types'; import ReducerRegistry from '../base/redux/ReducerRegistry'; import { @@ -12,6 +11,7 @@ import { SET_LOBBY_VISIBILITY, SET_PASSWORD_JOIN_FAILED } from './actionTypes'; +import { IKnockingParticipant } from './types'; const DEFAULT_STATE = { knocking: false, @@ -21,10 +21,6 @@ const DEFAULT_STATE = { passwordJoinFailed: false }; -interface IKnockingParticipant extends IParticipant { - chattingWithModerator?: string; -} - export interface ILobbyState { knocking: boolean; knockingParticipants: IKnockingParticipant[]; diff --git a/react/features/lobby/sounds.js b/react/features/lobby/sounds.ts similarity index 100% rename from react/features/lobby/sounds.js rename to react/features/lobby/sounds.ts diff --git a/react/features/lobby/types.ts b/react/features/lobby/types.ts new file mode 100644 index 0000000000..ffef42ab96 --- /dev/null +++ b/react/features/lobby/types.ts @@ -0,0 +1,5 @@ +import { IParticipant } from '../base/participants/types'; + +export interface IKnockingParticipant extends IParticipant { + chattingWithModerator?: string; +} diff --git a/react/features/old-client-notification/functions.js b/react/features/old-client-notification/functions.ts similarity index 88% rename from react/features/old-client-notification/functions.js rename to react/features/old-client-notification/functions.ts index 07a85e221b..cd6d26f2ac 100644 --- a/react/features/old-client-notification/functions.js +++ b/react/features/old-client-notification/functions.ts @@ -1,6 +1,4 @@ -// @flow - -import { browser } from '../../../react/features/base/lib-jitsi-meet'; +import { browser } from '../base/lib-jitsi-meet'; /** * Returns true if Jitsi Meet is running in too old jitsi-meet-electron app and false otherwise. diff --git a/react/features/old-client-notification/middleware.js b/react/features/old-client-notification/middleware.tsx similarity index 73% rename from react/features/old-client-notification/middleware.js rename to react/features/old-client-notification/middleware.tsx index 3a734a1b81..9906d9720a 100644 --- a/react/features/old-client-notification/middleware.js +++ b/react/features/old-client-notification/middleware.tsx @@ -1,16 +1,16 @@ -// @flow - import React from 'react'; +import { AnyAction } from 'redux'; -import { APP_WILL_MOUNT } from '../base/app'; -import { MiddlewareRegistry } from '../base/redux'; -import { NOTIFICATION_TIMEOUT_TYPE, showErrorNotification } from '../notifications'; +import { IStore } from '../app/types'; +import { APP_WILL_MOUNT } from '../base/app/actionTypes'; +import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; +import { showErrorNotification } from '../notifications/actions'; +import { NOTIFICATION_TIMEOUT_TYPE } from '../notifications/constants'; +// @ts-ignore import { OldElectronAPPNotificationDescription } from './components'; import { isOldJitsiMeetElectronApp } from './functions'; -declare var interfaceConfig: Object; - MiddlewareRegistry.register(store => next => action => { switch (action.type) { case APP_WILL_MOUNT: @@ -29,7 +29,7 @@ MiddlewareRegistry.register(store => next => action => { * @private * @returns {Object} The new state that is the result of the reduction of the specified {@code action}. */ -function _appWillMount(store, next, action) { +function _appWillMount(store: IStore, next: Function, action: AnyAction) { if (isOldJitsiMeetElectronApp()) { const { dispatch } = store; diff --git a/react/features/participants-pane/components/web/LobbyParticipants.tsx b/react/features/participants-pane/components/web/LobbyParticipants.tsx index 10c299b2d4..b1399a706a 100644 --- a/react/features/participants-pane/components/web/LobbyParticipants.tsx +++ b/react/features/participants-pane/components/web/LobbyParticipants.tsx @@ -9,9 +9,7 @@ import { Avatar } from '../../../base/avatar'; import Icon from '../../../base/icons/components/Icon'; import { IconCheck, IconCloseLarge } from '../../../base/icons/svg'; import { withPixelLineHeight } from '../../../base/styles/functions.web'; -// @ts-ignore import { admitMultiple } from '../../../lobby/actions.web'; -// @ts-ignore import { getKnockingParticipants, getLobbyEnabled } from '../../../lobby/functions'; // @ts-ignore import { Drawer, JitsiPortal } from '../../../toolbox/components/web'; @@ -72,7 +70,7 @@ const useStyles = makeStyles()(theme => { */ export default function LobbyParticipants() { const lobbyEnabled = useSelector(getLobbyEnabled); - const participants: Array = useSelector(getKnockingParticipants); + const participants = useSelector(getKnockingParticipants); const { t } = useTranslation(); const { classes } = useStyles(); const dispatch = useDispatch(); diff --git a/react/features/participants-pane/hooks.ts b/react/features/participants-pane/hooks.web.ts similarity index 93% rename from react/features/participants-pane/hooks.ts rename to react/features/participants-pane/hooks.web.ts index ef4a6cb31a..3a6788c279 100644 --- a/react/features/participants-pane/hooks.ts +++ b/react/features/participants-pane/hooks.web.ts @@ -2,9 +2,7 @@ import { useCallback, useState } from 'react'; import { useDispatch } from 'react-redux'; import { handleLobbyChatInitialized } from '../chat/actions.any'; -// eslint-disable-next-line lines-around-comment -// @ts-ignore -import { approveKnockingParticipant, rejectKnockingParticipant } from '../lobby/actions'; +import { approveKnockingParticipant, rejectKnockingParticipant } from '../lobby/actions.web'; interface IDrawerParticipant { displayName?: string; @@ -24,12 +22,12 @@ export function useLobbyActions(participant?: IDrawerParticipant | null, closeDr return [ useCallback(e => { e.stopPropagation(); - dispatch(approveKnockingParticipant(participant?.participantID)); + dispatch(approveKnockingParticipant(participant?.participantID ?? '')); closeDrawer?.(); }, [ dispatch, closeDrawer ]), useCallback(() => { - dispatch(rejectKnockingParticipant(participant?.participantID)); + dispatch(rejectKnockingParticipant(participant?.participantID ?? '')); closeDrawer?.(); }, [ dispatch, closeDrawer ]), diff --git a/tsconfig.native.json b/tsconfig.native.json index 59db91e8e4..f18551c015 100644 --- a/tsconfig.native.json +++ b/tsconfig.native.json @@ -26,6 +26,7 @@ "react/features/feedback", "react/features/no-audio-signal", "react/features/noise-suppression", + "react/features/old-client-notification", "react/features/screen-share", "react/features/stream-effects/noise-suppression", "react/features/stream-effects/rnnoise",