diff --git a/react/features/base/components/context-menu/ContextMenuItemGroup.js b/react/features/base/components/context-menu/ContextMenuItemGroup.js index 1e59eb8ef..406962faa 100644 --- a/react/features/base/components/context-menu/ContextMenuItemGroup.js +++ b/react/features/base/components/context-menu/ContextMenuItemGroup.js @@ -2,14 +2,15 @@ import { makeStyles } from '@material-ui/core'; import React from 'react'; -import ContextMenuItem, { type Props as Action } from './ContextMenuItem'; +import ContextMenuItem from './ContextMenuItem'; + type Props = { /** * List of actions in this group. */ - actions?: Array, + actions?: Array, /** * The children of the component. diff --git a/react/features/base/components/context-menu/useContextMenu.js b/react/features/base/components/context-menu/useContextMenu.js index 5e43d3bc1..84d7c14e0 100644 --- a/react/features/base/components/context-menu/useContextMenu.js +++ b/react/features/base/components/context-menu/useContextMenu.js @@ -4,12 +4,7 @@ import { useCallback, useRef, useState } from 'react'; import { findAncestorByClass } from '../../../participants-pane/functions'; -type NullProto = { - [key: string]: any, - __proto__: null -}; - -type RaiseContext = NullProto | {| +type RaiseContext = {| /** * Target elements against which positioning calculations are made. @@ -22,7 +17,7 @@ type RaiseContext = NullProto | {| entity?: string | Object, |}; -const initialState = Object.freeze(Object.create(null)); +const initialState = Object.freeze({}); const useContextMenu = () => { const [ raiseContext, setRaiseContext ] = useState < RaiseContext >(initialState); diff --git a/react/features/base/dialog/components/native/InputDialog.js b/react/features/base/dialog/components/native/InputDialog.js index 59f1f6e93..0ee43f76c 100644 --- a/react/features/base/dialog/components/native/InputDialog.js +++ b/react/features/base/dialog/components/native/InputDialog.js @@ -70,7 +70,8 @@ class InputDialog extends BaseDialog { super(props); this.state = { - fieldValue: props.initialValue + fieldValue: props.initialValue, + submitting: false }; this._onChangeText = this._onChangeText.bind(this); diff --git a/react/features/base/media/components/native/VideoTransform.js b/react/features/base/media/components/native/VideoTransform.js index cb7250128..038449895 100644 --- a/react/features/base/media/components/native/VideoTransform.js +++ b/react/features/base/media/components/native/VideoTransform.js @@ -1,6 +1,5 @@ // @flow -import type { PanResponderInstance } from 'PanResponder'; import React, { Component } from 'react'; import { PanResponder, PixelRatio, View } from 'react-native'; import { type Dispatch } from 'redux'; @@ -119,12 +118,12 @@ class VideoTransform extends Component { /** * The gesture handler object. */ - gestureHandlers: PanResponderInstance; + gestureHandlers: Object; /** * The initial distance of the fingers on pinch start. */ - initialDistance: number; + initialDistance: ?number; /** * The initial position of the finger on touch start. @@ -628,7 +627,10 @@ class VideoTransform extends Component { this._onGesture('press'); } delete this.initialDistance; - delete this.initialPosition; + this.initialPosition = { + x: 0, + y: 0 + }; } _onStartShouldSetPanResponder: () => boolean; diff --git a/react/features/base/media/constants.js b/react/features/base/media/constants.js index fafdbe757..a54349732 100644 --- a/react/features/base/media/constants.js +++ b/react/features/base/media/constants.js @@ -17,7 +17,7 @@ export type MediaType = 'audio' | 'video' | 'presenter'; * * @enum {string} */ -export const MEDIA_TYPE: { AUDIO: MediaType, PRESENTER: MediaType, VIDEO: MediaType} = { +export const MEDIA_TYPE = { AUDIO: 'audio', PRESENTER: 'presenter', VIDEO: 'video' diff --git a/react/features/base/react/Types.js b/react/features/base/react/Types.js index c2e07b5d4..417bfe103 100644 --- a/react/features/base/react/Types.js +++ b/react/features/base/react/Types.js @@ -1,6 +1,6 @@ // @flow -import type { ComponentType, Element } from 'react'; +import type { ComponentType } from 'react'; /** * Item data for NavigateSectionList. @@ -73,7 +73,7 @@ export type Section = { keyExtractor?: (item: Object) => string, - renderItem?: ?(info: Object) => ?Element + renderItem?: ?(info: Object) => null | React$Element } diff --git a/react/features/base/react/components/native/Container.js b/react/features/base/react/components/native/Container.js index 488f603f1..8e098c9a5 100644 --- a/react/features/base/react/components/native/Container.js +++ b/react/features/base/react/components/native/Container.js @@ -40,6 +40,8 @@ export default class Container extends AbstractContainer

{ touchFeedback = Boolean(onClick || onLongPress), underlayColor, visible = true, + + // $FlowExpectedError ...props } = this.props; diff --git a/react/features/base/react/components/native/LoadingIndicator.js b/react/features/base/react/components/native/LoadingIndicator.js index bd1332d59..a386e2b69 100644 --- a/react/features/base/react/components/native/LoadingIndicator.js +++ b/react/features/base/react/components/native/LoadingIndicator.js @@ -1,11 +1,11 @@ /* @flow */ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import { ActivityIndicator } from 'react-native'; import { ColorPalette } from '../../../styles'; -type Props = { +type Props = {| /** * The color of the spinner. @@ -17,14 +17,14 @@ type Props = { * prop of the native component. */ size: 'large' | 'small' -}; +|}; /** * An animated, large react-native {@link ActivityIndicator} which is considered * a suitable visualization of long-running processes with indeterminate amounts * of work to be done. */ -export default class LoadingIndicator extends Component { +export default class LoadingIndicator extends PureComponent { /** * Implements React's {@link Component#render()}. * diff --git a/react/features/base/react/components/native/Modal.js b/react/features/base/react/components/native/Modal.js index 22c50e60c..cc83f52da 100644 --- a/react/features/base/react/components/native/Modal.js +++ b/react/features/base/react/components/native/Modal.js @@ -1,33 +1,11 @@ -// @flow - -import React, { Component, type Node } from 'react'; +import React, { PureComponent } from 'react'; import { Modal as NativeModal } from 'react-native'; -/** - * Type of the props of the component. - */ -type Props = { - - /** - * Children of the component. - */ - children: Node - - /** - * NOTE: We pass through all props to {@code react-native#Modal} that are - * passed to this component, so we don't list them all here, as that would - * be an unnecessary duplication and probably an unmaintained list after a - * while. - * - * See list: https://facebook.github.io/react-native/docs/modal. - */ -}; - /** * Implements a generic Modal (using the built-in Modal component) to share - * behaviour across modals in the app. + * behavior across modals in the app. */ -export default class Modal extends Component { +export default class Modal extends PureComponent { /** * Implements {@code Component#render}. @@ -35,6 +13,7 @@ export default class Modal extends Component { * @inheritdoc */ render() { + // eslint-disable-next-line react/prop-types const { children, ...props } = this.props; return ( diff --git a/react/features/base/react/components/native/PagedList.js b/react/features/base/react/components/native/PagedList.js index 7b54d8a54..cf4edfb93 100644 --- a/react/features/base/react/components/native/PagedList.js +++ b/react/features/base/react/components/native/PagedList.js @@ -92,6 +92,20 @@ class PagedList extends Component { render() { const { disabled } = this.props; const pages = this.props.pages.filter(({ component }) => component); + let children; + + if (pages.length > 1) { + children = this._renderPagedList(disabled); + } else { + children = React.createElement( + + // $FlowExpectedError + /* type */ pages[0].component, + /* props */ { + disabled, + style: styles.pagedList + }); + } return ( { disabled ? styles.pagedListContainerDisabled : null ] }> { - pages.length > 1 - ? this._renderPagedList(disabled) - : React.createElement( - // $FlowExpectedError - /* type */ pages[0].component, - /* props */ { - disabled, - style: styles.pagedList - }) + // $FlowExpectedError + children } ); diff --git a/react/features/base/react/components/web/Switch.js b/react/features/base/react/components/web/Switch.js index 112cdae5e..1a0ade630 100644 --- a/react/features/base/react/components/web/Switch.js +++ b/react/features/base/react/components/web/Switch.js @@ -3,7 +3,7 @@ import Toggle from '@atlaskit/toggle'; import React, { Component } from 'react'; -type Props = { +type Props = {| /** * ID of the toggle. @@ -29,7 +29,7 @@ type Props = { * The current value. */ value: boolean -}; +|}; /** * Renders a boolean input. diff --git a/react/features/base/toolbox/components/AbstractButton.js b/react/features/base/toolbox/components/AbstractButton.js index 2219d0c8a..a4158e294 100644 --- a/react/features/base/toolbox/components/AbstractButton.js +++ b/react/features/base/toolbox/components/AbstractButton.js @@ -8,7 +8,7 @@ import { combineStyles } from '../../styles'; import type { Styles } from './AbstractToolboxItem'; import ToolboxItem from './ToolboxItem'; -export type Props = { +export type Props = {| /** * Function to be called after the click handler has been processed. @@ -20,6 +20,12 @@ export type Props = { */ buttonKey?: string, + /** + * An extra class name to be added at the end of the element's class name + * in order to enable custom styling. + */ + customClass?: string, + /** * Extra styles which will be applied in conjunction with `styles` or * `toggledStyles` when the button is disabled;. @@ -29,7 +35,7 @@ export type Props = { /** * External handler for click action. */ - handleClick?: Function, + handleClick?: Function, /** * Notify mode for `toolbarButtonClicked` event - @@ -61,7 +67,7 @@ export type Props = { * Whether this button is visible or not. */ visible: boolean -}; +|}; declare var APP: Object; @@ -312,7 +318,6 @@ export default class AbstractButton extends Component { const props = { ...this.props, accessibilityLabel: this.accessibilityLabel, - disabled: this._isDisabled(), elementAfter: this._getElementAfter(), icon: this._getIcon(), label: this._getLabel(), diff --git a/react/features/base/toolbox/components/AbstractToolboxItem.js b/react/features/base/toolbox/components/AbstractToolboxItem.js index 04d52b90f..2f5034d39 100644 --- a/react/features/base/toolbox/components/AbstractToolboxItem.js +++ b/react/features/base/toolbox/components/AbstractToolboxItem.js @@ -86,7 +86,7 @@ export type Props = { /** * True if the item is toggled, false otherwise. */ - toggled: boolean, + toggled: ?boolean, /** * The text to display in the tooltip. Used only on web. diff --git a/react/features/base/toolbox/components/ToolboxItem.native.js b/react/features/base/toolbox/components/ToolboxItem.native.js index 819ddf82a..6378bdcfc 100644 --- a/react/features/base/toolbox/components/ToolboxItem.native.js +++ b/react/features/base/toolbox/components/ToolboxItem.native.js @@ -74,7 +74,7 @@ export default class ToolboxItem extends AbstractToolboxItem { void; + _changeState: (symbol) => void; /** * Changes the current state of {@code RecordingController}. * * @private - * @param {Symbol} newState - The new state. + * @param {symbol} newState - The new state. * @returns {void} */ - _changeState(newState: Symbol) { + _changeState(newState: symbol) { if (this._state !== newState) { logger.log(`state change: ${this._state.toString()} -> ` + `${newState.toString()}`); diff --git a/react/features/overlay/middleware.js b/react/features/overlay/middleware.js index cc5f023ee..074289994 100644 --- a/react/features/overlay/middleware.js +++ b/react/features/overlay/middleware.js @@ -11,6 +11,27 @@ import { setFatalError } from './actions'; declare var APP: Object; +/** + * Error type. Basically like Error, but augmented with a recoverable property. + */ +type ErrorType = {| + + /** + * Error message. + */ + message?: string, + + /** + * Error name. + */ + name: string, + + /** + * Indicates whether this event is recoverable or not. + */ + recoverable?: boolean +|}; + /** * List of errors that are not fatal (or handled differently) so then the overlays won't kick in. */ @@ -74,16 +95,14 @@ StateListenerRegistry.register( return configError || connectionError || conferenceError; }, - /* listener */ (error, { dispatch, getState }) => { + /* listener */ (error: ErrorType, { dispatch, getState }) => { if (!error) { return; } if (typeof APP !== 'undefined') { - const parsedError = typeof error === 'string' ? { name: error } : error; - APP.API.notifyError({ - ...parsedError, + ...error, ...getErrorExtraInfo(getState, error) }); } diff --git a/react/features/participants-pane/constants.js b/react/features/participants-pane/constants.js index f1210cb70..87eefa0e2 100644 --- a/react/features/participants-pane/constants.js +++ b/react/features/participants-pane/constants.js @@ -30,13 +30,7 @@ export type MediaState = 'DominantSpeaker' | 'Muted' | 'ForceMuted' | 'Unmuted' /** * Enum of possible participant media states. */ -export const MEDIA_STATE: { - DOMINANT_SPEAKER: MediaState, - MUTED: MediaState, - FORCE_MUTED: MediaState, - UNMUTED: MediaState, - NONE: MediaState, -} = { +export const MEDIA_STATE = { DOMINANT_SPEAKER: 'DominantSpeaker', MUTED: 'Muted', FORCE_MUTED: 'ForceMuted', @@ -92,6 +86,7 @@ export const AudioStateIcons: {[MediaState]: React$Element | null} = { * Icon mapping for possible participant video states. */ export const VideoStateIcons = { + [MEDIA_STATE.DOMINANT_SPEAKER]: null, [MEDIA_STATE.FORCE_MUTED]: ( diff --git a/react/features/toolbox/components/native/ScreenSharingIosButton.js b/react/features/toolbox/components/native/ScreenSharingIosButton.js index da1a526bb..366df63d4 100644 --- a/react/features/toolbox/components/native/ScreenSharingIosButton.js +++ b/react/features/toolbox/components/native/ScreenSharingIosButton.js @@ -143,7 +143,9 @@ function _mapStateToProps(state): Object { _screensharing: isLocalVideoTrackDesktop(state), // TODO: this should work on iOS 12 too, but our trick to show the picker doesn't work. - visible: enabled && Platform.OS === 'ios' && Platform.Version.split('.')[0] >= 14 + visible: enabled + && Platform.OS === 'ios' + && Number.parseInt(Platform.Version.split('.')[0], 10) >= 14 }; } diff --git a/react/features/toolbox/middleware.js b/react/features/toolbox/middleware.js index a2b6429f9..d4289acc6 100644 --- a/react/features/toolbox/middleware.js +++ b/react/features/toolbox/middleware.js @@ -84,16 +84,17 @@ function _setFullScreen(next, action) { return result; } - // $FlowFixMe if (typeof document.exitFullscreen === 'function') { document.exitFullscreen(); - // $FlowFixMe + // $FlowExpectedError } else if (typeof document.mozCancelFullScreen === 'function') { + // $FlowExpectedError document.mozCancelFullScreen(); - // $FlowFixMe + // $FlowExpectedError } else if (typeof document.webkitExitFullscreen === 'function') { + // $FlowExpectedError document.webkitExitFullscreen(); } } diff --git a/react/features/video-quality/subscriber.js b/react/features/video-quality/subscriber.js index 6555b6089..13d762d9d 100644 --- a/react/features/video-quality/subscriber.js +++ b/react/features/video-quality/subscriber.js @@ -200,15 +200,16 @@ function _updateReceiverVideoConstraints({ getState }) { const sourceNameSignaling = getSourceNameSignalingFeatureFlag(state); const localParticipantId = getLocalParticipant(state).id; - const receiverConstraints = { - constraints: {}, - defaultConstraints: { 'maxHeight': VIDEO_QUALITY_LEVELS.NONE }, - lastN, - ...sourceNameSignaling ? { onStageSources: [] } : { onStageEndpoints: [] }, - ...sourceNameSignaling ? { selectedSources: [] } : { selectedEndpoints: [] } - }; + let receiverConstraints; if (sourceNameSignaling) { + receiverConstraints = { + constraints: {}, + defaultConstraints: { 'maxHeight': VIDEO_QUALITY_LEVELS.NONE }, + lastN, + onStageSources: [], + selectedSources: [] + }; const visibleRemoteTrackSourceNames = []; let largeVideoSourceName; @@ -267,6 +268,14 @@ function _updateReceiverVideoConstraints({ getState }) { } } else { + receiverConstraints = { + constraints: {}, + defaultConstraints: { 'maxHeight': VIDEO_QUALITY_LEVELS.NONE }, + lastN, + onStageEndpoints: [], + selectedEndpoints: [] + }; + // Tile view. // eslint-disable-next-line no-lonely-if if (shouldDisplayTileView(state)) { diff --git a/react/features/virtual-background/functions.js b/react/features/virtual-background/functions.js index 655400798..e5f0c6cd2 100644 --- a/react/features/virtual-background/functions.js +++ b/react/features/virtual-background/functions.js @@ -34,7 +34,7 @@ export const blobToData = (blob: Blob): Promise => new Promise(resolve => { const reader = new FileReader(); - reader.onloadend = () => resolve(reader.result.toString()); + reader.onloadend = () => resolve(reader.result?.toString()); reader.readAsDataURL(blob); });