diff --git a/react/features/analytics/AnalyticsEvents.ts b/react/features/analytics/AnalyticsEvents.ts index 8895a2947e..8ac44a4486 100644 --- a/react/features/analytics/AnalyticsEvents.ts +++ b/react/features/analytics/AnalyticsEvents.ts @@ -350,7 +350,7 @@ export function createOfferAnswerFailedEvent() { * @returns {Object} The event in a format suitable for sending via * sendAnalytics. */ -export function createPageReloadScheduledEvent(reason: string, timeout: number, details: Object) { +export function createPageReloadScheduledEvent(reason: string, timeout: number, details: Object = {}) { return { action: 'page.reload.scheduled', attributes: { diff --git a/react/features/audio-level-indicator/components/AudioLevelIndicator.js b/react/features/audio-level-indicator/components/AudioLevelIndicator.tsx similarity index 95% rename from react/features/audio-level-indicator/components/AudioLevelIndicator.js rename to react/features/audio-level-indicator/components/AudioLevelIndicator.tsx index 6a2acc0ccc..ff476d94e5 100644 --- a/react/features/audio-level-indicator/components/AudioLevelIndicator.js +++ b/react/features/audio-level-indicator/components/AudioLevelIndicator.tsx @@ -1,5 +1,3 @@ -/* @flow */ - import React, { Component } from 'react'; /** @@ -17,21 +15,21 @@ const CENTER_DOT_INDEX = Math.floor(AUDIO_LEVEL_DOTS / 2); /** * The type of the React {@code Component} props of {@link AudioLevelIndicator}. */ -type Props = { +interface IProps { /** * The current audio level to display. The value should be a number between * 0 and 1. */ - audioLevel: number -}; + audioLevel: number; +} /** * Creates a ReactElement responsible for drawing audio levels. * * @augments {Component} */ -class AudioLevelIndicator extends Component { +class AudioLevelIndicator extends Component { /** * Implements React's {@link Component#render()}. * diff --git a/react/features/base/conference/functions.ts b/react/features/base/conference/functions.ts index 1388f593c9..c6a5f904d6 100644 --- a/react/features/base/conference/functions.ts +++ b/react/features/base/conference/functions.ts @@ -494,7 +494,7 @@ function _reportError(msg: string, err: Error) { */ export function sendLocalParticipant( stateful: IStateful, - conference: IJitsiConference) { + conference?: IJitsiConference) { const { avatarURL, email, diff --git a/react/features/base/react/components/web/BaseIndicator.tsx b/react/features/base/react/components/web/BaseIndicator.tsx index 744d7f80d7..77fb19bcfd 100644 --- a/react/features/base/react/components/web/BaseIndicator.tsx +++ b/react/features/base/react/components/web/BaseIndicator.tsx @@ -5,6 +5,7 @@ import { makeStyles } from 'tss-react/mui'; import { translate } from '../../../i18n/functions'; import Icon from '../../../icons/components/Icon'; import Tooltip from '../../../tooltip/components/Tooltip'; +import { TOOLTIP_POSITION } from '../../../ui/constants.any'; /** * The type of the React {@code Component} props of {@link BaseIndicator}. @@ -56,7 +57,7 @@ interface IProps extends WithTranslation { * From which side of the indicator the tooltip should appear from, * defaulting to "top". */ - tooltipPosition: 'top' | 'bottom' | 'left' | 'right'; + tooltipPosition: TOOLTIP_POSITION; } const useStyles = makeStyles()(() => { diff --git a/react/features/base/toolbox/components/AbstractToolboxItem.tsx b/react/features/base/toolbox/components/AbstractToolboxItem.tsx index e24bc910ed..c89cff80ef 100644 --- a/react/features/base/toolbox/components/AbstractToolboxItem.tsx +++ b/react/features/base/toolbox/components/AbstractToolboxItem.tsx @@ -3,6 +3,7 @@ import { WithTranslation } from 'react-i18next'; import { GestureResponderEvent } from 'react-native'; import type { StyleType } from '../../styles/functions.any'; +import { TOOLTIP_POSITION } from '../../ui/constants.any'; export type Styles = { @@ -94,7 +95,7 @@ export interface IProps extends WithTranslation { * From which direction the tooltip should appear, relative to the * item. Used only on web. */ - tooltipPosition: 'top' | 'bottom' | 'left' | 'right'; + tooltipPosition: TOOLTIP_POSITION; /** * Whether this item is visible or not. diff --git a/react/features/base/tooltip/components/Tooltip.tsx b/react/features/base/tooltip/components/Tooltip.tsx index b7f5bbe3e6..a2632ec755 100644 --- a/react/features/base/tooltip/components/Tooltip.tsx +++ b/react/features/base/tooltip/components/Tooltip.tsx @@ -7,6 +7,7 @@ import { IReduxState } from '../../../app/types'; import { isMobileBrowser } from '../../environment/utils'; import Popover from '../../popover/components/Popover.web'; import { withPixelLineHeight } from '../../styles/functions.web'; +import { TOOLTIP_POSITION } from '../../ui/constants.any'; import { hideTooltip, showTooltip } from '../actions'; const TOOLTIP_DELAY = 300; @@ -16,7 +17,7 @@ interface IProps { children: ReactElement; containerClassName?: string; content: string; - position?: 'top' | 'bottom' | 'left' | 'right'; + position?: TOOLTIP_POSITION; } const useStyles = makeStyles()(theme => { diff --git a/react/features/base/tracks/functions.any.ts b/react/features/base/tracks/functions.any.ts index 32d96fdcf5..459b14eca2 100644 --- a/react/features/base/tracks/functions.any.ts +++ b/react/features/base/tracks/functions.any.ts @@ -29,7 +29,8 @@ export const getTrackState = (state: IReduxState) => state['features/base/tracks * @param {IReduxState} state - Global state. * @returns {boolean} - Is the media type muted for the participant. */ -export function isParticipantMediaMuted(participant: IParticipant, mediaType: MediaType, state: IReduxState) { +export function isParticipantMediaMuted(participant: IParticipant | undefined, + mediaType: MediaType, state: IReduxState) { if (!participant) { return false; } @@ -63,7 +64,7 @@ export function isParticipantAudioMuted(participant: IParticipant, state: IRedux * @param {IReduxState} state - Global state. * @returns {boolean} - Is video muted for the participant. */ -export function isParticipantVideoMuted(participant: IParticipant, state: IReduxState) { +export function isParticipantVideoMuted(participant: IParticipant | undefined, state: IReduxState) { return isParticipantMediaMuted(participant, MEDIA_TYPE.VIDEO, state); } diff --git a/react/features/base/ui/components/web/Checkbox.tsx b/react/features/base/ui/components/web/Checkbox.tsx index 6051e1e02f..488540ad2a 100644 --- a/react/features/base/ui/components/web/Checkbox.tsx +++ b/react/features/base/ui/components/web/Checkbox.tsx @@ -11,7 +11,7 @@ interface ICheckboxProps { /** * Whether the input is checked or not. */ - checked: boolean; + checked?: boolean; /** * Class name for additional styles. diff --git a/react/features/base/ui/constants.any.ts b/react/features/base/ui/constants.any.ts index 26a75e8eee..46d1eeb77d 100644 --- a/react/features/base/ui/constants.any.ts +++ b/react/features/base/ui/constants.any.ts @@ -26,3 +26,6 @@ export const BUTTON_MODES: { CONTAINED: 'contained', TEXT: 'text' }; + + +export type TOOLTIP_POSITION = 'top' | 'bottom' | 'left' | 'right'; diff --git a/react/features/connection-indicator/components/web/ConnectionIndicator.tsx b/react/features/connection-indicator/components/web/ConnectionIndicator.tsx index f7643aff92..953c25a84c 100644 --- a/react/features/connection-indicator/components/web/ConnectionIndicator.tsx +++ b/react/features/connection-indicator/components/web/ConnectionIndicator.tsx @@ -377,7 +377,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator { * @param {IProps} ownProps - The own props of the component. * @returns {IProps} */ -export function _mapStateToProps(state: IReduxState, ownProps: IProps) { +export function _mapStateToProps(state: IReduxState, ownProps: any) { const { participantId } = ownProps; const tracks = state['features/base/tracks']; const participant = participantId ? getParticipantById(state, participantId) : getLocalParticipant(state); diff --git a/react/features/desktop-picker/actions.ts b/react/features/desktop-picker/actions.ts index 6bb2e763c0..c6e647209e 100644 --- a/react/features/desktop-picker/actions.ts +++ b/react/features/desktop-picker/actions.ts @@ -1,6 +1,5 @@ import { openDialog } from '../base/dialog/actions'; -// @ts-ignore import DesktopPicker from './components/DesktopPicker'; /** diff --git a/react/features/desktop-picker/components/DesktopPicker.tsx b/react/features/desktop-picker/components/DesktopPicker.tsx index 22f6dbf02d..3c122ec5ea 100644 --- a/react/features/desktop-picker/components/DesktopPicker.tsx +++ b/react/features/desktop-picker/components/DesktopPicker.tsx @@ -9,7 +9,6 @@ import Dialog from '../../base/ui/components/web/Dialog'; import Tabs from '../../base/ui/components/web/Tabs'; import { obtainDesktopSources } from '../functions'; -// @ts-ignore import DesktopPickerPane from './DesktopPickerPane'; /** @@ -88,7 +87,7 @@ interface IState { /** * An object containing all the DesktopCapturerSources. */ - sources: Object; + sources: any; /** * The desktop source types to fetch previews for. diff --git a/react/features/desktop-picker/components/DesktopPickerPane.js b/react/features/desktop-picker/components/DesktopPickerPane.tsx similarity index 88% rename from react/features/desktop-picker/components/DesktopPickerPane.js rename to react/features/desktop-picker/components/DesktopPickerPane.tsx index 62ddb1f6dd..d6fefd7fcc 100644 --- a/react/features/desktop-picker/components/DesktopPickerPane.js +++ b/react/features/desktop-picker/components/DesktopPickerPane.tsx @@ -1,6 +1,5 @@ -/* @flow */ - import React, { Component } from 'react'; +import { WithTranslation } from 'react-i18next'; import { translate } from '../../base/i18n/functions'; import Platform from '../../base/react/Platform.web'; @@ -12,50 +11,45 @@ import DesktopSourcePreview from './DesktopSourcePreview'; /** * The type of the React {@code Component} props of {@link DesktopPickerPane}. */ -type Props = { +interface IProps extends WithTranslation { /** * The handler to be invoked when a DesktopSourcePreview is clicked. */ - onClick: Function, + onClick: Function; /** * The handler to be invoked when a DesktopSourcePreview is double clicked. */ - onDoubleClick: Function, + onDoubleClick: Function; /** * The handler to be invoked if the users checks the audio screen sharing checkbox. */ - onShareAudioChecked: Function, + onShareAudioChecked: Function; /** * The id of the DesktopCapturerSource that is currently selected. */ - selectedSourceId: string, + selectedSourceId: string; /** * An array of DesktopCapturerSources. */ - sources: Array, + sources: Array; /** * The source type of the DesktopCapturerSources to display. */ - type: string, - - /** - * Used to obtain translations. - */ - t: Function -}; + type: string; +} /** * React component for showing a grid of DesktopSourcePreviews. * * @augments Component */ -class DesktopPickerPane extends Component { +class DesktopPickerPane extends Component { /** * Initializes a new DesktopPickerPane instance. @@ -63,21 +57,19 @@ class DesktopPickerPane extends Component { * @param {Object} props - The read-only properties with which the new * instance is to be initialized. */ - constructor(props: Props) { + constructor(props: IProps) { super(props); this._onShareAudioCheck = this._onShareAudioCheck.bind(this); } - _onShareAudioCheck: (Object) => void; - /** * Function to be called when the Checkbox is used. * * @param {boolean} checked - Checkbox status (checked or not). * @returns {void} */ - _onShareAudioCheck({ target: { checked } }) { + _onShareAudioCheck({ target: { checked } }: { target: { checked: boolean; }; }) { this.props.onShareAudioChecked(checked); } diff --git a/react/features/desktop-picker/components/DesktopSourcePreview.js b/react/features/desktop-picker/components/DesktopSourcePreview.tsx similarity index 88% rename from react/features/desktop-picker/components/DesktopSourcePreview.js rename to react/features/desktop-picker/components/DesktopSourcePreview.tsx index 702d6200fa..00259c2fb1 100644 --- a/react/features/desktop-picker/components/DesktopSourcePreview.js +++ b/react/features/desktop-picker/components/DesktopSourcePreview.tsx @@ -1,6 +1,5 @@ -/* @flow */ - import React, { Component } from 'react'; +import { WithTranslation } from 'react-i18next'; import { translate } from '../../base/i18n/functions'; @@ -9,56 +8,51 @@ import { translate } from '../../base/i18n/functions'; * The type of the React {@code Component} props of * {@link DesktopSourcePreview}. */ -type Props = { +interface IProps extends WithTranslation { /** * The callback to invoke when the component is clicked. The id of the * clicked on DesktopCapturerSource will be passed in. */ - onClick: Function, + onClick: Function; /** * The callback to invoke when the component is double clicked. The id of * the DesktopCapturerSource will be passed in. */ - onDoubleClick: Function, + onDoubleClick: Function; /** * The indicator which determines whether this DesktopSourcePreview is * selected. If true, the 'is-selected' CSS class will be added to the root * of Component. */ - selected: boolean, + selected: boolean; /** * The DesktopCapturerSource to display. */ - source: Object, + source: any; /** * The source type of the DesktopCapturerSources to display. */ - type: string, - - /** - * Invoked to obtain translated strings. - */ - t: Function -}; + type: string; +} /** * React component for displaying a preview of a DesktopCapturerSource. * * @augments Component */ -class DesktopSourcePreview extends Component { +class DesktopSourcePreview extends Component { /** * Initializes a new DesktopSourcePreview instance. * * @param {Object} props - The read-only properties with which the new * instance is to be initialized. */ - constructor(props: Props) { + constructor(props: IProps) { super(props); this._onClick = this._onClick.bind(this); @@ -93,8 +87,6 @@ class DesktopSourcePreview extends Component { ); } - _onClick: () => void; - /** * Invokes the passed in onClick callback. * @@ -106,8 +98,6 @@ class DesktopSourcePreview extends Component { this.props.onClick(source.id, type); } - _onDoubleClick: () => void; - /** * Invokes the passed in onDoubleClick callback. * diff --git a/react/features/display-name/components/web/DisplayName.tsx b/react/features/display-name/components/web/DisplayName.tsx index a6e182fb51..7f028394d3 100644 --- a/react/features/display-name/components/web/DisplayName.tsx +++ b/react/features/display-name/components/web/DisplayName.tsx @@ -43,7 +43,7 @@ interface IProps { /** * The type of thumbnail. */ - thumbnailType: string; + thumbnailType?: string; } const useStyles = makeStyles()(theme => { diff --git a/react/features/feedback/actions.ts b/react/features/feedback/actions.ts index 151c302314..aa3c0e0bc1 100644 --- a/react/features/feedback/actions.ts +++ b/react/features/feedback/actions.ts @@ -11,8 +11,6 @@ import { SUBMIT_FEEDBACK_ERROR, SUBMIT_FEEDBACK_SUCCESS } from './actionTypes'; -// eslint-disable-next-line lines-around-comment -// @ts-ignore import FeedbackDialog from './components/FeedbackDialog'; import { sendFeedbackToJaaSRequest } from './functions'; diff --git a/react/features/filmstrip/components/web/AudioMutedIndicator.js b/react/features/filmstrip/components/web/AudioMutedIndicator.tsx similarity index 79% rename from react/features/filmstrip/components/web/AudioMutedIndicator.js rename to react/features/filmstrip/components/web/AudioMutedIndicator.tsx index fa58d2e633..6bc9b56a69 100644 --- a/react/features/filmstrip/components/web/AudioMutedIndicator.js +++ b/react/features/filmstrip/components/web/AudioMutedIndicator.tsx @@ -1,27 +1,26 @@ -/* @flow */ - import React from 'react'; import { IconMicSlash } from '../../../base/icons/svg'; import BaseIndicator from '../../../base/react/components/web/BaseIndicator'; +import { TOOLTIP_POSITION } from '../../../base/ui/constants.any'; /** * The type of the React {@code Component} props of {@link AudioMutedIndicator}. */ -type Props = { +interface IProps { /** * From which side of the indicator the tooltip should appear from. */ - tooltipPosition: string -}; + tooltipPosition: TOOLTIP_POSITION; +} /** * React {@code Component} for showing an audio muted icon with a tooltip. * * @returns {Component} */ -const AudioMutedIndicator = ({ tooltipPosition }: Props) => ( +const AudioMutedIndicator = ({ tooltipPosition }: IProps) => ( -}; + _tracks: ITrack[]; +} /** * A container for the remote tracks audio elements. * - * @param {Props} props - The props of the component. + * @param {IProps} props - The props of the component. * @returns {Array} */ -function AudioTracksContainer(props: Props) { +function AudioTracksContainer(props: IProps) { const { _tracks } = props; const remoteAudioTracks = _tracks.filter(t => !t.local && t.mediaType === MEDIA_TYPE.AUDIO); @@ -31,7 +34,7 @@ function AudioTracksContainer(props: Props) { { remoteAudioTracks.map(t => { const { jitsiTrack, participantId } = t; - const audioTrackId = jitsiTrack && jitsiTrack.getId(); + const audioTrackId = jitsiTrack?.getId(); const id = `remoteAudio_${audioTrackId || ''}`; return ( @@ -50,9 +53,9 @@ function AudioTracksContainer(props: Props) { * * @param {Object} state - The Redux state. * @private - * @returns {Props} + * @returns {IProps} */ -function _mapStateToProps(state) { +function _mapStateToProps(state: IReduxState) { // NOTE: The disadvantage of this approach is that the component will re-render on any track change. // One way to solve the problem would be to pass only the participant ID to the AudioTrack component and // find the corresponding track inside the AudioTrack's mapStateToProps. But currently this will be very diff --git a/react/features/filmstrip/components/web/Filmstrip.tsx b/react/features/filmstrip/components/web/Filmstrip.tsx index 19f3889041..1e758be5ee 100644 --- a/react/features/filmstrip/components/web/Filmstrip.tsx +++ b/react/features/filmstrip/components/web/Filmstrip.tsx @@ -43,7 +43,6 @@ import { shouldRemoteVideosBeVisible } from '../../functions'; -// @ts-ignore import AudioTracksContainer from './AudioTracksContainer'; import Thumbnail from './Thumbnail'; import ThumbnailWrapper from './ThumbnailWrapper'; diff --git a/react/features/filmstrip/components/web/ModeratorIndicator.tsx b/react/features/filmstrip/components/web/ModeratorIndicator.tsx index 56de4f9cb1..e839e26d80 100644 --- a/react/features/filmstrip/components/web/ModeratorIndicator.tsx +++ b/react/features/filmstrip/components/web/ModeratorIndicator.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { IconModerator } from '../../../base/icons/svg'; import BaseIndicator from '../../../base/react/components/web/BaseIndicator'; +import { TOOLTIP_POSITION } from '../../../base/ui/constants.any'; /** * The type of the React {@code Component} props of {@link ModeratorIndicator}. @@ -11,7 +12,7 @@ interface IProps { /** * From which side of the indicator the tooltip should appear from. */ - tooltipPosition: 'top' | 'bottom' | 'left' | 'right'; + tooltipPosition: TOOLTIP_POSITION; } /** diff --git a/react/features/filmstrip/components/web/PinnedIndicator.tsx b/react/features/filmstrip/components/web/PinnedIndicator.tsx index 068d36973a..c73b23ef38 100644 --- a/react/features/filmstrip/components/web/PinnedIndicator.tsx +++ b/react/features/filmstrip/components/web/PinnedIndicator.tsx @@ -6,6 +6,7 @@ import { IReduxState } from '../../../app/types'; import { IconPin } from '../../../base/icons/svg'; import { getParticipantById } from '../../../base/participants/functions'; import BaseIndicator from '../../../base/react/components/web/BaseIndicator'; +import { TOOLTIP_POSITION } from '../../../base/ui/constants.any'; import { getPinnedActiveParticipants, isStageFilmstripAvailable } from '../../functions.web'; /** @@ -27,7 +28,7 @@ interface IProps { /** * From which side of the indicator the tooltip should appear from. */ - tooltipPosition: 'top' | 'bottom' | 'left' | 'right'; + tooltipPosition: TOOLTIP_POSITION; } const useStyles = makeStyles()(() => { diff --git a/react/features/filmstrip/components/web/RaisedHandIndicator.tsx b/react/features/filmstrip/components/web/RaisedHandIndicator.tsx index df725cda0a..12e789f698 100644 --- a/react/features/filmstrip/components/web/RaisedHandIndicator.tsx +++ b/react/features/filmstrip/components/web/RaisedHandIndicator.tsx @@ -7,6 +7,7 @@ import { IconRaiseHand } from '../../../base/icons/svg'; import { getParticipantById, hasRaisedHand } from '../../../base/participants/functions'; import { IParticipant } from '../../../base/participants/types'; import BaseIndicator from '../../../base/react/components/web/BaseIndicator'; +import { TOOLTIP_POSITION } from '../../../base/ui/constants.any'; /** * The type of the React {@code Component} props of {@link RaisedHandIndicator}. @@ -27,7 +28,7 @@ interface IProps { /** * From which side of the indicator the tooltip should appear from. */ - tooltipPosition: 'top' | 'bottom' | 'left' | 'right'; + tooltipPosition: TOOLTIP_POSITION; } const useStyles = makeStyles()(theme => { diff --git a/react/features/filmstrip/components/web/ScreenShareIndicator.js b/react/features/filmstrip/components/web/ScreenShareIndicator.tsx similarity index 71% rename from react/features/filmstrip/components/web/ScreenShareIndicator.js rename to react/features/filmstrip/components/web/ScreenShareIndicator.tsx index 321be7f1cd..87f2ef3d79 100644 --- a/react/features/filmstrip/components/web/ScreenShareIndicator.js +++ b/react/features/filmstrip/components/web/ScreenShareIndicator.tsx @@ -1,26 +1,24 @@ -// @flow - import React from 'react'; import { IconScreenshare } from '../../../base/icons/svg'; import BaseIndicator from '../../../base/react/components/web/BaseIndicator'; +import { TOOLTIP_POSITION } from '../../../base/ui/constants.any'; - -type Props = { +interface IProps { /** * From which side of the indicator the tooltip should appear from. */ - tooltipPosition: string -}; + tooltipPosition: TOOLTIP_POSITION; +} /** * React {@code Component} for showing a screen-sharing icon with a tooltip. * - * @param {Props} props - React props passed to this component. + * @param {IProps} props - React props passed to this component. * @returns {React$Element} */ -export default function ScreenShareIndicator(props: Props) { +export default function ScreenShareIndicator(props: IProps) { return ( { +class StatusIndicators extends Component { /** * Implements React's {@link Component#render()}. * @@ -96,7 +90,7 @@ class StatusIndicators extends Component { * _showScreenShareIndicator: boolean * }} */ -function _mapStateToProps(state, ownProps) { +function _mapStateToProps(state: IReduxState, ownProps: any) { const { participantID, audio, moderator, screenshare } = ownProps; // Only the local participant won't have id for the time when the conference is not yet joined. diff --git a/react/features/filmstrip/components/web/Thumbnail.tsx b/react/features/filmstrip/components/web/Thumbnail.tsx index d85bb8dd99..aa5764c5b3 100644 --- a/react/features/filmstrip/components/web/Thumbnail.tsx +++ b/react/features/filmstrip/components/web/Thumbnail.tsx @@ -1,4 +1,3 @@ -/* eslint-disable lines-around-comment */ import { Theme } from '@mui/material'; import { withStyles } from '@mui/styles'; import clsx from 'clsx'; @@ -14,6 +13,7 @@ import Avatar from '../../../base/avatar/components/Avatar'; import { isMobileBrowser } from '../../../base/environment/utils'; import { translate } from '../../../base/i18n/functions'; import { JitsiTrackEvents } from '../../../base/lib-jitsi-meet'; +// eslint-disable-next-line lines-around-comment // @ts-ignore import VideoTrack from '../../../base/media/components/web/VideoTrack'; import { MEDIA_TYPE } from '../../../base/media/constants'; @@ -36,10 +36,10 @@ import { getTrackByMediaTypeAndParticipant, getVideoTrackByParticipant } from '../../../base/tracks/functions'; +import { ITrack } from '../../../base/tracks/types'; import { getVideoObjectPosition } from '../../../face-landmarks/functions'; import { hideGif, showGif } from '../../../gifs/actions'; import { getGifDisplayMode, getGifForParticipant } from '../../../gifs/functions'; -// @ts-ignore import PresenceLabel from '../../../presence-status/components/PresenceLabel'; import { LAYOUTS } from '../../../video-layout/constants'; import { getCurrentLayout } from '../../../video-layout/functions.web'; @@ -61,13 +61,10 @@ import { showGridInVerticalView } from '../../functions'; -// @ts-ignore import ThumbnailAudioIndicator from './ThumbnailAudioIndicator'; import ThumbnailBottomIndicators from './ThumbnailBottomIndicators'; import ThumbnailTopIndicators from './ThumbnailTopIndicators'; -// @ts-ignore import VirtualScreenshareParticipant from './VirtualScreenshareParticipant'; -/* eslint-enable lines-around-comment */ /** * The type of the React {@code Component} state of {@link Thumbnail}. @@ -103,7 +100,7 @@ export interface IProps extends WithTranslation { /** * The audio track related to the participant. */ - _audioTrack?: Object; + _audioTrack?: ITrack; /** * Indicates whether the local video flip feature is disabled or not. diff --git a/react/features/filmstrip/components/web/ThumbnailAudioIndicator.js b/react/features/filmstrip/components/web/ThumbnailAudioIndicator.tsx similarity index 72% rename from react/features/filmstrip/components/web/ThumbnailAudioIndicator.js rename to react/features/filmstrip/components/web/ThumbnailAudioIndicator.tsx index bff9aa35c6..a280988972 100644 --- a/react/features/filmstrip/components/web/ThumbnailAudioIndicator.js +++ b/react/features/filmstrip/components/web/ThumbnailAudioIndicator.tsx @@ -1,23 +1,24 @@ -// @flow - import React, { useEffect, useState } from 'react'; import AudioLevelIndicator from '../../../audio-level-indicator/components/AudioLevelIndicator'; +// eslint-disable-next-line lines-around-comment +// @ts-ignore import JitsiMeetJS from '../../../base/lib-jitsi-meet/_'; +import { ITrack } from '../../../base/tracks/types'; const JitsiTrackEvents = JitsiMeetJS.events.track; -type Props = { +interface IProps { /** * The audio track related to the participant. */ - _audioTrack: ?Object + _audioTrack?: ITrack; } const ThumbnailAudioIndicator = ({ _audioTrack -}: Props) => { +}: IProps) => { const [ audioLevel, setAudioLevel ] = useState(0); useEffect(() => { @@ -25,14 +26,14 @@ const ThumbnailAudioIndicator = ({ if (_audioTrack) { const { jitsiTrack } = _audioTrack; - jitsiTrack && jitsiTrack.on(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, setAudioLevel); + jitsiTrack?.on(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, setAudioLevel); } return () => { if (_audioTrack) { const { jitsiTrack } = _audioTrack; - jitsiTrack && jitsiTrack.off(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, setAudioLevel); + jitsiTrack?.off(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, setAudioLevel); } }; }, [ _audioTrack ]); diff --git a/react/features/filmstrip/components/web/ThumbnailBottomIndicators.tsx b/react/features/filmstrip/components/web/ThumbnailBottomIndicators.tsx index bfc43a0e45..2dcded8faa 100644 --- a/react/features/filmstrip/components/web/ThumbnailBottomIndicators.tsx +++ b/react/features/filmstrip/components/web/ThumbnailBottomIndicators.tsx @@ -10,7 +10,6 @@ import { import { isScreenShareParticipantById } from '../../../base/participants/functions'; import DisplayName from '../../../display-name/components/web/DisplayName'; -// @ts-ignore import StatusIndicators from './StatusIndicators'; interface IProps { @@ -38,7 +37,7 @@ interface IProps { /** * The type of thumbnail. */ - thumbnailType: string; + thumbnailType?: string; } const useStyles = makeStyles()(() => { diff --git a/react/features/filmstrip/components/web/ThumbnailTopIndicators.tsx b/react/features/filmstrip/components/web/ThumbnailTopIndicators.tsx index 4de3ce55fc..aaccf9a5d1 100644 --- a/react/features/filmstrip/components/web/ThumbnailTopIndicators.tsx +++ b/react/features/filmstrip/components/web/ThumbnailTopIndicators.tsx @@ -11,8 +11,6 @@ import { getIndicatorsTooltipPosition } from '../../functions.web'; import PinnedIndicator from './PinnedIndicator'; import RaisedHandIndicator from './RaisedHandIndicator'; -// eslint-disable-next-line lines-around-comment -// @ts-ignore import StatusIndicators from './StatusIndicators'; import VideoMenuTriggerButton from './VideoMenuTriggerButton'; @@ -26,12 +24,12 @@ interface IProps { /** * Hide popover callback. */ - hidePopover: Function; + hidePopover?: Function; /** * Class name for the status indicators container. */ - indicatorsClassName: string; + indicatorsClassName?: string; /** * Whether or not the thumbnail is hovered. @@ -41,7 +39,7 @@ interface IProps { /** * Whether or not the indicators are for the local participant. */ - local: boolean; + local?: boolean; /** * Id of the participant for which the component is displayed. @@ -51,12 +49,12 @@ interface IProps { /** * Whether popover is visible or not. */ - popoverVisible: boolean; + popoverVisible?: boolean; /** * Show popover callback. */ - showPopover: Function; + showPopover?: Function; /** * The type of thumbnail. @@ -104,7 +102,7 @@ const ThumbnailTopIndicators = ({ if (isVirtualScreenshareParticipant) { return (
- {!_connectionIndicatorDisabled // @ts-ignore + {!_connectionIndicatorDisabled && - {!_connectionIndicatorDisabled // @ts-ignore + {!_connectionIndicatorDisabled && void; /** * Mouse enter handler. */ - onMouseEnter: Function, + onMouseEnter: (e?: React.MouseEvent) => void; /** * Mouse leave handler. */ - onMouseLeave: Function, + onMouseLeave: (e?: React.MouseEvent) => void; - /** + /** * Mouse move handler. */ - onMouseMove: Function, + onMouseMove: (e?: React.MouseEvent) => void; /** * Touch end handler. */ - onTouchEnd: Function, + onTouchEnd: TouchEventHandler; /** * Touch move handler. */ - onTouchMove: Function, + onTouchMove: TouchEventHandler; /** * Touch start handler. */ - onTouchStart: Function, + onTouchStart: TouchEventHandler; /** * The ID of the virtual screen share participant. */ - participantId: string, + participantId: string; /** * Whether or not to display a tint background over tile. */ - shouldDisplayTintBackground: boolean, + shouldDisplayTintBackground: boolean; /** * An object with the styles for thumbnail. */ - styles: Object, + styles: any; /** * The type of thumbnail. */ - thumbnailType: string, + thumbnailType: string; /** * JitsiTrack instance. */ - videoTrack: Object + videoTrack: ITrack; } const VirtualScreenshareParticipant = ({ @@ -117,7 +117,7 @@ const VirtualScreenshareParticipant = ({ styles, videoTrack, thumbnailType -}: Props) => { +}: IProps) => { const currentLayout = useSelector(getCurrentLayout); const videoTrackId = videoTrack?.jitsiTrack?.getId(); const video = videoTrack && @@ -165,7 +164,6 @@ const VirtualScreenshareParticipant = ({ ) }> diff --git a/react/features/filmstrip/functions.web.ts b/react/features/filmstrip/functions.web.ts index a27adf8102..5086ff3537 100644 --- a/react/features/filmstrip/functions.web.ts +++ b/react/features/filmstrip/functions.web.ts @@ -613,8 +613,8 @@ export function getDisplayModeInput(props: any, state: { canPlayEventReceived: b * @param {string} thumbnailType - The current thumbnail type. * @returns {string} */ -export function getIndicatorsTooltipPosition(thumbnailType: string) { - return INDICATORS_TOOLTIP_POSITION[thumbnailType] || 'top'; +export function getIndicatorsTooltipPosition(thumbnailType?: string) { + return INDICATORS_TOOLTIP_POSITION[thumbnailType ?? ''] || 'top'; } /** diff --git a/react/features/invite/components/add-people-dialog/web/AddPeopleDialog.tsx b/react/features/invite/components/add-people-dialog/web/AddPeopleDialog.tsx index bab8a00ca9..3a32168384 100644 --- a/react/features/invite/components/add-people-dialog/web/AddPeopleDialog.tsx +++ b/react/features/invite/components/add-people-dialog/web/AddPeopleDialog.tsx @@ -30,7 +30,6 @@ import DialInSection from './DialInSection'; import InviteByEmailSection from './InviteByEmailSection'; // @ts-ignore import InviteContactsSection from './InviteContactsSection'; -// @ts-ignore import LiveStreamSection from './LiveStreamSection'; /* eslint-enable lines-around-comment */ diff --git a/react/features/invite/components/add-people-dialog/web/LiveStreamSection.js b/react/features/invite/components/add-people-dialog/web/LiveStreamSection.tsx similarity index 93% rename from react/features/invite/components/add-people-dialog/web/LiveStreamSection.js rename to react/features/invite/components/add-people-dialog/web/LiveStreamSection.tsx index 32aaeb8370..ca847518a4 100644 --- a/react/features/invite/components/add-people-dialog/web/LiveStreamSection.js +++ b/react/features/invite/components/add-people-dialog/web/LiveStreamSection.tsx @@ -1,25 +1,19 @@ -// @flow - /* eslint-disable react/jsx-no-bind */ import React, { useState } from 'react'; +import { WithTranslation } from 'react-i18next'; import { translate } from '../../../../base/i18n/functions'; import Icon from '../../../../base/icons/components/Icon'; import { IconCheck, IconCopy } from '../../../../base/icons/svg'; import { copyText } from '../../../../base/util/copyText.web'; -type Props = { +interface IProps extends WithTranslation { /** * The current known URL for a live stream in progress. */ - liveStreamViewURL: string, - - /** - * Invoked to obtain translated strings. - */ - t: Function + liveStreamViewURL: string; } /** @@ -28,7 +22,7 @@ type Props = { * * @returns {React$Element} */ -function LiveStreamSection({ liveStreamViewURL, t }: Props) { +function LiveStreamSection({ liveStreamViewURL, t }: IProps) { const [ isClicked, setIsClicked ] = useState(false); const [ isHovered, setIsHovered ] = useState(false); diff --git a/react/features/lobby/actions.any.ts b/react/features/lobby/actions.any.ts index 7b196fc64c..44409e0065 100644 --- a/react/features/lobby/actions.any.ts +++ b/react/features/lobby/actions.any.ts @@ -207,12 +207,10 @@ export function startKnocking() { 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); diff --git a/react/features/no-audio-signal/components/DialInLink.js b/react/features/no-audio-signal/components/DialInLink.tsx similarity index 84% rename from react/features/no-audio-signal/components/DialInLink.js rename to react/features/no-audio-signal/components/DialInLink.tsx index 1c86cad9a8..f68160af3f 100644 --- a/react/features/no-audio-signal/components/DialInLink.js +++ b/react/features/no-audio-signal/components/DialInLink.tsx @@ -1,31 +1,26 @@ -// @flow - import React, { Component } from 'react'; +import { WithTranslation } from 'react-i18next'; import { connect } from 'react-redux'; +import { IReduxState } from '../../app/types'; import { translate } from '../../base/i18n/functions'; import { getDialInfoPageURL, shouldDisplayDialIn } from '../../invite/functions'; /** * The type of the React {@code Component} props of {@link DialInLink}. */ -type Props = { +interface IProps extends WithTranslation { /** * The redux state representing the dial-in numbers feature. */ - _dialIn: Object, + _dialIn: Object; /** * The url of the page containing the dial-in numbers list. */ - _dialInfoPageUrl: string, - - /** - * Invoked to obtain translated strings. - */ - t: Function -}; + _dialInfoPageUrl: string; +} /** * React {@code Component} responsible for displaying a telephone number and @@ -33,7 +28,7 @@ type Props = { * * @augments Component */ -class DialInLink extends Component { +class DialInLink extends Component { /** * Implements React's {@link Component#render()}. * @@ -66,9 +61,9 @@ class DialInLink extends Component { * * @param {Object} state - The Redux state. * @private - * @returns {Props} + * @returns {IProps} */ -function _mapStateToProps(state) { +function _mapStateToProps(state: IReduxState) { return { _dialIn: state['features/invite'], _dialInfoPageUrl: getDialInfoPageURL(state) diff --git a/react/features/no-audio-signal/middleware.tsx b/react/features/no-audio-signal/middleware.tsx index 5550712496..96afdb9692 100644 --- a/react/features/no-audio-signal/middleware.tsx +++ b/react/features/no-audio-signal/middleware.tsx @@ -14,8 +14,6 @@ import { hideNotification, showNotification } from '../notifications/actions'; import { NOTIFICATION_TIMEOUT_TYPE } from '../notifications/constants'; import { setNoAudioSignalNotificationUid } from './actions'; -// eslint-disable-next-line lines-around-comment -// @ts-ignore import DialInLink from './components/DialInLink'; import { NO_AUDIO_SIGNAL_SOUND_ID } from './constants'; import { NO_AUDIO_SIGNAL_SOUND_FILE } from './sounds'; diff --git a/react/features/overlay/actions.web.ts b/react/features/overlay/actions.web.ts index bc215c1b3e..0cd61c21ac 100644 --- a/react/features/overlay/actions.web.ts +++ b/react/features/overlay/actions.web.ts @@ -27,6 +27,6 @@ export function mediaPermissionPromptVisibilityChanged(isVisible: boolean, brows * * @returns {Function} */ -export function openPageReloadDialog() { +export function openPageReloadDialog(): any { // Dummy } diff --git a/react/features/overlay/components/web/AbstractPageReloadOverlay.tsx b/react/features/overlay/components/web/AbstractPageReloadOverlay.tsx index 133c8a2e99..a3469d29b8 100644 --- a/react/features/overlay/components/web/AbstractPageReloadOverlay.tsx +++ b/react/features/overlay/components/web/AbstractPageReloadOverlay.tsx @@ -13,7 +13,6 @@ import { } from '../../../base/lib-jitsi-meet/functions.web'; import logger from '../../logger'; -// @ts-ignore import ReloadButton from './ReloadButton'; /** @@ -26,7 +25,7 @@ export interface IProps extends WithTranslation { * The details is an object containing more information about the connection * failed (shard changes, was the computer suspended, etc.). */ - details: Object; + details?: Object; /** * Redux dispatch function. @@ -36,7 +35,7 @@ export interface IProps extends WithTranslation { /** * The error that caused the display of the overlay. */ - error: Error; + error?: any; /** * The indicator which determines whether the reload was caused by network @@ -48,7 +47,7 @@ export interface IProps extends WithTranslation { * The reason for the error that will cause the reload. * NOTE: Used by PageReloadOverlay only. */ - reason: string; + reason?: string; } /** @@ -167,7 +166,7 @@ export default class AbstractPageReloadOverlay

} sendAnalytics(createPageReloadScheduledEvent( - this.props.reason, + this.props.reason ?? '', this.state.timeoutSeconds, this.props.details)); diff --git a/react/features/overlay/components/web/AbstractUserMediaPermissionsOverlay.ts b/react/features/overlay/components/web/AbstractUserMediaPermissionsOverlay.ts index 22aeb219d1..917765502b 100644 --- a/react/features/overlay/components/web/AbstractUserMediaPermissionsOverlay.ts +++ b/react/features/overlay/components/web/AbstractUserMediaPermissionsOverlay.ts @@ -9,11 +9,13 @@ import { IReduxState } from '../../../app/types'; */ interface IProps extends WithTranslation { + _premeetingBackground?: any; + /** * The browser which is used currently. The text is different for every * browser. */ - browser: string; + browser?: string; } /** diff --git a/react/features/overlay/components/web/OverlayFrame.tsx b/react/features/overlay/components/web/OverlayFrame.tsx index 12b3b10552..f2abb2374f 100644 --- a/react/features/overlay/components/web/OverlayFrame.tsx +++ b/react/features/overlay/components/web/OverlayFrame.tsx @@ -1,4 +1,4 @@ -import React, { Component, ReactChildren } from 'react'; +import React, { Component, ReactNode } from 'react'; /** * The type of the React {@code Component} props of {@link OverlayFrame}. @@ -8,7 +8,7 @@ interface IProps { /** * The children components to be displayed into the overlay frame. */ - children: ReactChildren; + children: ReactNode; /** * Indicates the css style of the overlay. If true, then lighter; darker, @@ -19,7 +19,7 @@ interface IProps { /** * The style property. */ - style: Object; + style?: Object; } /** diff --git a/react/features/overlay/components/web/PageReloadOverlay.js b/react/features/overlay/components/web/PageReloadOverlay.tsx similarity index 90% rename from react/features/overlay/components/web/PageReloadOverlay.js rename to react/features/overlay/components/web/PageReloadOverlay.tsx index 4345f568bc..ffe3ac39e2 100644 --- a/react/features/overlay/components/web/PageReloadOverlay.js +++ b/react/features/overlay/components/web/PageReloadOverlay.tsx @@ -1,12 +1,10 @@ -// @flow - import React from 'react'; import { connect } from 'react-redux'; import { translate } from '../../../base/i18n/functions'; import AbstractPageReloadOverlay, { - type Props, + IProps, abstractMapStateToProps } from './AbstractPageReloadOverlay'; import OverlayFrame from './OverlayFrame'; @@ -16,7 +14,7 @@ import OverlayFrame from './OverlayFrame'; * conference is reloaded. Shows a warning message and counts down towards the * reload. */ -class PageReloadOverlay extends AbstractPageReloadOverlay { +class PageReloadOverlay extends AbstractPageReloadOverlay { /** * Implements React's {@link Component#render()}. * @@ -51,10 +49,6 @@ class PageReloadOverlay extends AbstractPageReloadOverlay { ); } - - _renderButton: () => React$Element<*>; - - _renderProgressBar: () => React$Element<*>; } export default translate(connect(abstractMapStateToProps)(PageReloadOverlay)); diff --git a/react/features/overlay/components/web/ReloadButton.js b/react/features/overlay/components/web/ReloadButton.tsx similarity index 81% rename from react/features/overlay/components/web/ReloadButton.js rename to react/features/overlay/components/web/ReloadButton.tsx index dd71bdc810..d0ba647331 100644 --- a/react/features/overlay/components/web/ReloadButton.js +++ b/react/features/overlay/components/web/ReloadButton.tsx @@ -1,37 +1,32 @@ -// @flow - import React, { Component } from 'react'; +import { WithTranslation } from 'react-i18next'; import { connect } from 'react-redux'; -import { reloadNow } from '../../../app/actions'; +import { reloadNow } from '../../../app/actions.web'; +import { IStore } from '../../../app/types'; import { translate } from '../../../base/i18n/functions'; /** * The type of the React {@code Component} props of {@link ReloadButton}. */ -type Props = { +interface IProps extends WithTranslation { /** * Reloads the page. */ - _reloadNow: Function, - - /** - * The function to translate human-readable text. - */ - t: Function, + _reloadNow: () => void; /** * The translation key for the text in the button. */ - textKey: string -}; + textKey: string; +} /** * Implements a React Component for button for the overlays that will reload * the page. */ -class ReloadButton extends Component { +class ReloadButton extends Component { /** * Renders the button for relaod the page if necessary. * @@ -63,7 +58,7 @@ class ReloadButton extends Component { * @private * @returns {Object} */ -function _mapDispatchToProps(dispatch: Function) { +function _mapDispatchToProps(dispatch: IStore['dispatch']) { return { /** * Dispatches the redux action to reload the page. diff --git a/react/features/overlay/components/web/SuspendedOverlay.js b/react/features/overlay/components/web/SuspendedOverlay.tsx similarity index 99% rename from react/features/overlay/components/web/SuspendedOverlay.js rename to react/features/overlay/components/web/SuspendedOverlay.tsx index 1064b3938c..33d2d309d1 100644 --- a/react/features/overlay/components/web/SuspendedOverlay.js +++ b/react/features/overlay/components/web/SuspendedOverlay.tsx @@ -1,5 +1,3 @@ -// @flow - import React from 'react'; import { translate } from '../../../base/i18n/functions'; diff --git a/react/features/overlay/components/web/UserMediaPermissionsOverlay.js b/react/features/overlay/components/web/UserMediaPermissionsOverlay.tsx similarity index 94% rename from react/features/overlay/components/web/UserMediaPermissionsOverlay.js rename to react/features/overlay/components/web/UserMediaPermissionsOverlay.tsx index 290bc6ae6b..052f53b5e2 100644 --- a/react/features/overlay/components/web/UserMediaPermissionsOverlay.js +++ b/react/features/overlay/components/web/UserMediaPermissionsOverlay.tsx @@ -1,16 +1,13 @@ -// @flow - import React from 'react'; import { connect } from 'react-redux'; +import { IReduxState } from '../../../app/types'; import { translate, translateToHTML } from '../../../base/i18n/functions'; import AbstractUserMediaPermissionsOverlay, { abstractMapStateToProps } from './AbstractUserMediaPermissionsOverlay'; import OverlayFrame from './OverlayFrame'; -declare var interfaceConfig: Object; - /** * Implements a React Component for overlay with guidance how to proceed with * gUM prompt. @@ -96,7 +93,7 @@ class UserMediaPermissionsOverlay extends AbstractUserMediaPermissionsOverlay { * @param {Object} ownProps - The props passed to the component. * @returns {Object} */ -function mapStateToProps(state) { +function mapStateToProps(state: IReduxState) { const { premeetingBackground } = state['features/dynamic-branding']; return { @@ -105,5 +102,4 @@ function mapStateToProps(state) { }; } -export default translate( - connect(mapStateToProps)(UserMediaPermissionsOverlay)); +export default translate(connect(mapStateToProps)(UserMediaPermissionsOverlay)); diff --git a/react/features/overlay/functions.web.ts b/react/features/overlay/functions.web.ts index 63a95102e6..119739926b 100644 --- a/react/features/overlay/functions.web.ts +++ b/react/features/overlay/functions.web.ts @@ -1,13 +1,9 @@ -/* eslint-disable lines-around-comment */ - import { IReduxState } from '../app/types'; -// @ts-ignore import PageReloadOverlay from './components/web/PageReloadOverlay'; -// @ts-ignore import SuspendedOverlay from './components/web/SuspendedOverlay'; -// @ts-ignore import UserMediaPermissionsOverlay from './components/web/UserMediaPermissionsOverlay'; + /** * Returns the overlay to be currently rendered. * diff --git a/react/features/overlay/middleware.ts b/react/features/overlay/middleware.ts index ccbc4445a7..db70a7d017 100644 --- a/react/features/overlay/middleware.ts +++ b/react/features/overlay/middleware.ts @@ -108,7 +108,6 @@ StateListenerRegistry.register( }); } else if (RN_NO_RELOAD_DIALOG_ERRORS.indexOf(error.name) === -1 && typeof error.recoverable === 'undefined') { setTimeout(() => { - // @ts-ignore store.dispatch(openPageReloadDialog()); }, 500); } diff --git a/react/features/participants-pane/components/native/MeetingParticipantItem.js b/react/features/participants-pane/components/native/MeetingParticipantItem.js index d7204c4b80..aaa8666c29 100644 --- a/react/features/participants-pane/components/native/MeetingParticipantItem.js +++ b/react/features/participants-pane/components/native/MeetingParticipantItem.js @@ -172,7 +172,7 @@ function mapStateToProps(state, ownProps): Object { const { participant } = ownProps; const { ownerId } = state['features/shared-video']; const localParticipantId = getLocalParticipant(state).id; - const _isAudioMuted = isParticipantAudioMuted(participant, state); + const _isAudioMuted = Boolean(participant && isParticipantAudioMuted(participant, state)); const _isVideoMuted = isParticipantVideoMuted(participant, state); const audioMediaState = getParticipantAudioMediaState(participant, _isAudioMuted, state); const videoMediaState = getParticipantVideoMediaState(participant, _isVideoMuted, state); diff --git a/react/features/participants-pane/components/web/LobbyParticipantItems.js b/react/features/participants-pane/components/web/LobbyParticipantItems.tsx similarity index 77% rename from react/features/participants-pane/components/web/LobbyParticipantItems.js rename to react/features/participants-pane/components/web/LobbyParticipantItems.tsx index 6f04d0ba87..8cd478c2d6 100644 --- a/react/features/participants-pane/components/web/LobbyParticipantItems.js +++ b/react/features/participants-pane/components/web/LobbyParticipantItems.tsx @@ -1,25 +1,25 @@ -// @flow - import React from 'react'; +import { IParticipant } from '../../../base/participants/types'; + import { LobbyParticipantItem } from './LobbyParticipantItem'; -type Props = { +interface IProps { /** * Opens a drawer with actions for a knocking participant. */ - openDrawerForParticipant: Function, + openDrawerForParticipant: Function; /** * If a drawer with actions should be displayed. */ - overflowDrawer: boolean, + overflowDrawer: boolean; /** * List with the knocking participants. */ - participants: Array + participants: IParticipant[]; } /** @@ -28,7 +28,7 @@ type Props = { * @param {Object} props - The props of the component. * @returns {ReactNode} */ -function LobbyParticipantItems({ openDrawerForParticipant, overflowDrawer, participants }: Props) { +function LobbyParticipantItems({ openDrawerForParticipant, overflowDrawer, participants }: IProps) { return (
@@ -44,4 +44,4 @@ function LobbyParticipantItems({ openDrawerForParticipant, overflowDrawer, parti } // Memoize the component in order to avoid rerender on drawer open/close. -export default React.memo(LobbyParticipantItems); +export default React.memo(LobbyParticipantItems); diff --git a/react/features/participants-pane/components/web/LobbyParticipants.tsx b/react/features/participants-pane/components/web/LobbyParticipants.tsx index 10169ce5b0..ceb12ea678 100644 --- a/react/features/participants-pane/components/web/LobbyParticipants.tsx +++ b/react/features/participants-pane/components/web/LobbyParticipants.tsx @@ -14,7 +14,6 @@ import JitsiPortal from '../../../toolbox/components/web/JitsiPortal'; import { showOverflowDrawer } from '../../../toolbox/functions.web'; import { useLobbyActions, useParticipantDrawer } from '../../hooks'; -// @ts-ignore import LobbyParticipantItems from './LobbyParticipantItems'; const useStyles = makeStyles()(theme => { diff --git a/react/features/participants-pane/components/web/MeetingParticipantContextMenu.js b/react/features/participants-pane/components/web/MeetingParticipantContextMenu.tsx similarity index 78% rename from react/features/participants-pane/components/web/MeetingParticipantContextMenu.js rename to react/features/participants-pane/components/web/MeetingParticipantContextMenu.tsx index 84424529b7..68b73ecfb1 100644 --- a/react/features/participants-pane/components/web/MeetingParticipantContextMenu.js +++ b/react/features/participants-pane/components/web/MeetingParticipantContextMenu.tsx @@ -1,73 +1,77 @@ -// @flow import React, { Component } from 'react'; import { connect } from 'react-redux'; +import { IReduxState, IStore } from '../../../app/types'; import { translate } from '../../../base/i18n/functions'; import { getLocalParticipant, getParticipantByIdOrUndefined } from '../../../base/participants/functions'; +import { IParticipant } from '../../../base/participants/types'; import FakeParticipantContextMenu from '../../../video-menu/components/web/FakeParticipantContextMenu'; import ParticipantContextMenu from '../../../video-menu/components/web/ParticipantContextMenu'; -type Props = { +interface IProps { /** * Shared video local participant owner. */ - _localVideoOwner: boolean, + _localVideoOwner: boolean; /** * Participant reference. */ - _participant: Object, + _participant?: IParticipant; /** * Closes a drawer if open. */ - closeDrawer: Function, + closeDrawer: () => void; /** * The dispatch function from redux. */ - dispatch: Function, + dispatch: IStore['dispatch']; /** * The participant for which the drawer is open. * It contains the displayName & participantID. */ - drawerParticipant: Object, + drawerParticipant: { + displayName: string; + participantID: string; + }; /** * Target elements against which positioning calculations are made. */ - offsetTarget?: HTMLElement, + offsetTarget?: HTMLElement; /** * Callback for the mouse entering the component. */ - onEnter: Function, + onEnter: (e?: React.MouseEvent) => void; /** * Callback for the mouse leaving the component. */ - onLeave: Function, + onLeave: (e?: React.MouseEvent) => void; /** * Callback for making a selection in the menu. */ - onSelect: Function, + onSelect: (e?: React.MouseEvent | boolean) => void; /** * The ID of the participant. */ - participantID: string -}; + participantID: string; +} /** * Implements the MeetingParticipantContextMenu component. */ -class MeetingParticipantContextMenu extends Component { +class MeetingParticipantContextMenu extends Component { /** * Implements React's {@link Component#render()}. @@ -120,12 +124,12 @@ class MeetingParticipantContextMenu extends Component { * @param {Object} state - The Redux state. * @param {Object} ownProps - The own props of the component. * @private - * @returns {Props} + * @returns {IProps} */ -function _mapStateToProps(state, ownProps) { +function _mapStateToProps(state: IReduxState, ownProps: any) { const { participantID, overflowDrawer, drawerParticipant } = ownProps; const { ownerId } = state['features/shared-video']; - const localParticipantId = getLocalParticipant(state).id; + const localParticipantId = getLocalParticipant(state)?.id; const participant = getParticipantByIdOrUndefined(state, overflowDrawer ? drawerParticipant?.participantID : participantID); diff --git a/react/features/participants-pane/components/web/MeetingParticipantItem.js b/react/features/participants-pane/components/web/MeetingParticipantItem.tsx similarity index 83% rename from react/features/participants-pane/components/web/MeetingParticipantItem.js rename to react/features/participants-pane/components/web/MeetingParticipantItem.tsx index 11796e807c..fb2f25978d 100644 --- a/react/features/participants-pane/components/web/MeetingParticipantItem.js +++ b/react/features/participants-pane/components/web/MeetingParticipantItem.tsx @@ -1,8 +1,7 @@ -// @flow - import React, { useCallback, useEffect, useState } from 'react'; import { connect } from 'react-redux'; +import { IReduxState } from '../../../app/types'; import { JitsiTrackEvents } from '../../../base/lib-jitsi-meet'; import { MEDIA_TYPE } from '../../../base/media/constants'; import { @@ -12,12 +11,14 @@ import { hasRaisedHand, isParticipantModerator } from '../../../base/participants/functions'; +import { IParticipant } from '../../../base/participants/types'; import { getLocalAudioTrack, getTrackByMediaTypeAndParticipant, isParticipantAudioMuted, isParticipantVideoMuted } from '../../../base/tracks/functions.web'; +import { ITrack } from '../../../base/tracks/types'; import { ACTION_TRIGGER, MEDIA_STATE, type MediaState } from '../../constants'; import { getParticipantAudioMediaState, @@ -30,57 +31,57 @@ import ParticipantActionEllipsis from './ParticipantActionEllipsis'; import ParticipantItem from './ParticipantItem'; import ParticipantQuickAction from './ParticipantQuickAction'; -type Props = { +interface IProps { /** * Media state for audio. */ - _audioMediaState: MediaState, + _audioMediaState: MediaState; /** * The audio track related to the participant. */ - _audioTrack: ?Object, + _audioTrack?: ITrack; /** * Whether or not to disable the moderator indicator. */ - _disableModeratorIndicator: boolean, + _disableModeratorIndicator: boolean; /** * The display name of the participant. */ - _displayName: string, + _displayName: string; /** * Whether or not moderation is supported. */ - _isModerationSupported: boolean, + _isModerationSupported: boolean; /** * True if the participant is the local participant. */ - _local: boolean, + _local: boolean; /** * Whether or not the local participant is moderator. */ - _localModerator: boolean, + _localModerator: boolean; /** * Shared video local participant owner. */ - _localVideoOwner: boolean, + _localVideoOwner: boolean; /** * Whether or not the participant name matches the search string. */ - _matchesSearch: boolean, + _matchesSearch: boolean; /** * The participant. */ - _participant: Object, + _participant?: IParticipant; /** * The participant ID. @@ -88,94 +89,94 @@ type Props = { * NOTE: This ID may be different from participantID prop in the case when we pass undefined for the local * participant. In this case the local participant ID will be filled through _participantID prop. */ - _participantID: string, + _participantID: string; /** * The type of button to be rendered for the quick action. */ - _quickActionButtonType: string, + _quickActionButtonType: string; /** * True if the participant have raised hand. */ - _raisedHand: boolean, + _raisedHand: boolean; /** * Media state for video. */ - _videoMediaState: MediaState, + _videoMediaState: MediaState; /** - * The translated ask unmute text for the qiuck action buttons. + * The translated ask unmute text for the quick action buttons. */ - askUnmuteText: string, + askUnmuteText: string; /** * Is this item highlighted. */ - isHighlighted: boolean, + isHighlighted: boolean; /** * Whether or not the local participant is in a breakout room. */ - isInBreakoutRoom: boolean, + isInBreakoutRoom: boolean; /** * Callback used to open a confirmation dialog for audio muting. */ - muteAudio: Function, + muteAudio: Function; /** * The translated text for the mute participant button. */ - muteParticipantButtonText: string, + muteParticipantButtonText: string; /** * Callback for the activation of this item's context menu. */ - onContextMenu: Function, + onContextMenu: () => void; /** * Callback for the mouse leaving this item. */ - onLeave: Function, + onLeave: (e?: React.MouseEvent) => void; /** * Callback used to open an actions drawer for a participant. */ - openDrawerForParticipant: Function, + openDrawerForParticipant: Function; /** * True if an overflow drawer should be displayed. */ - overflowDrawer: boolean, + overflowDrawer: boolean; /** * The aria-label for the ellipsis action. */ - participantActionEllipsisLabel: string, + participantActionEllipsisLabel: string; /** * The ID of the participant. */ - participantID: ?string, + participantID?: string; /** * Callback used to stop a participant's video. */ - stopVideo: Function, + stopVideo: Function; /** * The translated "you" text. */ - youText: string -}; + youText: string; +} /** * Implements the MeetingParticipantItem component. * - * @param {Props} props - The props of the component. + * @param {IProps} props - The props of the component. * @returns {ReactElement} */ function MeetingParticipantItem({ @@ -201,7 +202,7 @@ function MeetingParticipantItem({ participantActionEllipsisLabel, stopVideo, youText -}: Props) { +}: IProps) { const [ hasAudioLevels, setHasAudioLevel ] = useState(false); const [ registeredEvent, setRegisteredEvent ] = useState(false); @@ -227,7 +228,7 @@ function MeetingParticipantItem({ if (_audioTrack && registeredEvent) { const { jitsiTrack } = _audioTrack; - jitsiTrack && jitsiTrack.off(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, _updateAudioLevel); + jitsiTrack?.off(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, _updateAudioLevel); } }; }, [ _audioTrack ]); @@ -292,20 +293,20 @@ function MeetingParticipantItem({ * @param {Object} state - The Redux state. * @param {Object} ownProps - The own props of the component. * @private - * @returns {Props} + * @returns {IProps} */ -function _mapStateToProps(state, ownProps) { +function _mapStateToProps(state: IReduxState, ownProps: any) { const { participantID, searchString } = ownProps; const { ownerId } = state['features/shared-video']; - const localParticipantId = getLocalParticipant(state).id; + const localParticipantId = getLocalParticipant(state)?.id; const participant = getParticipantByIdOrUndefined(state, participantID); - const _displayName = getParticipantDisplayName(state, participant?.id); + const _displayName = getParticipantDisplayName(state, participant?.id ?? ''); const _matchesSearch = participantMatchesSearch(participant, searchString); - const _isAudioMuted = isParticipantAudioMuted(participant, state); + const _isAudioMuted = Boolean(participant && isParticipantAudioMuted(participant, state)); const _isVideoMuted = isParticipantVideoMuted(participant, state); const _audioMediaState = getParticipantAudioMediaState(participant, _isAudioMuted, state); const _videoMediaState = getParticipantVideoMediaState(participant, _isVideoMuted, state); @@ -320,13 +321,13 @@ function _mapStateToProps(state, ownProps) { return { _audioMediaState, _audioTrack, - _disableModeratorIndicator: disableModeratorIndicator, + _disableModeratorIndicator: Boolean(disableModeratorIndicator), _displayName, _local: Boolean(participant?.local), _localVideoOwner: Boolean(ownerId === localParticipantId), _matchesSearch, _participant: participant, - _participantID: participant?.id, + _participantID: participant?.id ?? '', _quickActionButtonType, _raisedHand: hasRaisedHand(participant), _videoMediaState diff --git a/react/features/participants-pane/components/web/MeetingParticipantItems.js b/react/features/participants-pane/components/web/MeetingParticipantItems.tsx similarity index 75% rename from react/features/participants-pane/components/web/MeetingParticipantItems.js rename to react/features/participants-pane/components/web/MeetingParticipantItems.tsx index 5b786007ec..6434f5dc9c 100644 --- a/react/features/participants-pane/components/web/MeetingParticipantItems.js +++ b/react/features/participants-pane/components/web/MeetingParticipantItems.tsx @@ -1,80 +1,78 @@ -// @flow - import React from 'react'; import MeetingParticipantItem from './MeetingParticipantItem'; -type Props = { +interface IProps { /** - * The translated ask unmute text for the qiuck action buttons. + * The translated ask unmute text for the quick action buttons. */ - askUnmuteText: string, + askUnmuteText?: string; /** * Whether or not the local participant is in a breakout room. */ - isInBreakoutRoom: boolean, + isInBreakoutRoom: boolean; /** * Callback for the mouse leaving this item. */ - lowerMenu: Function, - - /** - * Callback for the activation of this item's context menu. - */ - toggleMenu: Function, + lowerMenu: Function; /** * Callback used to open a confirmation dialog for audio muting. */ - muteAudio: Function, + muteAudio: Function; /** * The translated text for the mute participant button. */ - muteParticipantButtonText: string, - - /** - * The meeting participants. - */ - participantIds: Array, + muteParticipantButtonText?: string; /** * Callback used to open an actions drawer for a participant. */ - openDrawerForParticipant: Function, + openDrawerForParticipant: Function; /** * True if an overflow drawer should be displayed. */ - overflowDrawer: boolean, - - /** - * The if of the participant for which the context menu should be open. - */ - raiseContextId?: string, + overflowDrawer?: boolean; /** * The aria-label for the ellipsis action. */ - participantActionEllipsisLabel: string, + participantActionEllipsisLabel: string; + + /** + * The meeting participants. + */ + participantIds: Array; + + /** + * The if of the participant for which the context menu should be open. + */ + raiseContextId?: string; /** * Current search string. */ - searchString?: string, + searchString?: string; /** * Callback used to stop a participant's video. */ - stopVideo: Function, + stopVideo: Function; + + /** + * Callback for the activation of this item's context menu. + */ + toggleMenu: Function; /** * The translated "you" text. */ - youText: string + youText: string; } /** @@ -95,8 +93,8 @@ function MeetingParticipantItems({ searchString, stopVideo, youText -}: Props) { - const renderParticipant = id => ( +}: IProps) { + const renderParticipant = (id: string) => ( ); - return participantIds.map(renderParticipant); + return (<> + {participantIds.map(renderParticipant)} + ); } // Memoize the component in order to avoid rerender on drawer open/close. -export default React.memo(MeetingParticipantItems); +export default React.memo(MeetingParticipantItems); diff --git a/react/features/participants-pane/components/web/MeetingParticipants.tsx b/react/features/participants-pane/components/web/MeetingParticipants.tsx index 4ff7df115a..50bbb30994 100644 --- a/react/features/participants-pane/components/web/MeetingParticipants.tsx +++ b/react/features/participants-pane/components/web/MeetingParticipants.tsx @@ -1,4 +1,3 @@ -/* eslint-disable lines-around-comment */ import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { connect, useDispatch, useSelector } from 'react-redux'; @@ -21,11 +20,8 @@ import { getSortedParticipantIds, shouldRenderInviteButton } from '../../functio import { useParticipantDrawer } from '../../hooks'; import { InviteButton } from './InviteButton'; -// @ts-ignore import MeetingParticipantContextMenu from './MeetingParticipantContextMenu'; -// @ts-ignore import MeetingParticipantItems from './MeetingParticipantItems'; -/* eslint-enable lines-around-comment */ const useStyles = makeStyles()(theme => { return { @@ -140,7 +136,6 @@ function MeetingParticipants({ overflowDrawer = { overflowDrawer } participantActionEllipsisLabel = { participantActionEllipsisLabel } participantIds = { sortedParticipantIds } - participantsCount = { participantsCount } raiseContextId = { raiseContext.entity } searchString = { normalizeAccents(searchString) } stopVideo = { stopVideo } diff --git a/react/features/participants-pane/components/web/ParticipantItem.tsx b/react/features/participants-pane/components/web/ParticipantItem.tsx index c86c99a5ca..aba68e037f 100644 --- a/react/features/participants-pane/components/web/ParticipantItem.tsx +++ b/react/features/participants-pane/components/web/ParticipantItem.tsx @@ -1,4 +1,4 @@ -import React, { ReactElement, useCallback } from 'react'; +import React, { ReactNode, useCallback } from 'react'; import { WithTranslation } from 'react-i18next'; import { makeStyles } from 'tss-react/mui'; @@ -32,7 +32,7 @@ interface IProps extends WithTranslation { /** * React children. */ - children?: ReactElement | boolean; + children?: ReactNode; /** * Whether or not to disable the moderator indicator. diff --git a/react/features/participants-pane/components/web/ParticipantQuickAction.tsx b/react/features/participants-pane/components/web/ParticipantQuickAction.tsx index ee176aa7f2..906f74c258 100644 --- a/react/features/participants-pane/components/web/ParticipantQuickAction.tsx +++ b/react/features/participants-pane/components/web/ParticipantQuickAction.tsx @@ -17,7 +17,7 @@ interface IProps { /** * The translated "ask unmute" text. */ - askUnmuteText: string; + askUnmuteText?: string; /** * The type of button to be displayed. @@ -32,7 +32,7 @@ interface IProps { /** * Label for mute participant button. */ - muteParticipantButtonText: string; + muteParticipantButtonText?: string; /** * The ID of the participant. diff --git a/react/features/participants-pane/functions.ts b/react/features/participants-pane/functions.ts index 08f9369cba..9638b774cc 100644 --- a/react/features/participants-pane/functions.ts +++ b/react/features/participants-pane/functions.ts @@ -57,7 +57,8 @@ export function isForceMuted(participant: IParticipant | undefined, mediaType: M * @param {IReduxState} state - The redux state. * @returns {MediaState} */ -export function getParticipantAudioMediaState(participant: IParticipant, muted: Boolean, state: IReduxState) { +export function getParticipantAudioMediaState(participant: IParticipant | undefined, + muted: Boolean, state: IReduxState) { const dominantSpeaker = getDominantSpeakerParticipant(state); if (muted) { @@ -83,7 +84,8 @@ export function getParticipantAudioMediaState(participant: IParticipant, muted: * @param {IReduxState} state - The redux state. * @returns {MediaState} */ -export function getParticipantVideoMediaState(participant: IParticipant, muted: Boolean, state: IReduxState) { +export function getParticipantVideoMediaState(participant: IParticipant | undefined, + muted: Boolean, state: IReduxState) { if (muted) { if (isForceMuted(participant, MEDIA_TYPE.VIDEO, state)) { return MEDIA_STATE.FORCE_MUTED; @@ -136,7 +138,7 @@ export const getParticipantsPaneOpen = (state: IReduxState) => Boolean(getState( * @returns {string} - The type of the quick action button. */ export function getQuickActionButtonType( - participant: IParticipant, + participant: IParticipant | undefined, isAudioMuted: Boolean, isVideoMuted: Boolean, state: IReduxState) { @@ -232,8 +234,9 @@ export function getSortedParticipantIds(stateful: IStateful) { * @param {string} searchString - The participants search string. * @returns {boolean} */ -export function participantMatchesSearch(participant: { displayName: string; jid: string; name?: string; }, - searchString: string) { +export function participantMatchesSearch(participant: IParticipant | undefined + | { displayName?: string; name?: string; }, +searchString: string) { if (searchString === '') { return true; } diff --git a/react/features/presence-status/components/PresenceLabel.js b/react/features/presence-status/components/PresenceLabel.tsx similarity index 85% rename from react/features/presence-status/components/PresenceLabel.js rename to react/features/presence-status/components/PresenceLabel.tsx index 63ac20b7de..9b2cb24f32 100644 --- a/react/features/presence-status/components/PresenceLabel.js +++ b/react/features/presence-status/components/PresenceLabel.tsx @@ -1,8 +1,8 @@ -/* @flow */ - import React, { Component } from 'react'; +import { WithTranslation } from 'react-i18next'; import { connect } from 'react-redux'; +import { IReduxState } from '../../app/types'; import { translate } from '../../base/i18n/functions'; import { getParticipantById } from '../../base/participants/functions'; import { Text } from '../../base/react/components/index'; @@ -12,40 +12,35 @@ import { presenceStatusDisabled } from '../functions'; /** * The type of the React {@code Component} props of {@link PresenceLabel}. */ -type Props = { +interface IProps extends WithTranslation { /** * The current present status associated with the passed in participantID * prop. */ - _presence: string, + _presence: string; /** * Class name for the presence label. */ - className: string, + className: string; /** * Default presence status that will be displayed if user's presence status * is not available. */ - defaultPresence: string, + defaultPresence: string; /** * The ID of the participant whose presence status should display. */ - participantID: string, + participantID: string; /** * Styles for the presence label. */ - style: Object, - - /** - * Invoked to obtain translated strings. - */ - t: Function -}; + style: Object; +} /** * React {@code Component} for displaying the current presence status of a @@ -53,7 +48,7 @@ type Props = { * * @augments Component */ -class PresenceLabel extends Component { +class PresenceLabel extends Component { /** * The default values for {@code PresenceLabel} component's property types. * @@ -98,7 +93,7 @@ class PresenceLabel extends Component { return null; } - const i18nKey = STATUS_TO_I18N_KEY[_presence]; + const i18nKey = STATUS_TO_I18N_KEY[_presence as keyof typeof STATUS_TO_I18N_KEY]; if (!i18nKey) { // fallback to status value return _presence; @@ -120,7 +115,7 @@ class PresenceLabel extends Component { * _presence: (string|undefined) * }} */ -function _mapStateToProps(state, ownProps) { +function _mapStateToProps(state: IReduxState, ownProps: any) { const participant = getParticipantById(state, ownProps.participantID); return { diff --git a/react/features/reactions/components/web/ReactionButton.tsx b/react/features/reactions/components/web/ReactionButton.tsx index 309968e1f2..9fffce43db 100644 --- a/react/features/reactions/components/web/ReactionButton.tsx +++ b/react/features/reactions/components/web/ReactionButton.tsx @@ -1,6 +1,7 @@ import React from 'react'; import Tooltip from '../../../base/tooltip/components/Tooltip'; +import { TOOLTIP_POSITION } from '../../../base/ui/constants.any'; import AbstractToolbarButton, { IProps as AbstractToolbarButtonProps } from '../../../toolbox/components/AbstractToolbarButton'; @@ -24,7 +25,7 @@ interface IProps extends AbstractToolbarButtonProps { * From which direction the tooltip should appear, relative to the * button. */ - tooltipPosition: 'top' | 'bottom' | 'left' | 'right'; + tooltipPosition: TOOLTIP_POSITION; } /** diff --git a/react/features/video-menu/components/web/LocalVideoMenuTriggerButton.tsx b/react/features/video-menu/components/web/LocalVideoMenuTriggerButton.tsx index 47019ac821..4a5ffd37f0 100644 --- a/react/features/video-menu/components/web/LocalVideoMenuTriggerButton.tsx +++ b/react/features/video-menu/components/web/LocalVideoMenuTriggerButton.tsx @@ -79,17 +79,17 @@ interface IProps { /** * Hides popover. */ - hidePopover: Function; + hidePopover?: Function; /** * Whether the popover is visible or not. */ - popoverVisible: boolean; + popoverVisible?: boolean; /** * Shows popover. */ - showPopover: Function; + showPopover?: Function; /** * The type of the thumbnail. @@ -141,12 +141,12 @@ const LocalVideoMenuTriggerButton = ({ const { t } = useTranslation(); const _onPopoverOpen = useCallback(() => { - showPopover(); + showPopover?.(); dispatch(setParticipantContextMenuOpen(true)); }, []); const _onPopoverClose = useCallback(() => { - hidePopover(); + hidePopover?.(); batch(() => { dispatch(setParticipantContextMenuOpen(false)); dispatch(renderConnectionStatus(false)); @@ -194,7 +194,7 @@ const LocalVideoMenuTriggerButton = ({ onPopoverClose = { _onPopoverClose } onPopoverOpen = { _onPopoverOpen } position = { _menuPosition } - visible = { popoverVisible }> + visible = { Boolean(popoverVisible) }> {buttonVisible && !isMobileBrowser() && (