diff --git a/react/features/base/conference/reducer.ts b/react/features/base/conference/reducer.ts index 361c0c6b1..3d95bb856 100644 --- a/react/features/base/conference/reducer.ts +++ b/react/features/base/conference/reducer.ts @@ -44,9 +44,13 @@ export interface IJitsiConference { addTrack: Function; getBreakoutRooms: Function; getLocalTracks: Function; + grantOwner: Function; isAVModerationSupported: Function; isEndConferenceSupported: Function; isLobbySupported: Function; + kickParticipant: Function; + muteParticipant: Function; + on: Function; removeTrack: Function; sendCommand: Function; sendEndpointMessage: Function; diff --git a/react/features/base/config/configType.ts b/react/features/base/config/configType.ts index 93636905d..9930bef56 100644 --- a/react/features/base/config/configType.ts +++ b/react/features/base/config/configType.ts @@ -67,7 +67,7 @@ type ButtonsWithNotifyClick = 'camera' | 'add-passcode' | '__end'; -type Sounds = 'ASKED_TO_UNMUTE_SOUND' | +export type Sounds = 'ASKED_TO_UNMUTE_SOUND' | 'E2EE_OFF_SOUND' | 'E2EE_ON_SOUND' | 'INCOMING_MSG_SOUND' | diff --git a/react/features/base/participants/actions.ts b/react/features/base/participants/actions.ts index 258ce24b3..8357734e7 100644 --- a/react/features/base/participants/actions.ts +++ b/react/features/base/participants/actions.ts @@ -1,6 +1,4 @@ -import { Dispatch } from 'redux'; - -// @ts-ignore +import { IStore } from '../../app/types'; import { showNotification } from '../../notifications/actions'; import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants'; import { set } from '../redux/functions'; @@ -115,7 +113,7 @@ export function kickParticipant(id: string) { * @returns {Function} */ export function localParticipantConnectionStatusChanged(connectionStatus: string) { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const participant = getLocalParticipant(getState); if (participant) { @@ -135,7 +133,7 @@ export function localParticipantConnectionStatusChanged(connectionStatus: string * @returns {Function} */ export function localParticipantIdChanged(id: string) { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const participant = getLocalParticipant(getState); if (participant) { @@ -171,7 +169,7 @@ export function localParticipantJoined(participant: Participant = { id: '' }) { * @returns {Function} */ export function localParticipantLeft() { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const participant = getLocalParticipant(getState); if (participant) { @@ -201,7 +199,7 @@ export function localParticipantLeft() { * @returns {Function} */ export function localParticipantRoleChanged(role: string) { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const participant = getLocalParticipant(getState); if (participant) { @@ -280,7 +278,7 @@ export function participantJoined(participant: Participant) { 'A remote participant must be associated with a JitsiConference!'); } - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { // 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 @@ -310,7 +308,7 @@ export function participantJoined(participant: Participant) { * }} */ export function updateRemoteParticipantFeatures(jitsiParticipant: any) { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { if (!jitsiParticipant) { return; } @@ -508,7 +506,7 @@ export function participantUpdated(participant: Participant = { id: '' }) { * @returns {Promise} */ export function participantMutedUs(participant: any, track: any) { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { if (!participant) { return; } @@ -532,7 +530,7 @@ export function participantMutedUs(participant: any, track: any) { * @returns {Function} */ export function createVirtualScreenshareParticipant(sourceName: string, local: boolean) { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const state = getState(); const ownerId = getVirtualScreenshareParticipantOwnerId(sourceName); const ownerName = getParticipantDisplayName(state, ownerId); @@ -555,7 +553,7 @@ export function createVirtualScreenshareParticipant(sourceName: string, local: b * @returns {Promise} */ export function participantKicked(kicker: any, kicked: any) { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { dispatch({ type: PARTICIPANT_KICKED, diff --git a/react/features/base/participants/sounds.js b/react/features/base/participants/sounds.ts similarity index 100% rename from react/features/base/participants/sounds.js rename to react/features/base/participants/sounds.ts diff --git a/react/features/base/participants/subscriber.js b/react/features/base/participants/subscriber.ts similarity index 85% rename from react/features/base/participants/subscriber.js rename to react/features/base/participants/subscriber.ts index 68f21fc82..eeb8e2770 100644 --- a/react/features/base/participants/subscriber.js +++ b/react/features/base/participants/subscriber.ts @@ -1,13 +1,12 @@ -// @flow - import _ from 'lodash'; -import { getCurrentConference } from '../conference'; +import { IStore } from '../../app/types'; +import { getCurrentConference } from '../conference/functions'; import { getMultipleVideoSendingSupportFeatureFlag, getMultipleVideoSupportFeatureFlag } from '../config/functions.any'; -import { StateListenerRegistry } from '../redux'; +import StateListenerRegistry from '../redux/StateListenerRegistry'; import { createVirtualScreenshareParticipant, participantLeft } from './actions'; @@ -22,7 +21,7 @@ StateListenerRegistry.register( * @param {*} store - The redux store. * @returns {void} */ -function _updateScreenshareParticipants({ getState, dispatch }) { +function _updateScreenshareParticipants({ getState, dispatch }: IStore) { const state = getState(); if (!getMultipleVideoSupportFeatureFlag(state)) { @@ -36,9 +35,9 @@ function _updateScreenshareParticipants({ getState, dispatch }) { let newLocalSceenshareSourceName; - const currentScreenshareSourceNames = tracks.reduce((acc, track) => { + const currentScreenshareSourceNames = tracks.reduce((acc: string[], track) => { if (track.videoType === 'desktop' && !track.jitsiTrack.isMuted()) { - const sourceName = track.jitsiTrack.getSourceName(); + const sourceName: string = track.jitsiTrack.getSourceName(); if (track.local) { newLocalSceenshareSourceName = sourceName; diff --git a/react/features/base/participants/types.ts b/react/features/base/participants/types.ts index bf699eac5..6e57f703f 100644 --- a/react/features/base/participants/types.ts +++ b/react/features/base/participants/types.ts @@ -15,15 +15,18 @@ export interface Participant { isFakeParticipant?: boolean; isJigasi?: boolean; isLocalScreenShare?: boolean; + isReplaced?: boolean; isReplacing?: number; isVirtualScreenshareParticipant?: boolean; loadableAvatarUrl?: string; loadableAvatarUrlUseCORS?: boolean; local?: boolean; + localRecording?: string; name?: string; pinned?: boolean; presence?: string; raisedHandTimestamp?: number; + region?: string; remoteControlSessionStatus?: boolean; role?: string; supportsRemoteControl?: boolean; diff --git a/react/features/base/popover/functions.web.js b/react/features/base/popover/functions.web.ts similarity index 86% rename from react/features/base/popover/functions.web.js rename to react/features/base/popover/functions.web.ts index 804ec1d0e..fd653aea8 100644 --- a/react/features/base/popover/functions.web.js +++ b/react/features/base/popover/functions.web.ts @@ -1,67 +1,65 @@ -// @flow - const LEFT_RIGHT_OFFSET = 25; const TOP_BOTTOM_OFFSET = 20; -const getLeftAlignedStyle = bounds => { +const getLeftAlignedStyle = (bounds: DOMRect) => { return { position: 'fixed', right: `${window.innerWidth - bounds.x + LEFT_RIGHT_OFFSET}px` }; }; -const getRightAlignedStyle = bounds => { +const getRightAlignedStyle = (bounds: DOMRect) => { return { position: 'fixed', left: `${bounds.x + bounds.width + LEFT_RIGHT_OFFSET}px` }; }; -const getTopAlignedStyle = bounds => { +const getTopAlignedStyle = (bounds: DOMRect) => { return { position: 'fixed', bottom: `${window.innerHeight - bounds.y + TOP_BOTTOM_OFFSET}px` }; }; -const getBottomAlignedStyle = bounds => { +const getBottomAlignedStyle = (bounds: DOMRect) => { return { position: 'fixed', top: `${bounds.y + bounds.height + TOP_BOTTOM_OFFSET}px` }; }; -const getLeftRightStartAlign = (bounds, size) => { +const getLeftRightStartAlign = (bounds: DOMRect, size: DOMRectReadOnly) => { return { top: `${Math.min(bounds.y + 15, window.innerHeight - size.height - 20)}px` }; }; -const getLeftRightMidAlign = (bounds, size) => { +const getLeftRightMidAlign = (bounds: DOMRect, size: DOMRectReadOnly) => { return { bottom: `${window.innerHeight - bounds.y - bounds.height - (size.height / 2)}px` }; }; -const getLeftRightEndAlign = (bounds, size) => { +const getLeftRightEndAlign = (bounds: DOMRect, size: DOMRectReadOnly) => { return { bottom: `${Math.min(window.innerHeight - bounds.y - bounds.height, window.innerHeight - size.height)}px` }; }; -const getTopBotStartAlign = bounds => { +const getTopBotStartAlign = (bounds: DOMRect) => { return { right: `${window.innerWidth - bounds.x + 10}px` }; }; -const getTopBotMidAlign = (bounds, size) => { +const getTopBotMidAlign = (bounds: DOMRect, size: DOMRectReadOnly) => { return { right: `${window.innerWidth - bounds.x - (size.width / 2)}px` }; }; -const getTopBotEndAlign = bounds => { +const getTopBotEndAlign = (bounds: DOMRect) => { return { left: `${bounds.x + bounds.width + 10}px` }; diff --git a/react/features/base/premeeting/functions.js b/react/features/base/premeeting/functions.ts similarity index 94% rename from react/features/base/premeeting/functions.js rename to react/features/base/premeeting/functions.ts index ddedbb7e8..6c2791486 100644 --- a/react/features/base/premeeting/functions.js +++ b/react/features/base/premeeting/functions.ts @@ -1,10 +1,8 @@ -// @flow - import { findIndex } from 'lodash'; -import { CONNECTION_TYPE } from './constants'; +import { IState } from '../../app/types'; -declare var interfaceConfig: Object; +import { CONNECTION_TYPE } from './constants'; const LOSS_AUDIO_THRESHOLDS = [ 0.33, 0.05 ]; const LOSS_VIDEO_THRESHOLDS = [ 0.33, 0.1, 0.05 ]; @@ -90,15 +88,15 @@ export function calculateAvatarDimensions(height: number) { * * @returns {number} */ -function _getLevel(thresholds, value, descending = true) { +function _getLevel(thresholds: number[], value: number, descending = true) { let predicate; if (descending) { - predicate = function(threshold) { + predicate = function(threshold: number) { return value > threshold; }; } else { - predicate = function(threshold) { + predicate = function(threshold: number) { return value < threshold; }; } @@ -123,7 +121,8 @@ function _getLevel(thresholds, value, descending = true) { * connectionDetails: string[] * }} */ -function _getConnectionDataFromTestResults({ fractionalLoss: l, throughput: t }) { +function _getConnectionDataFromTestResults({ fractionalLoss: l, throughput: t }: + { fractionalLoss: number; throughput: number; }) { const loss = { audioQuality: _getLevel(LOSS_AUDIO_THRESHOLDS, l), videoQuality: _getLevel(LOSS_VIDEO_THRESHOLDS, l) @@ -192,7 +191,7 @@ function _getConnectionDataFromTestResults({ fractionalLoss: l, throughput: t }) * connectionDetails: string[] * }} */ -export function getConnectionData(state: Object) { +export function getConnectionData(state: IState) { const { precallTestResults } = state['features/prejoin']; if (precallTestResults) { diff --git a/react/features/base/premeeting/logger.js b/react/features/base/premeeting/logger.ts similarity index 91% rename from react/features/base/premeeting/logger.js rename to react/features/base/premeeting/logger.ts index 1d09c1b7a..81a80b318 100644 --- a/react/features/base/premeeting/logger.js +++ b/react/features/base/premeeting/logger.ts @@ -1,5 +1,3 @@ -// @flow - import { getLogger } from '../logging/functions'; export default getLogger('features/base/premeeting'); diff --git a/react/features/base/react/Platform.native.js b/react/features/base/react/Platform.native.ts similarity index 92% rename from react/features/base/react/Platform.native.js rename to react/features/base/react/Platform.native.ts index 2c5130848..1710b20d3 100644 --- a/react/features/base/react/Platform.native.js +++ b/react/features/base/react/Platform.native.ts @@ -1,5 +1,3 @@ -/* @flow */ - // Re-export react-native's Platform because we want to provide a minimal // equivalent on Web. import { Platform } from 'react-native'; diff --git a/react/features/base/react/functions.js b/react/features/base/react/functions.ts similarity index 76% rename from react/features/base/react/functions.js rename to react/features/base/react/functions.ts index 1180038c3..df627fb70 100644 --- a/react/features/base/react/functions.js +++ b/react/features/base/react/functions.ts @@ -1,11 +1,9 @@ -// @flow - /** * Returns the field value in a platform generic way. * * @param {Object | string} fieldParameter - The parameter passed through the change event function. * @returns {string} */ -export function getFieldValue(fieldParameter: Object | string) { +export function getFieldValue(fieldParameter: { target: { value: string; }; } | string) { return typeof fieldParameter === 'string' ? fieldParameter : fieldParameter?.target?.value; } diff --git a/react/features/base/react/logger.js b/react/features/base/react/logger.ts similarity index 90% rename from react/features/base/react/logger.js rename to react/features/base/react/logger.ts index 18ff002fa..71e0a0f7f 100644 --- a/react/features/base/react/logger.js +++ b/react/features/base/react/logger.ts @@ -1,5 +1,3 @@ -// @flow - import { getLogger } from '../logging/functions'; export default getLogger('features/base/react'); diff --git a/react/features/base/redux/MiddlewareRegistry.ts b/react/features/base/redux/MiddlewareRegistry.ts index 8a97085b9..cb107e0fd 100644 --- a/react/features/base/redux/MiddlewareRegistry.ts +++ b/react/features/base/redux/MiddlewareRegistry.ts @@ -1,6 +1,6 @@ import { applyMiddleware, Middleware } from 'redux'; -import { IState } from '../../app/types'; +import { IState, IStore } from '../../app/types'; /** * A registry for Redux middleware, allowing features to register their @@ -42,7 +42,7 @@ class MiddlewareRegistry { * @param {Middleware} middleware - A Redux middleware. * @returns {void} */ - register(middleware: Middleware) { + register(middleware: Middleware) { this._elements.push(middleware); } } diff --git a/react/features/base/redux/StateListenerRegistry.ts b/react/features/base/redux/StateListenerRegistry.ts index d4d5fb632..d8e27e69a 100644 --- a/react/features/base/redux/StateListenerRegistry.ts +++ b/react/features/base/redux/StateListenerRegistry.ts @@ -1,6 +1,6 @@ import { Store } from 'redux'; -import { IState } from '../../app/types'; +import { IState, IStore } from '../../app/types'; import { equals } from './functions'; import logger from './logger'; @@ -20,7 +20,7 @@ import logger from './logger'; * Immutable! */ type Listener - = (selection: any, store: Store, prevSelection: any) => void; + = (selection: any, store: IStore, prevSelection: any) => void; /** * The type selector supported for registration with diff --git a/react/features/base/responsive-ui/actions.js b/react/features/base/responsive-ui/actions.ts similarity index 89% rename from react/features/base/responsive-ui/actions.js rename to react/features/base/responsive-ui/actions.ts index 1f738fd8a..1232d0bcd 100644 --- a/react/features/base/responsive-ui/actions.js +++ b/react/features/base/responsive-ui/actions.ts @@ -1,8 +1,6 @@ -// @flow - import { batch } from 'react-redux'; -import type { Dispatch } from 'redux'; +import { IStore } from '../../app/types'; import { CHAT_SIZE } from '../../chat/constants'; import { getParticipantsPaneOpen } from '../../participants-pane/functions'; import theme from '../components/themes/participantsPaneTheme.json'; @@ -35,7 +33,7 @@ const REDUCED_UI_THRESHOLD = 300; * @returns {Object} */ export function clientResized(clientWidth: number, clientHeight: number) { - return (dispatch: Dispatch, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { let availableWidth = clientWidth; if (navigator.product !== 'ReactNative') { @@ -74,8 +72,8 @@ export function clientResized(clientWidth: number, clientHeight: number) { * aspectRatio: Symbol * }} */ -export function setAspectRatio(width: number, height: number): Function { - return (dispatch: Dispatch, getState: Function) => { +export function setAspectRatio(width: number, height: number) { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { // Don't change the aspect ratio if width and height are the same, that // is, if we transition to a 1:1 aspect ratio. if (width !== height) { @@ -104,8 +102,8 @@ export function setAspectRatio(width: number, height: number): Function { * reducedUI: boolean * }} */ -export function setReducedUI(width: number, height: number): Function { - return (dispatch: Dispatch, getState: Function) => { +export function setReducedUI(width: number, height: number) { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const reducedUI = Math.min(width, height) < REDUCED_UI_THRESHOLD; if (reducedUI !== getState()['features/base/responsive-ui'].reducedUI) { @@ -139,7 +137,7 @@ export function setParticipantContextMenuOpen(isOpen: boolean) { * insets: Object * }} */ -export function setSafeAreaInsets(insets) { +export function setSafeAreaInsets(insets: Object) { return { type: SAFE_AREA_INSETS_CHANGED, insets diff --git a/react/features/base/responsive-ui/middleware.native.js b/react/features/base/responsive-ui/middleware.native.ts similarity index 91% rename from react/features/base/responsive-ui/middleware.native.js rename to react/features/base/responsive-ui/middleware.native.ts index a7b9bbd25..a3e89bfc7 100644 --- a/react/features/base/responsive-ui/middleware.native.js +++ b/react/features/base/responsive-ui/middleware.native.ts @@ -1,6 +1,4 @@ -// @flow - -import { MiddlewareRegistry } from '../../base/redux'; +import MiddlewareRegistry from '../redux/MiddlewareRegistry'; import { CLIENT_RESIZED } from './actionTypes'; import { setAspectRatio, setReducedUI } from './actions'; diff --git a/react/features/base/responsive-ui/middleware.web.js b/react/features/base/responsive-ui/middleware.web.ts similarity index 78% rename from react/features/base/responsive-ui/middleware.web.js rename to react/features/base/responsive-ui/middleware.web.ts index 9d5109e56..b1b7932b8 100644 --- a/react/features/base/responsive-ui/middleware.web.js +++ b/react/features/base/responsive-ui/middleware.web.ts @@ -1,14 +1,13 @@ -// @flow - -import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app'; -import { MiddlewareRegistry } from '../../base/redux'; +import { IStore } from '../../app/types'; +import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app/actionTypes'; +import MiddlewareRegistry from '../redux/MiddlewareRegistry'; import { clientResized } from './actions'; /** * Dimensions change handler. */ -let handler; +let handler: undefined | ((this: Window, ev: UIEvent) => any); /** * Middleware that handles window dimension changes. @@ -42,7 +41,7 @@ MiddlewareRegistry.register(store => next => action => { * @private * @returns {void} */ -function _appWillMount(store) { +function _appWillMount(store: IStore) { handler = () => { const { innerHeight, @@ -63,7 +62,7 @@ function _appWillMount(store) { * @returns {void} */ function _appWillUnmount() { - window.removeEventListener('resize', handler); + handler && window.removeEventListener('resize', handler); handler = undefined; } diff --git a/react/features/base/sounds/actions.js b/react/features/base/sounds/actions.ts similarity index 94% rename from react/features/base/sounds/actions.js rename to react/features/base/sounds/actions.ts index 4584bc575..1935ae933 100644 --- a/react/features/base/sounds/actions.js +++ b/react/features/base/sounds/actions.ts @@ -1,5 +1,6 @@ -// @flow - +/* eslint-disable lines-around-comment */ +import { Sounds } from '../config/configType'; +// @ts-ignore import type { AudioElement } from '../media'; import { @@ -10,6 +11,7 @@ import { STOP_SOUND, UNREGISTER_SOUND } from './actionTypes'; +// @ts-ignore import { getSoundsPath } from './functions'; import { getDisabledSounds } from './functions.any'; @@ -70,7 +72,7 @@ export function playSound(soundId: string): Object { return (dispatch: Function, getState: Function) => { const disabledSounds = getDisabledSounds(getState()); - if (!disabledSounds.includes(soundId) && !disabledSounds.find(id => soundId.startsWith(id))) { + if (!disabledSounds.includes(soundId as Sounds) && !disabledSounds.find(id => soundId.startsWith(id))) { dispatch({ type: PLAY_SOUND, soundId diff --git a/react/features/base/sounds/functions.any.js b/react/features/base/sounds/functions.any.ts similarity index 71% rename from react/features/base/sounds/functions.any.js rename to react/features/base/sounds/functions.any.ts index 251fa3a84..ddb586657 100644 --- a/react/features/base/sounds/functions.any.js +++ b/react/features/base/sounds/functions.any.ts @@ -1,4 +1,4 @@ -// @flow +import { IState } from '../../app/types'; /** * Selector for retrieving the disabled sounds array. @@ -6,6 +6,6 @@ * @param {Object} state - The Redux state. * @returns {Array} - The disabled sound id's array. */ -export function getDisabledSounds(state: Object) { +export function getDisabledSounds(state: IState) { return state['features/base/config'].disabledSounds || []; } diff --git a/react/features/base/testing/logger.js b/react/features/base/testing/logger.ts similarity index 91% rename from react/features/base/testing/logger.js rename to react/features/base/testing/logger.ts index a762f52a9..1698fd2d2 100644 --- a/react/features/base/testing/logger.js +++ b/react/features/base/testing/logger.ts @@ -1,5 +1,3 @@ -// @flow - import { getLogger } from '../logging/functions'; export default getLogger('features/base/testing'); diff --git a/react/features/base/testing/middleware.js b/react/features/base/testing/middleware.ts similarity index 85% rename from react/features/base/testing/middleware.js rename to react/features/base/testing/middleware.ts index f13ade563..62343f643 100644 --- a/react/features/base/testing/middleware.js +++ b/react/features/base/testing/middleware.ts @@ -1,10 +1,10 @@ -// @flow - +import { IStore } from '../../app/types'; import { CONFERENCE_JOIN_IN_PROGRESS } from '../conference/actionTypes'; -import { SET_CONFIG } from '../config'; +import { IJitsiConference } from '../conference/reducer'; +import { SET_CONFIG } from '../config/actionTypes'; import { JitsiConferenceEvents } from '../lib-jitsi-meet'; -import { MiddlewareRegistry } from '../redux'; -import { getJitsiMeetGlobalNS } from '../util'; +import MiddlewareRegistry from '../redux/MiddlewareRegistry'; +import { getJitsiMeetGlobalNS } from '../util/helpers'; import { setConnectionState } from './actions'; import { @@ -51,7 +51,7 @@ MiddlewareRegistry.register(store => next => action => { * @private * @returns {void} */ -function _bindConferenceConnectionListener(conference, { dispatch }) { +function _bindConferenceConnectionListener(conference: IJitsiConference, { dispatch }: IStore) { conference.on( JitsiConferenceEvents.CONNECTION_ESTABLISHED, @@ -70,11 +70,11 @@ function _bindConferenceConnectionListener(conference, { dispatch }) { /** * Binds all the helper functions needed by torture. * - * @param {Store} store - The redux store. + * @param {IStore} store - The redux store. * @private * @returns {void} */ -function _bindTortureHelpers(store) { +function _bindTortureHelpers(store: IStore) { const { getState } = store; // We bind helpers only if testing mode is enabled @@ -100,7 +100,7 @@ function _bindTortureHelpers(store) { * @returns {void} * @private */ -function _onConnectionEvent(event, dispatch) { +function _onConnectionEvent(event: string, dispatch: IStore['dispatch']) { switch (event) { case JitsiConferenceEvents.CONNECTION_ESTABLISHED: case JitsiConferenceEvents.CONNECTION_INTERRUPTED: diff --git a/react/features/e2ee/actions.js b/react/features/e2ee/actions.ts similarity index 99% rename from react/features/e2ee/actions.js rename to react/features/e2ee/actions.ts index c3f17554d..0548c6a01 100644 --- a/react/features/e2ee/actions.js +++ b/react/features/e2ee/actions.ts @@ -1,5 +1,3 @@ -// @flow - import { SET_EVERYONE_ENABLED_E2EE, SET_EVERYONE_SUPPORT_E2EE, diff --git a/react/features/notifications/actions.js b/react/features/notifications/actions.ts similarity index 83% rename from react/features/notifications/actions.js rename to react/features/notifications/actions.ts index cff01969e..60dd8fa2e 100644 --- a/react/features/notifications/actions.js +++ b/react/features/notifications/actions.ts @@ -1,9 +1,8 @@ -// @flow - import throttle from 'lodash/throttle'; -import type { Dispatch } from 'redux'; -import { NOTIFICATIONS_ENABLED, getFeatureFlag } from '../base/flags'; +import { IStore } from '../app/types'; +import { NOTIFICATIONS_ENABLED } from '../base/flags/constants'; +import { getFeatureFlag } from '../base/flags/functions'; import { getParticipantCount } from '../base/participants/functions'; import { @@ -28,7 +27,11 @@ import { * @param {Object} notificationTimeouts - Config notification timeouts. * @returns {number} */ -function getNotificationTimeout(type: ?string, notificationTimeouts: ?Object) { +function getNotificationTimeout(type?: string, notificationTimeouts?: { + long?: number; + medium?: number; + short?: number; +}) { if (type === NOTIFICATION_TIMEOUT_TYPE.SHORT) { return notificationTimeouts?.short ?? NOTIFICATION_TIMEOUT.SHORT; } else if (type === NOTIFICATION_TIMEOUT_TYPE.MEDIUM) { @@ -86,6 +89,19 @@ export function setNotificationsEnabled(enabled: boolean) { }; } +interface INotificationProps { + appearance?: string; + concatText?: boolean; + description?: string; + descriptionKey?: string; + icon?: string; + titleArguments?: { + [key: string]: string; + }; + titleKey?: string; + uid?: string; +} + /** * Queues an error notification for display. * @@ -93,7 +109,7 @@ export function setNotificationsEnabled(enabled: boolean) { * @param {string} type - Notification type. * @returns {Object} */ -export function showErrorNotification(props: Object, type: ?string) { +export function showErrorNotification(props: INotificationProps, type?: string) { return showNotification({ ...props, appearance: NOTIFICATION_TYPE.ERROR @@ -107,17 +123,17 @@ export function showErrorNotification(props: Object, type: ?string) { * @param {string} type - Timeout type. * @returns {Function} */ -export function showNotification(props: Object = {}, type: ?string) { - return function(dispatch: Function, getState: Function) { +export function showNotification(props: INotificationProps = {}, type?: string) { + return function(dispatch: IStore['dispatch'], getState: IStore['getState']) { const { disabledNotifications = [], notifications, notificationTimeouts } = getState()['features/base/config']; const enabledFlag = getFeatureFlag(getState(), NOTIFICATIONS_ENABLED, true); const shouldDisplay = enabledFlag - && !(disabledNotifications.includes(props.descriptionKey) - || disabledNotifications.includes(props.titleKey)) + && !(disabledNotifications.includes(props.descriptionKey ?? '') + || disabledNotifications.includes(props.titleKey ?? '')) && (!notifications - || notifications.includes(props.descriptionKey) - || notifications.includes(props.titleKey)); + || notifications.includes(props.descriptionKey ?? '') + || notifications.includes(props.titleKey ?? '')); if (shouldDisplay) { return dispatch({ @@ -137,7 +153,7 @@ export function showNotification(props: Object = {}, type: ?string) { * @param {string} type - Notification type. * @returns {Object} */ -export function showWarningNotification(props: Object, type: ?string) { +export function showWarningNotification(props: INotificationProps, type?: string) { return showNotification({ ...props, @@ -152,7 +168,7 @@ export function showWarningNotification(props: Object, type: ?string) { * @param {string} type - Notification type. * @returns {Object} */ -export function showMessageNotification(props: Object, type: ?string) { +export function showMessageNotification(props: INotificationProps, type?: string) { return showNotification({ ...props, concatText: true, @@ -169,7 +185,7 @@ export function showMessageNotification(props: Object, type: ?string) { * @private * @type {string[]} */ -let joinedParticipantsNames = []; +let joinedParticipantsNames: string[] = []; /** * A throttled internal function that takes the internal list of participant @@ -179,7 +195,7 @@ let joinedParticipantsNames = []; * @private * @type {Function} */ -const _throttledNotifyParticipantConnected = throttle((dispatch: Dispatch, getState: Function) => { +const _throttledNotifyParticipantConnected = throttle((dispatch: IStore['dispatch'], getState: IStore['getState']) => { const participantCount = getParticipantCount(getState()); // Skip join notifications altogether for large meetings. @@ -233,7 +249,7 @@ const _throttledNotifyParticipantConnected = throttle((dispatch: Dispatch, * @private * @type {string[]} */ -let leftParticipantsNames = []; +let leftParticipantsNames: string[] = []; /** * A throttled internal function that takes the internal list of participant @@ -243,7 +259,7 @@ let leftParticipantsNames = []; * @private * @type {Function} */ -const _throttledNotifyParticipantLeft = throttle((dispatch: Dispatch, getState: Function) => { +const _throttledNotifyParticipantLeft = throttle((dispatch: IStore['dispatch'], getState: IStore['getState']) => { const participantCount = getParticipantCount(getState()); // Skip left notifications altogether for large meetings. @@ -301,7 +317,8 @@ const _throttledNotifyParticipantLeft = throttle((dispatch: Dispatch, getSt export function showParticipantJoinedNotification(displayName: string) { joinedParticipantsNames.push(displayName); - return (dispatch: Dispatch, getState: Function) => _throttledNotifyParticipantConnected(dispatch, getState); + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => + _throttledNotifyParticipantConnected(dispatch, getState); } /** @@ -315,5 +332,6 @@ export function showParticipantJoinedNotification(displayName: string) { export function showParticipantLeftNotification(displayName: string) { leftParticipantsNames.push(displayName); - return (dispatch: Dispatch, getState: Function) => _throttledNotifyParticipantLeft(dispatch, getState); + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => + _throttledNotifyParticipantLeft(dispatch, getState); } diff --git a/react/features/notifications/components/web/NotificationsContainer.tsx b/react/features/notifications/components/web/NotificationsContainer.tsx index ac0aab4a9..fbb71e153 100644 --- a/react/features/notifications/components/web/NotificationsContainer.tsx +++ b/react/features/notifications/components/web/NotificationsContainer.tsx @@ -184,11 +184,11 @@ class NotificationsContainer extends Component { * Emits an action to remove the notification from the redux store so it * stops displaying. * - * @param {number} uid - The id of the notification to be removed. + * @param {string} uid - The id of the notification to be removed. * @private * @returns {void} */ - _onDismissed(uid: number) { + _onDismissed(uid: string) { const timeout = this._timeouts.get(`${uid}`); if (timeout) { diff --git a/react/features/notifications/middleware.js b/react/features/notifications/middleware.ts similarity index 90% rename from react/features/notifications/middleware.js rename to react/features/notifications/middleware.ts index a7eafedbd..4a4e164e3 100644 --- a/react/features/notifications/middleware.js +++ b/react/features/notifications/middleware.ts @@ -1,16 +1,18 @@ -/* @flow */ - -import { getCurrentConference } from '../base/conference'; +import { IState, IStore } from '../app/types'; +import { getCurrentConference } from '../base/conference/functions'; import { PARTICIPANT_JOINED, PARTICIPANT_LEFT, - PARTICIPANT_ROLE, - PARTICIPANT_UPDATED, + PARTICIPANT_UPDATED +} from '../base/participants/actionTypes'; +import { PARTICIPANT_ROLE } from '../base/participants/constants'; +import { getParticipantById, getParticipantDisplayName, getLocalParticipant -} from '../base/participants'; -import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux'; +} from '../base/participants/functions'; +import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; +import StateListenerRegistry from '../base/redux/StateListenerRegistry'; import { PARTICIPANTS_PANE_OPEN } from '../participants-pane/actionTypes'; import { @@ -45,7 +47,7 @@ const timers = new Map(); * @param {Function} dispatch - The Redux dispatch function. * @returns {void} */ -const createTimeoutId = (notification, dispatch) => { +const createTimeoutId = (notification: { timeout: number; uid: string; }, dispatch: IStore['dispatch']) => { const { timeout, uid @@ -66,7 +68,7 @@ const createTimeoutId = (notification, dispatch) => { * @param {Object} state - Global state. * @returns {Array} - Notifications state. */ -const getNotifications = state => { +const getNotifications = (state: IState) => { const _visible = areThereNotifications(state); const { notifications } = state['features/notifications']; @@ -80,7 +82,6 @@ const getNotifications = state => { * @returns {Function} */ MiddlewareRegistry.register(store => next => action => { - const { dispatch, getState } = store; const state = getState(); diff --git a/react/features/prejoin/reducer.ts b/react/features/prejoin/reducer.ts index 7fb509c89..3d3bd11e2 100644 --- a/react/features/prejoin/reducer.ts +++ b/react/features/prejoin/reducer.ts @@ -48,7 +48,11 @@ export interface IPrejoinState { isDisplayNameRequired: boolean; joiningInProgress?: boolean; name: string; - precallTestResults?: Object; + precallTestResults?: { + fractionalLoss: number; + mediaConnectivity: boolean; + throughput: number; + }; rawError: string; showJoinByPhoneDialog: boolean; showPrejoin: boolean;