ref: Convert files to TS (#12007)

Convert files that use material-ui to TS (needed for material-ui upgrade)
This commit is contained in:
Robert Pintilii 2022-08-26 12:54:03 +03:00 committed by GitHub
parent fc60ab8383
commit 3bd3be4df0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 534 additions and 518 deletions

19
package-lock.json generated
View File

@ -143,6 +143,7 @@
"@types/react": "17.0.14",
"@types/react-native": "0.68.1",
"@types/react-redux": "7.1.24",
"@types/react-window": "1.8.5",
"@types/unorm": "1.3.28",
"@types/uuid": "8.3.4",
"@types/zxcvbn": "4.4.1",
@ -5534,6 +5535,15 @@
"@types/react": "*"
}
},
"node_modules/@types/react-window": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.5.tgz",
"integrity": "sha512-V9q3CvhC9Jk9bWBOysPGaWy/Z0lxYcTXLtLipkt2cnRj1JOSFNF7wqGpkScSXMgBwC+fnVRg/7shwgddBG5ICw==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/retry": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz",
@ -23993,6 +24003,15 @@
"@types/react": "*"
}
},
"@types/react-window": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.5.tgz",
"integrity": "sha512-V9q3CvhC9Jk9bWBOysPGaWy/Z0lxYcTXLtLipkt2cnRj1JOSFNF7wqGpkScSXMgBwC+fnVRg/7shwgddBG5ICw==",
"dev": true,
"requires": {
"@types/react": "*"
}
},
"@types/retry": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz",

View File

@ -148,6 +148,7 @@
"@types/react": "17.0.14",
"@types/react-native": "0.68.1",
"@types/react-redux": "7.1.24",
"@types/react-window": "1.8.5",
"@types/unorm": "1.3.28",
"@types/uuid": "8.3.4",
"@types/zxcvbn": "4.4.1",

View File

@ -1,5 +1,3 @@
// @flow
import { PureComponent } from 'react';
export type Props = {
@ -32,21 +30,21 @@ export type Props = {
/**
* The URL of the avatar to render.
*/
url?: ?string | Object
url?: string|Function
};
/**
* Implements an abstract stateless avatar component that renders an avatar purely from what gets passed through
* props.
*/
export default class AbstractStatelessAvatar<P: Props> extends PureComponent<P> {
export default class AbstractStatelessAvatar<P extends Props> extends PureComponent<P> {
/**
* Checks if the passed prop is a loaded icon or not.
*
* @param {string? | Object?} iconProp - The prop to check.
* @returns {boolean}
*/
_isIcon(iconProp: ?string | ?Object): boolean {
_isIcon(iconProp?: string | Function): iconProp is Function {
return Boolean(iconProp) && (typeof iconProp === 'object' || typeof iconProp === 'function');
}
}

View File

@ -1,25 +1,23 @@
// @flow
import { withStyles } from '@material-ui/core/styles';
import clsx from 'clsx';
import React from 'react';
import { Icon } from '../../../icons';
import Icon from '../../../icons/components/Icon';
import AbstractStatelessAvatar, { type Props as AbstractProps } from '../AbstractStatelessAvatar';
import { PRESENCE_AVAILABLE_COLOR, PRESENCE_AWAY_COLOR, PRESENCE_BUSY_COLOR, PRESENCE_IDLE_COLOR } from '../styles';
type Props = AbstractProps & {
/**
* An object containing the CSS classes.
*/
classes: Object,
/**
* External class name passed through props.
*/
className?: string,
/**
* An object containing the CSS classes.
*/
classes: any,
/**
* The default avatar URL if we want to override the app bundled one (e.g. AlwaysOnTop).
*/
@ -33,7 +31,7 @@ type Props = AbstractProps & {
/**
* One of the expected status strings (e.g. 'available') to render a badge on the avatar, if necessary.
*/
status?: ?string,
status?: string,
/**
* TestId of the element, if any.
@ -43,7 +41,7 @@ type Props = AbstractProps & {
/**
* Indicates whether to load the avatar using CORS or not.
*/
useCORS?: ?boolean
useCORS?: boolean
};
/**
@ -211,10 +209,10 @@ class StatelessAvatar extends AbstractStatelessAvatar<Props> {
/**
* Constructs a style object to be used on the avatars.
*
* @param {string?} color - The desired background color.
* @param {string} color - The desired background color.
* @returns {Object}
*/
_getAvatarStyle(color) {
_getAvatarStyle(color?: string) {
const { size } = this.props;
return {
@ -231,7 +229,7 @@ class StatelessAvatar extends AbstractStatelessAvatar<Props> {
* @param {string} additional - Any additional class to add.
* @returns {string}
*/
_getAvatarClassName(additional) {
_getAvatarClassName(additional?: string) {
return clsx('avatar', additional, this.props.className, this.props.classes.avatar);
}
@ -250,10 +248,6 @@ class StatelessAvatar extends AbstractStatelessAvatar<Props> {
return '';
}
_isIcon: (?string | ?Object) => boolean;
_onAvatarLoadError: () => void;
/**
* Handles avatar load errors.
*
@ -268,4 +262,5 @@ class StatelessAvatar extends AbstractStatelessAvatar<Props> {
}
}
// @ts-ignore
export default withStyles(styles)(StatelessAvatar);

View File

@ -1,17 +1,15 @@
// @flow
/* eslint-disable react/jsx-no-bind */
import { withStyles } from '@material-ui/styles';
import clsx from 'clsx';
import React, { useEffect, useState } from 'react';
import { Icon, IconCheck, IconCopy } from '../../base/icons';
import Icon from '../icons/components/Icon';
import { IconCheck, IconCopy } from '../icons/svg/index';
import { withPixelLineHeight } from '../styles/functions.web';
import { copyText } from '../util';
import { Theme } from '../ui/types';
import { copyText } from '../util/helpers';
const styles = theme => {
const styles = (theme: Theme) => {
return {
copyButton: {
...withPixelLineHeight(theme.typography.bodyLongRegular),
@ -54,34 +52,29 @@ const styles = theme => {
};
};
let mounted;
let mounted: boolean;
type Props = {
/**
* An object containing the CSS classes.
*/
classes: Object,
/**
* Css class to apply on container.
*/
className: string,
/**
* An object containing the CSS classes.
*/
classes: any,
/**
* The displayed text.
*/
displayedText: string,
/**
* The text that needs to be copied (might differ from the displayedText).
* The id of the button.
*/
textToCopy: string,
/**
* The text displayed on mouse hover.
*/
textOnHover: string,
id?: string,
/**
* The text displayed on copy success.
@ -89,9 +82,14 @@ type Props = {
textOnCopySuccess: string,
/**
* The id of the button.
* The text displayed on mouse hover.
*/
id?: string,
textOnHover: string,
/**
* The text that needs to be copied (might differ from the displayedText).
*/
textToCopy: string
};
/**
@ -160,7 +158,7 @@ function CopyButton({ classes, className, displayedText, textToCopy, textOnHover
*
* @returns {void}
*/
function onKeyPress(e) {
function onKeyPress(e: React.KeyboardEvent) {
if (onClick && (e.key === ' ' || e.key === 'Enter')) {
e.preventDefault();
onClick();
@ -216,4 +214,5 @@ CopyButton.defaultProps = {
className: ''
};
// @ts-ignore
export default withStyles(styles)(CopyButton);

View File

@ -1,11 +1,14 @@
// @flow
/* eslint-disable lines-around-comment */
import { makeStyles } from '@material-ui/core';
import clsx from 'clsx';
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
import React, { ReactNode, useEffect, useLayoutEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux';
// @ts-ignore
import { getComputedOuterHeight } from '../../../participants-pane/functions';
// @ts-ignore
import { Drawer, JitsiPortal } from '../../../toolbox/components/web';
// @ts-ignore
import { showOverflowDrawer } from '../../../toolbox/functions.web';
import participantsPaneTheme from '../themes/participantsPaneTheme.json';
@ -19,12 +22,12 @@ type Props = {
/**
* Children of the context menu.
*/
children: React$Node,
children: ReactNode,
/**
* Class name for context menu. Used to overwrite default styles.
*/
className?: ?string,
className?: string,
/**
* The entity for which the context menu is displayed.
@ -39,7 +42,7 @@ type Props = {
/**
* Whether or not the menu is already in a drawer.
*/
inDrawer?: ?boolean,
inDrawer?: boolean,
/**
* Whether or not drawer should be open.
@ -54,32 +57,32 @@ type Props = {
/**
* Callback for click on an item in the menu.
*/
onClick?: Function,
/**
* Keydown handler.
*/
onKeyDown?: Function,
onClick?: (e?: React.MouseEvent) => void,
/**
* Callback for drawer close.
*/
onDrawerClose?: Function,
onDrawerClose?: (e?: React.MouseEvent) => void,
/**
* Keydown handler.
*/
onKeyDown?: (e?: React.KeyboardEvent) => void,
/**
* Callback for the mouse entering the component.
*/
onMouseEnter?: Function,
onMouseEnter?: (e?: React.MouseEvent) => void,
/**
* Callback for the mouse leaving the component.
*/
onMouseLeave?: Function
onMouseLeave?: (e?: React.MouseEvent) => void
};
const MAX_HEIGHT = 400;
const useStyles = makeStyles(theme => {
const useStyles = makeStyles((theme: any) => {
return {
contextMenu: {
backgroundColor: theme.palette.ui02,

View File

@ -1,12 +1,11 @@
// @flow
import { makeStyles } from '@material-ui/styles';
import clsx from 'clsx';
import React from 'react';
import React, { ReactNode } from 'react';
import { useSelector } from 'react-redux';
// @ts-ignore
import { showOverflowDrawer } from '../../../toolbox/functions.web';
import { Icon } from '../../icons';
import Icon from '../../icons/components/Icon';
export type Props = {
@ -24,37 +23,37 @@ export type Props = {
* Custom icon. If used, the icon prop is ignored.
* Used to allow custom children instead of just the default icons.
*/
customIcon?: React$Node,
customIcon?: ReactNode,
/**
* Whether or not the action is disabled.
*/
disabled?: boolean,
/**
* Id of the action container.
*/
id?: string,
/**
* Default icon for action.
*/
icon?: Function,
/**
* Id of the action container.
*/
id?: string,
/**
* Click handler.
*/
onClick?: Function,
onClick?: (e?: React.MouseEvent) => void,
/**
* Keydown handler.
*/
onKeyDown?: Function,
onKeyDown?: (e?: React.KeyboardEvent) => void,
/**
* Keypress handler.
*/
onKeyPress?: Function,
onKeyPress?: (e?: React.KeyboardEvent) => void,
/**
* TestId of the element, if any.
@ -72,7 +71,7 @@ export type Props = {
textClassName?: string
}
const useStyles = makeStyles(theme => {
const useStyles = makeStyles((theme: any) => {
return {
contextMenuItem: {
alignItems: 'center',
@ -121,7 +120,7 @@ const ContextMenuItem = ({
text,
textClassName }: Props) => {
const styles = useStyles();
const _overflowDrawer = useSelector(showOverflowDrawer);
const _overflowDrawer: boolean = useSelector(showOverflowDrawer);
return (
<div

View File

@ -1,8 +1,7 @@
// @flow
import { makeStyles } from '@material-ui/core';
import React from 'react';
import React, { ReactNode } from 'react';
import ContextMenuItem from './ContextMenuItem';
import ContextMenuItem, { Props as ItemProps } from './ContextMenuItem';
type Props = {
@ -10,15 +9,15 @@ type Props = {
/**
* List of actions in this group.
*/
actions?: Array<Object>,
actions?: Array<ItemProps>,
/**
* The children of the component.
*/
children?: React$Node,
children?: ReactNode,
};
const useStyles = makeStyles(theme => {
const useStyles = makeStyles((theme: any) => {
return {
contextMenuItemGroup: {
'&:not(:empty)': {

View File

@ -1,9 +1,8 @@
// @flow
import { makeStyles } from '@material-ui/styles';
import clsx from 'clsx';
import React from 'react';
import React, { ReactNode } from 'react';
// @ts-ignore
import { ACTION_TRIGGER } from '../../../participants-pane/constants';
import { isMobileBrowser } from '../../environment/utils';
import participantsPaneTheme from '../themes/participantsPaneTheme.json';
@ -13,32 +12,32 @@ type Props = {
/**
* List item actions.
*/
actions: React$Node,
actions: ReactNode,
/**
* List item container class name.
*/
className: string,
/**
* Whether or not the actions should be hidden.
*/
hideActions?: boolean,
/**
* Icon to be displayed on the list item. (Avatar for participants).
*/
icon: React$Node,
icon: ReactNode,
/**
* Id of the container.
*/
id: string,
/**
* Whether or not the actions should be hidden.
*/
hideActions?: Boolean,
/**
* Indicators to be displayed on the list item.
*/
indicators?: React$Node,
indicators?: ReactNode,
/**
* Whether or not the item is highlighted.
@ -48,17 +47,17 @@ type Props = {
/**
* Click handler.
*/
onClick: Function,
onClick: (e?: React.MouseEvent) => void,
/**
* Long press handler.
*/
onLongPress: Function,
onLongPress: (e?: EventTarget) => void,
/**
* Mouse leave handler.
*/
onMouseLeave: Function,
onMouseLeave: (e?: React.MouseEvent) => void,
/**
* Data test id.
@ -68,7 +67,7 @@ type Props = {
/**
* Text children to be displayed on the list item.
*/
textChildren: React$Node | string,
textChildren: ReactNode | string,
/**
* The actions trigger. Can be Hover or Permanent.
@ -77,7 +76,7 @@ type Props = {
}
const useStyles = makeStyles(theme => {
const useStyles = makeStyles((theme: any) => {
return {
container: {
alignItems: 'center',
@ -194,7 +193,7 @@ const ListItem = ({
}: Props) => {
const styles = useStyles();
const _isMobile = isMobileBrowser();
let timeoutHandler;
let timeoutHandler: number;
/**
* Set calling long press handler after x milliseconds.
@ -202,10 +201,10 @@ const ListItem = ({
* @param {TouchEvent} e - Touch start event.
* @returns {void}
*/
function _onTouchStart(e) {
function _onTouchStart(e: React.TouchEvent) {
const target = e.touches[0].target;
timeoutHandler = setTimeout(() => onLongPress(target), 600);
timeoutHandler = window.setTimeout(() => onLongPress(target), 600);
}
/**

View File

@ -1,4 +1,4 @@
// @flow
/* eslint-disable lines-around-comment */
/* eslint-disable react/no-multi-comp */
import ErrorIcon from '@atlaskit/icon/glyph/error';
import WarningIcon from '@atlaskit/icon/glyph/warning';
@ -7,12 +7,15 @@ import {
Title,
titleIconWrapperStyles,
TitleText
// @ts-ignore
} from '@atlaskit/modal-dialog/dist/es2019/styled/Content';
import { withStyles } from '@material-ui/core/styles';
import React from 'react';
import { WithTranslation } from 'react-i18next';
import { translate } from '../../../i18n';
import { translate } from '../../../i18n/functions';
import { IconClose } from '../../../icons/svg/index';
// @ts-ignore
import { withPixelLineHeight } from '../../../styles/functions';
import Button from '../../../ui/components/web/Button';
import { BUTTON_TYPES } from '../../../ui/constants';
@ -31,17 +34,16 @@ const TitleIcon = ({ appearance }: { appearance?: 'danger' | 'warning' }) => {
);
};
type Props = {
id: string,
interface Props extends WithTranslation {
appearance?: 'danger' | 'warning',
classes: Object,
classes: any,
heading: string,
hideCloseIconButton: boolean,
onClose: Function,
showKeyline: boolean,
id?: string,
isHeadingMultiline: boolean,
testId: string,
t: Function
onClose: (e?: any) => void,
showKeyline: boolean,
testId?: string
}
/**
@ -51,7 +53,7 @@ type Props = {
*
* @returns {Object}
*/
const styles = theme => {
const styles = (theme: any) => {
return {
closeButton: {
borderRadius: theme.shape.borderRadius,
@ -95,15 +97,13 @@ class ModalHeader extends React.Component<Props> {
* @param {*} props - The read-only properties with which the new instance
* is to be initialized.
*/
constructor(props) {
constructor(props: Props) {
super(props);
// Bind event handler so it is only bound once for every instance.
this._onKeyPress = this._onKeyPress.bind(this);
}
_onKeyPress: (Object) => void;
/**
* KeyPress handler for accessibility.
*
@ -111,7 +111,7 @@ class ModalHeader extends React.Component<Props> {
*
* @returns {void}
*/
_onKeyPress(e) {
_onKeyPress(e: React.KeyboardEvent) {
if (this.props.onClose && (e.key === ' ' || e.key === 'Enter')) {
e.preventDefault();
this.props.onClose();

View File

@ -1,9 +1,8 @@
// @flow
/* eslint-disable lines-around-comment */
import Modal, { ModalFooter } from '@atlaskit/modal-dialog';
import { withStyles } from '@material-ui/core/styles';
import _ from 'lodash';
import React, { Component } from 'react';
import React, { Component, ReactElement } from 'react';
import { WithTranslation } from 'react-i18next';
import { translate } from '../../../i18n/functions';
import Button from '../../../ui/components/web/Button';
@ -31,17 +30,23 @@ const OK_BUTTON_ID = 'modal-dialog-ok-button';
*
* @static
*/
type Props = DialogProps & {
interface Props extends DialogProps, WithTranslation {
/**
* An object containing the CSS classes.
*/
classes: Object,
classes: any,
/**
* Custom dialog header that replaces the standard heading.
*/
customHeader?: React$Element<any> | Function,
customHeader?: ReactElement<any> | Function,
/**
* Disables dismissing the dialog when the blanket is clicked. Enabled
* by default.
*/
disableBlanketClickDismiss: boolean,
/*
* True if listening for the Enter key should be disabled.
@ -49,10 +54,9 @@ type Props = DialogProps & {
disableEnter: boolean,
/**
* Disables dismissing the dialog when the blanket is clicked. Enabled
* by default.
* If true, no footer will be displayed.
*/
disableBlanketClickDismiss: boolean,
disableFooter?: boolean,
/**
* If true, the cancel button will not display but cancel actions, like
@ -65,13 +69,6 @@ type Props = DialogProps & {
*/
hideCloseIconButton: boolean,
/**
* If true, no footer will be displayed.
*/
disableFooter?: boolean,
i18n: Object,
/**
* Whether the dialog is modal. This means clicking on the blanket will
* leave the dialog open. No cancel button.
@ -82,7 +79,7 @@ type Props = DialogProps & {
* The handler for the event when clicking the 'confirmNo' button.
* Defaults to onCancel if absent.
*/
onDecline?: Function,
onDecline?: () => void,
/**
* Callback invoked when setting the ref of the Dialog.
@ -94,11 +91,6 @@ type Props = DialogProps & {
*/
submitDisabled: boolean,
/**
* Function to be used to retrieve translated i18n labels.
*/
t: Function,
/**
* Width of the dialog, can be:
* - 'small' (400px), 'medium' (600px), 'large' (800px),
@ -107,7 +99,7 @@ type Props = DialogProps & {
* - string value for percentage.
*/
width: string
};
}
/**
* Creates the styles for the component.
@ -115,7 +107,7 @@ type Props = DialogProps & {
* @param {Object} theme - The theme.
* @returns {Object}
*/
const styles = theme => {
const styles = (theme: any) => {
return {
footer: {
boxShadow: 'none'
@ -139,20 +131,13 @@ class StatelessDialog extends Component<Props> {
hideCloseIconButton: false
};
/**
* The functional component to be used for rendering the modal footer.
*/
_Footer: ?Function;
_dialogElement: ?HTMLElement;
/**
* Initializes a new {@code StatelessDialog} instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
constructor(props: Props) {
super(props);
// Bind event handlers so they are only bound once for every instance.
@ -175,7 +160,7 @@ class StatelessDialog extends Component<Props> {
customHeader,
children,
hideCloseIconButton,
t /* The following fixes a flow error: */ = _.identity,
t,
titleString,
titleKey,
width
@ -185,10 +170,12 @@ class StatelessDialog extends Component<Props> {
<Modal
autoFocus = { true }
components = {{
// @ts-ignore
Header: customHeader ? customHeader : props => (
// @ts-ignore
<ModalHeader
{ ...props }
heading = { titleString || t(titleKey) }
heading = { titleString || t(titleKey ?? '') }
hideCloseIconButton = { hideCloseIconButton } />
)
}}
@ -212,8 +199,6 @@ class StatelessDialog extends Component<Props> {
);
}
_renderFooter: () => React$Node;
/**
* Returns a ReactElement to display buttons for closing the modal.
*
@ -222,7 +207,7 @@ class StatelessDialog extends Component<Props> {
* @private
* @returns {ReactElement}
*/
_renderFooter(propsFromModalFooter) {
_renderFooter(propsFromModalFooter: any) {
// Filter out falsy (null) values because {@code ButtonGroup} will error
// if passed in anything but buttons with valid type props.
const buttons = [
@ -252,8 +237,6 @@ class StatelessDialog extends Component<Props> {
);
}
_onCancel: () => void;
/**
* Dispatches action to hide the dialog.
*
@ -267,8 +250,6 @@ class StatelessDialog extends Component<Props> {
}
}
_onDialogDismissed: () => void;
/**
* Handles click on the blanket area.
*
@ -280,8 +261,6 @@ class StatelessDialog extends Component<Props> {
}
}
_onSubmit: (?string) => void;
/**
* Dispatches the action when submitting the dialog.
*
@ -289,7 +268,7 @@ class StatelessDialog extends Component<Props> {
* @param {string} value - The submitted value if any.
* @returns {void}
*/
_onSubmit(value) {
_onSubmit(value?: any) {
const { onSubmit } = this.props;
onSubmit && onSubmit(value);
@ -310,12 +289,13 @@ class StatelessDialog extends Component<Props> {
}
const {
t /* The following fixes a flow error: */ = _.identity,
t,
onDecline
} = this.props;
return (
<Button
accessibilityLabel = { t(this.props.cancelKey || 'dialog.Cancel') }
id = { CANCEL_BUTTON_ID }
key = { CANCEL_BUTTON_ID }
label = { t(this.props.cancelKey || 'dialog.Cancel') }
@ -332,16 +312,18 @@ class StatelessDialog extends Component<Props> {
* @returns {ReactElement|null} The OK button if enabled.
*/
_renderOKButton() {
if (this.props.submitDisabled) {
const {
submitDisabled,
t
} = this.props;
if (submitDisabled) {
return null;
}
const {
t /* The following fixes a flow error: */ = _.identity
} = this.props;
return (
<Button
accessibilityLabel = { t(this.props.okKey || 'dialog.Ok') }
disabled = { this.props.okDisabled }
id = { OK_BUTTON_ID }
key = { OK_BUTTON_ID }
@ -351,8 +333,6 @@ class StatelessDialog extends Component<Props> {
);
}
_onDialogRef: (?Element) => void;
/**
* Callback invoked when setting the ref of the dialog's child passing the Modal ref.
* It is done this way because we cannot directly access the ref of the Modal component.
@ -361,12 +341,10 @@ class StatelessDialog extends Component<Props> {
* @private
* @returns {void}
*/
_onDialogRef(element: ?Element) {
_onDialogRef(element?: any) {
this.props.onDialogRef && this.props.onDialogRef(element && element.parentNode);
}
_onKeyPress: (Object) => void;
/**
* Handles 'Enter' key in the dialog to submit/hide dialog depending on
* the available buttons and their disabled state.
@ -375,7 +353,7 @@ class StatelessDialog extends Component<Props> {
* @private
* @returns {void}
*/
_onKeyPress(event) {
_onKeyPress(event: React.KeyboardEvent) {
// If the event coming to the dialog has been subject to preventDefault
// we don't handle it here.
if (event.defaultPrevented) {

View File

@ -1,31 +1,31 @@
// @flow
import { ReactNode } from 'react';
export type DialogProps = {
/**
* Whether cancel button is disabled. Enabled by default.
*/
cancelDisabled: ?boolean,
cancelDisabled?: boolean,
/**
* Optional i18n key to change the cancel button title.
*/
cancelKey: ?string,
cancelKey?: string,
/**
* The React {@code Component} children which represents the dialog's body.
*/
children: ?React$Node,
children?: ReactNode,
/**
* Is ok button enabled/disabled. Enabled by default.
*/
okDisabled: ?boolean,
okDisabled?: boolean,
/**
* Optional i18n key to change the ok button title.
*/
okKey: ?string,
okKey?: string,
/**
* The handler for onCancel event.
@ -47,14 +47,14 @@ export type DialogProps = {
/**
* Key to use for showing a title.
*/
titleKey: ?string,
titleKey?: string,
/**
* The string to use as a title instead of {@code titleKey}. If a truthy
* value is specified, it takes precedence over {@code titleKey} i.e.
* The latter is unused.
*/
titleString: ?string
titleString?: string
};
/**

View File

@ -159,7 +159,7 @@ export function getFirstLoadableAvatarUrl(participant: Participant, store: IStor
* features/base/participants.
* @returns {(Participant|undefined)}
*/
export function getLocalParticipant(stateful: IStore | Function) {
export function getLocalParticipant(stateful: IStore | Function | IState) {
const state = toState(stateful)['features/base/participants'];
return state.local;
@ -342,7 +342,7 @@ export function getParticipantCountWithFake(stateful: IStore | Function) {
* @param {string} id - The ID of the participant's display name to retrieve.
* @returns {string}
*/
export function getParticipantDisplayName(stateful: IStore | Function, id: string): string {
export function getParticipantDisplayName(stateful: IStore | Function | IState, id: string): string {
const participant = getParticipantById(stateful, id);
const {
defaultLocalDisplayName,
@ -374,7 +374,7 @@ export function getParticipantDisplayName(stateful: IStore | Function, id: strin
* @param {string} id - The ID of the screenshare participant's display name to retrieve.
* @returns {string}
*/
export function getScreenshareParticipantDisplayName(stateful: IStore | Function, id: string) {
export function getScreenshareParticipantDisplayName(stateful: IStore | Function| IState, id: string) {
const ownerDisplayName = getParticipantDisplayName(stateful, getVirtualScreenshareParticipantOwnerId(id));
return i18next.t('screenshareDisplayName', { name: ownerDisplayName });
@ -648,6 +648,6 @@ export function getRaiseHandsQueue(stateful: IStore | Function): Array<Object> {
* @param {Object} participant - The participant.
* @returns {boolean} - Whether participant has raise hand or not.
*/
export function hasRaisedHand(participant: Participant): boolean {
return Boolean(participant && participant.raisedHandTimestamp);
export function hasRaisedHand(participant?: Participant): boolean {
return Boolean(participant?.raisedHandTimestamp);
}

View File

@ -1,29 +1,48 @@
// @flow
import { withStyles } from '@material-ui/styles';
import clsx from 'clsx';
import React, { useCallback } from 'react';
import React, { ReactNode, useCallback } from 'react';
import { Icon, IconArrowDown } from '../../../icons';
import Icon from '../../../icons/components/Icon';
import { IconArrowDown } from '../../../icons/svg/index';
import { withPixelLineHeight } from '../../../styles/functions.web';
type Props = {
/**
* Text of the button.
* Icon to display in the options section.
*/
children: React$Node,
OptionsIcon?: Function,
/**
* An object containing the CSS classes.
* The Label of the child element.
*/
classes: Object,
ariaDropDownLabel?: string,
/**
* The Label of the current element.
*/
ariaLabel?: string,
/**
* To give a aria-pressed to the icon.
*/
ariaPressed?: boolean,
/**
* Text of the button.
*/
children: ReactNode,
/**
* Text css class of the button.
*/
className?: string,
/**
* An object containing the CSS classes.
*/
classes: any,
/**
* If the button is disabled or not.
*/
@ -34,10 +53,26 @@ type Props = {
*/
hasOptions?: boolean,
/**
* Icon to display in the options section.
* OnClick button handler.
*/
OptionsIcon?: React$Node,
onClick?: (e?: React.MouseEvent) => void,
/**
* Click handler for options.
*/
onOptionsClick?: (e?: React.KeyboardEvent | React.MouseEvent) => void,
/**
* To give a role to the icon.
*/
role?: string,
/**
* To navigate with the keyboard.
*/
tabIndex?: number,
/**
* TestId of the button. Can be used to locate element when testing UI.
@ -47,43 +82,7 @@ type Props = {
/**
* The type of th button: primary, secondary, text.
*/
type: string,
/**
* OnClick button handler.
*/
onClick: Function,
/**
* Click handler for options.
*/
onOptionsClick?: Function,
/**
* To navigate with the keyboard.
*/
tabIndex?: number,
/**
* To give a role to the icon.
*/
role?: string,
/**
* To give a aria-pressed to the icon.
*/
ariaPressed?: boolean,
/**
* The Label of the current element.
*/
ariaLabel?: string,
/**
* The Label of the child element.
*/
ariaDropDownLabel?: string
type: string
};
/**
@ -93,7 +92,7 @@ type Props = {
*
* @returns {Object}
*/
const styles = theme => {
const styles = (theme: any) => {
return {
actionButton: {
...withPixelLineHeight(theme.typography.bodyLongBold),
@ -254,4 +253,5 @@ function ActionButton({
);
}
// @ts-ignore
export default withStyles(styles)(ActionButton);

View File

@ -1,16 +1,21 @@
// @flow
/* eslint-disable lines-around-comment */
import { makeStyles } from '@material-ui/styles';
import React, { useCallback, useState } from 'react';
import { WithTranslation } from 'react-i18next';
import { translate } from '../../../i18n';
import { Icon, IconArrowDownSmall, IconWifi1Bar, IconWifi2Bars, IconWifi3Bars } from '../../../icons';
import { connect } from '../../../redux';
import { IState } from '../../../../app/types';
import { translate } from '../../../i18n/functions';
import Icon from '../../../icons/components/Icon';
import { IconArrowDownSmall, IconWifi1Bar, IconWifi2Bars, IconWifi3Bars } from '../../../icons/svg/index';
import { connect } from '../../../redux/functions';
// @ts-ignore
import { PREJOIN_DEFAULT_CONTENT_WIDTH } from '../../../ui/components/variables';
// @ts-ignore
import { CONNECTION_TYPE } from '../../constants';
// @ts-ignore
import { getConnectionData } from '../../functions';
type Props = {
interface Props extends WithTranslation {
/**
* List of strings with details about the connection.
@ -20,15 +25,10 @@ type Props = {
/**
* The type of the connection. Can be: 'none', 'poor', 'nonOptimal' or 'good'.
*/
connectionType: string,
/**
* Used for translation.
*/
t: Function
connectionType: string
}
const useStyles = makeStyles(theme => {
const useStyles = makeStyles((theme: any) => {
return {
connectionStatus: {
borderRadius: '6px',
@ -121,7 +121,7 @@ const useStyles = makeStyles(theme => {
};
});
const CONNECTION_TYPE_MAP = {
const CONNECTION_TYPE_MAP: any = {
[CONNECTION_TYPE.POOR]: {
connectionClass: 'con-status--poor',
icon: IconWifi1Bar,
@ -152,7 +152,7 @@ function ConnectionStatus({ connectionDetails, t, connectionType }: Props) {
const arrowClassName = showDetails
? 'con-status-arrow con-status-arrow--up'
: 'con-status-arrow';
const detailsText = connectionDetails.map(t).join(' ');
const detailsText = connectionDetails.map(d => t(d)).join(' ');
const detailsClassName = showDetails
? 'con-status-details-visible'
: 'con-status-details-hidden';
@ -202,7 +202,7 @@ function ConnectionStatus({ connectionDetails, t, connectionType }: Props) {
tabIndex = { 0 } />
</div>
<div
aria-level = '2'
aria-level = { 2 }
className = { `con-status-details ${detailsClassName}` }
role = 'heading'>
{detailsText}</div>
@ -216,7 +216,7 @@ function ConnectionStatus({ connectionDetails, t, connectionType }: Props) {
* @param {Object} state - The redux state.
* @returns {Object}
*/
function mapStateToProps(state): Object {
function mapStateToProps(state: IState): Object {
const { connectionDetails, connectionType } = getConnectionData(state);
return {

View File

@ -1,36 +1,37 @@
/* @flow */
import { makeStyles } from '@material-ui/core';
import React from 'react';
import { WithTranslation } from 'react-i18next';
import { translate } from '../../../i18n';
import { Icon } from '../../../icons';
import { translate } from '../../../i18n/functions';
import Icon from '../../../icons/components/Icon';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { Tooltip } from '../../../tooltip';
/**
* The type of the React {@code Component} props of {@link BaseIndicator}.
*/
type Props = {
interface Props extends WithTranslation {
/**
* Additional CSS class name.
*/
className: string,
className?: string,
/**
* The icon component to use.
*/
icon: Object,
icon: Function,
/**
* The CSS classnames to set on the icon element of the component.
*/
iconClassName: string,
iconClassName?: string,
/**
* The color of the icon.
*/
iconColor: ?string,
iconColor?: string,
/**
* Id of the icon to be rendered.
@ -45,12 +46,7 @@ type Props = {
/**
* The ID attribute to set on the root element of the component.
*/
id: string,
/**
* Invoked to obtain translated strings.
*/
t: Function,
id?: string,
/**
* The translation key to use for displaying a tooltip when hovering over
@ -63,7 +59,7 @@ type Props = {
* defaulting to "top".
*/
tooltipPosition: string
};
}
const useStyles = makeStyles(() => {
return {
@ -95,7 +91,7 @@ const BaseIndicator = ({
tooltipPosition = 'top'
}: Props) => {
const styles = useStyles();
const style = {};
const style: any = {};
if (iconSize) {
style.fontSize = iconSize;

View File

@ -1,8 +1,8 @@
// @flow
import { createStyles, makeStyles } from '@material-ui/core';
import { commonStyles, getGlobalStyles } from '../constants';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { formatCommonClasses } from '../functions';
/**
@ -12,7 +12,7 @@ import { formatCommonClasses } from '../functions';
*
* @returns {Object}
*/
const useStyles = makeStyles(theme =>
const useStyles = makeStyles((theme: any) =>
createStyles({
'@global': {
...formatCommonClasses(commonStyles(theme)),

View File

@ -1,5 +1,3 @@
// @flow
import { makeStyles } from '@material-ui/styles';
import React from 'react';

View File

@ -1,8 +1,6 @@
// @flow
import { makeStyles } from '@material-ui/core/styles';
import clsx from 'clsx';
import React, { useEffect, useRef } from 'react';
import React, { ReactElement, useEffect, useRef } from 'react';
import { isMobileBrowser } from '../../../base/environment/utils';
@ -11,7 +9,7 @@ type Props = {
/**
* The component(s) that need to be scrollable on mobile.
*/
children: React$Node,
children: ReactElement,
/**
* Whether the component should be flex container or not.
@ -48,7 +46,7 @@ function TouchmoveHack({ children, isModal, flex }: Props) {
return children;
}
const touchMoveElementRef = useRef(null);
const touchMoveElementRef = useRef<HTMLDivElement>(null);
/**
* Atlaskit's {@code Modal} uses a third party library to disable touchmove events

View File

@ -1,15 +1,20 @@
/* eslint-disable lines-around-comment */
import { makeStyles } from '@material-ui/styles';
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import { IconRaisedHand } from '../../../base/icons';
import { IState } from '../../../app/types';
import { IconRaisedHand } from '../../../base/icons/svg/index';
// @ts-ignore
import { Label } from '../../../base/label';
// @ts-ignore
import { Tooltip } from '../../../base/tooltip';
import BaseTheme from '../../../base/ui/components/BaseTheme';
import BaseTheme from '../../../base/ui/components/BaseTheme.web';
// @ts-ignore
import { open as openParticipantsPane } from '../../../participants-pane/actions';
const useStyles = makeStyles(theme => {
const useStyles = makeStyles((theme: any) => {
return {
label: {
backgroundColor: theme.palette.warning02,
@ -22,7 +27,7 @@ const useStyles = makeStyles(theme => {
const RaisedHandsCountLabel = () => {
const styles = useStyles();
const dispatch = useDispatch();
const raisedHandsCount = useSelector(state =>
const raisedHandsCount = useSelector((state: IState) =>
(state['features/base/participants'].raisedHandsQueue || []).length);
const { t } = useTranslation();
const onClick = useCallback(() => {
@ -38,7 +43,7 @@ const RaisedHandsCountLabel = () => {
iconColor = { BaseTheme.palette.uiBackground }
id = 'raisedHandsCountLabel'
onClick = { onClick }
text = { raisedHandsCount } />
text = { `${raisedHandsCount}` } />
</Tooltip>);
};

View File

@ -1,33 +1,40 @@
// @flow
/* eslint-disable lines-around-comment */
import { withStyles } from '@material-ui/styles';
import clsx from 'clsx';
import React from 'react';
import { WithTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import type { Dispatch } from 'redux';
import { IState } from '../../../app/types';
// @ts-ignore
import { getSourceNameSignalingFeatureFlag } from '../../../base/config';
import { translate } from '../../../base/i18n';
import { MEDIA_TYPE } from '../../../base/media';
import { getLocalParticipant, getParticipantById } from '../../../base/participants';
import { translate } from '../../../base/i18n/functions';
import { MEDIA_TYPE } from '../../../base/media/constants';
import { getLocalParticipant, getParticipantById } from '../../../base/participants/functions';
// @ts-ignore
import { Popover } from '../../../base/popover';
import { connect } from '../../../base/redux';
import {
getVirtualScreenshareParticipantTrack,
getSourceNameByParticipantId,
getSourceNameByParticipantId, // @ts-ignore
getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
import {
isParticipantConnectionStatusInactive,
isParticipantConnectionStatusInterrupted,
isTrackStreamingStatusInactive,
isTrackStreamingStatusInterrupted
// @ts-ignore
} from '../../functions';
import AbstractConnectionIndicator, {
INDICATOR_DISPLAY_THRESHOLD,
type Props as AbstractProps,
type State as AbstractState
// @ts-ignore
} from '../AbstractConnectionIndicator';
// @ts-ignore
import ConnectionIndicatorContent from './ConnectionIndicatorContent';
// @ts-ignore
import { ConnectionIndicatorIcon } from './ConnectionIndicatorIcon';
/**
@ -37,7 +44,11 @@ import { ConnectionIndicatorIcon } from './ConnectionIndicatorIcon';
*
* @type {Object[]}
*/
const QUALITY_TO_WIDTH: Array<Object> = [
const QUALITY_TO_WIDTH: Array<{
colorClass: string;
percent: number;
tip: string;
}> = [
// Full (3 bars)
{
@ -66,7 +77,12 @@ const QUALITY_TO_WIDTH: Array<Object> = [
/**
* The type of the React {@code Component} props of {@link ConnectionIndicator}.
*/
type Props = AbstractProps & {
type Props = AbstractProps & WithTranslation & {
/**
* Disable/enable inactive indicator.
*/
_connectionIndicatorInactiveDisabled: boolean,
/**
* The current condition of the user's connection, matching one of the
@ -74,16 +90,21 @@ type Props = AbstractProps & {
*/
_connectionStatus: string,
/**
* Disable/enable inactive indicator.
*/
_connectionIndicatorInactiveDisabled: boolean,
/**
* Whether the indicator popover is disabled.
*/
_popoverDisabled: boolean,
/**
* The source name of the track.
*/
_sourceName: string,
/**
* Whether source name signaling is enabled.
*/
_sourceNameSignalingEnabled: boolean,
/**
* Whether or not the component should ignore setting a visibility class for
* hiding the component when the connection quality is not strong.
@ -95,6 +116,7 @@ type Props = AbstractProps & {
*/
audioSsrc: number,
/**
* An object containing the CSS classes.
*/
@ -105,7 +127,6 @@ type Props = AbstractProps & {
*/
dispatch: Dispatch<any>,
/**
* Whether or not clicking the indicator should display a popover for more
* details.
@ -121,22 +142,7 @@ type Props = AbstractProps & {
* Relative to the icon from where the popover for more connection details
* should display.
*/
statsPopoverPosition: string,
/**
* Invoked to obtain translated strings.
*/
t: Function,
/**
* The source name of the track.
*/
_sourceName: string,
/**
* Whether source name signaling is enabled.
*/
_sourceNameSignalingEnabled: boolean
statsPopoverPosition: string
};
type State = AbstractState & {
@ -147,7 +153,7 @@ type State = AbstractState & {
popoverVisible: boolean
}
const styles = theme => {
const styles = (theme: any) => {
return {
container: {
display: 'inline-block'
@ -209,6 +215,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
constructor(props: Props) {
super(props);
// @ts-ignore
this.state = {
showIndicator: false,
stats: {},
@ -225,9 +232,11 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
* @returns {ReactElement}
*/
render() {
// @ts-ignore
const { enableStatsDisplay, participantId, statsPopoverPosition, classes } = this.props;
const visibilityClass = this._getVisibilityClass();
// @ts-ignore
if (this.props._popoverDisabled) {
return this._renderIndicator();
}
@ -236,6 +245,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
<Popover
className = { clsx(classes.container, visibilityClass) }
content = { <ConnectionIndicatorContent
// @ts-ignore
inheritedStats = { this.state.stats }
participantId = { participantId } /> }
disablePopover = { !enableStatsDisplay }
@ -244,6 +254,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
onPopoverClose = { this._onHidePopover }
onPopoverOpen = { this._onShowPopover }
position = { statsPopoverPosition }
// @ts-ignore
visible = { this.state.popoverVisible }>
{ this._renderIndicator() }
</Popover>
@ -259,12 +270,14 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
*/
_getConnectionColorClass() {
// TODO We currently do not have logic to emit and handle stats changes for tracks.
// @ts-ignore
const { percent } = this.state.stats;
const {
_isConnectionStatusInactive,
_isConnectionStatusInterrupted,
_connectionIndicatorInactiveDisabled
// @ts-ignore
} = this.props;
if (_isConnectionStatusInactive) {
@ -293,7 +306,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
* @private
* @returns {Object}
*/
_getDisplayConfiguration(percent: number): Object {
_getDisplayConfiguration(percent: number): any {
return QUALITY_TO_WIDTH.find(x => percent >= x.percent) || {};
}
@ -305,17 +318,18 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
* @returns {string}
*/
_getVisibilityClass() {
// @ts-ignore
const { _isConnectionStatusInactive, _isConnectionStatusInterrupted, classes } = this.props;
// @ts-ignore
return this.state.showIndicator
// @ts-ignore
|| this.props.alwaysVisible
|| _isConnectionStatusInterrupted
|| _isConnectionStatusInactive
? '' : classes.hidden;
}
_onHidePopover: () => void;
/**
* Hides popover.
*
@ -323,12 +337,10 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
* @returns {void}
*/
_onHidePopover() {
// @ts-ignore
this.setState({ popoverVisible: false });
}
_onShowPopover: () => void;
/**
* Shows popover.
*
@ -336,6 +348,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
* @returns {void}
*/
_onShowPopover() {
// @ts-ignore
this.setState({ popoverVisible: true });
}
@ -353,6 +366,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
_videoTrack,
classes,
iconSize
// @ts-ignore
} = this.props;
return (
@ -377,7 +391,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
* @param {Props} ownProps - The own props of the component.
* @returns {Props}
*/
export function _mapStateToProps(state: Object, ownProps: Props) {
export function _mapStateToProps(state: IState, ownProps: Props) {
const { participantId } = ownProps;
const tracks = state['features/base/tracks'];
const sourceNameSignalingEnabled = getSourceNameSignalingFeatureFlag(state);
@ -411,4 +425,5 @@ export function _mapStateToProps(state: Object, ownProps: Props) {
};
}
export default translate(connect(_mapStateToProps)(
// @ts-ignore
withStyles(styles)(ConnectionIndicator)));

View File

@ -1,18 +1,22 @@
/* @flow */
import { withStyles } from '@material-ui/styles';
import clsx from 'clsx';
import React, { Component } from 'react';
import { WithTranslation } from 'react-i18next';
import { isMobileBrowser } from '../../../features/base/environment/utils';
import ContextMenu from '../../base/components/context-menu/ContextMenu';
import { translate } from '../../base/i18n';
import { isMobileBrowser } from '../../base/environment/utils';
import { translate } from '../../base/i18n/functions';
type DownloadUpload = {
download: number;
upload: number;
}
/**
* The type of the React {@code Component} props of
* {@link ConnectionStatsTable}.
*/
type Props = {
interface Props extends WithTranslation {
/**
* The audio SSRC of this client.
@ -26,7 +30,7 @@ type Props = {
* upload: Number
* }}.
*/
bandwidth: Object,
bandwidth: DownloadUpload,
/**
* Statistics related to bitrate.
@ -35,7 +39,7 @@ type Props = {
* upload: Number
* }}.
*/
bitrate: Object,
bitrate: DownloadUpload,
/**
* The number of bridges (aka media servers) currently used in the
@ -46,18 +50,28 @@ type Props = {
/**
* An object containing the CSS classes.
*/
classes: Object,
classes: any,
/**
* Audio/video codecs in use for the connection.
*/
codec: Object,
codec: {
[key: string]: {
audio: string;
video: string;
}
},
/**
* A message describing the connection quality.
*/
connectionSummary: string,
/**
* Whether or not should display the "Show More" link.
*/
disableShowMoreStats: boolean,
/**
* The end-to-end round-trip-time.
*/
@ -68,16 +82,6 @@ type Props = {
*/
enableSaveLogs: boolean,
/**
* Whether or not should display the "Show More" link.
*/
disableShowMoreStats: boolean,
/**
* The endpoint id of this client.
*/
participantId: string,
/**
* Statistics related to frame rates for each ssrc.
* {{
@ -105,12 +109,12 @@ type Props = {
/**
* Callback to invoke when the user clicks on the download logs link.
*/
onSaveLogs: Function,
onSaveLogs: () => void,
/**
* Callback to invoke when the show additional stats link is clicked.
*/
onShowMore: Function,
onShowMore: (e?: React.MouseEvent) => void,
/**
* Statistics related to packet loss.
@ -119,7 +123,12 @@ type Props = {
* upload: Number
* }}.
*/
packetLoss: Object,
packetLoss: DownloadUpload,
/**
* The endpoint id of this client.
*/
participantId: string,
/**
* The region that we think the client is in.
@ -135,7 +144,12 @@ type Props = {
* }
* }}.
*/
resolution: Object,
resolution: {
[ssrc: string]: {
height: number;
width: number;
}
},
/**
* The region of the media server that we are connected to.
@ -149,25 +163,28 @@ type Props = {
shouldShowMore: boolean,
/**
* Invoked to obtain translated strings.
* Whether source name signaling is enabled.
*/
t: Function,
/**
* The video SSRC of this client.
*/
videoSsrc: number,
sourceNameSignalingEnabled: boolean,
/**
* Statistics related to transports.
*/
transport: Array<Object>,
transport: Array<{
ip: string;
localCandidateType: string;
localip: string;
p2p: boolean;
remoteCandidateType: string;
transportType: string;
type: string;
}>,
/**
* Whether source name signaling is enabled.
* The video SSRC of this client.
*/
sourceNameSignalingEnabled: boolean
};
videoSsrc: number
}
/**
* Click handler.
@ -175,13 +192,13 @@ type Props = {
* @param {SyntheticEvent} event - The click event.
* @returns {void}
*/
function onClick(event) {
function onClick(event: React.MouseEvent) {
// If the event is propagated to the thumbnail container the participant will be pinned. That's why the propagation
// needs to be stopped.
event.stopPropagation();
}
const styles = theme => {
const styles = (theme: any) => {
return {
actions: {
margin: '10px auto',
@ -599,7 +616,7 @@ class ConnectionStatsTable extends Component<Props> {
frameRateString = framerate || 'N/A';
} else {
frameRateString = Object.keys(framerate || {})
.map(ssrc => framerate[ssrc])
.map(ssrc => framerate[ssrc as keyof typeof framerate])
.join(', ') || 'N/A';
}
@ -791,7 +808,13 @@ class ConnectionStatsTable extends Component<Props> {
return [ NA ];
}
const data = {
const data: {
localIP: string[],
localPort: string[],
remoteIP: string[],
remotePort: string[],
transportType: string[]
} = {
localIP: [],
localPort: [],
remoteIP: [],
@ -897,7 +920,7 @@ class ConnectionStatsTable extends Component<Props> {
* @private
* @returns {ReactElement}
*/
_renderTransportTableRow(config: Object) {
_renderTransportTableRow(config: any) {
const { additionalData, data, key, label } = config;
return (
@ -924,7 +947,7 @@ class ConnectionStatsTable extends Component<Props> {
* @private
* @returns {string}
*/
function getIP(value) {
function getIP(value: string) {
if (!value) {
return '';
}
@ -940,7 +963,7 @@ function getIP(value) {
* @private
* @returns {string}
*/
function getPort(value) {
function getPort(value: string) {
if (!value) {
return '';
}
@ -955,7 +978,7 @@ function getPort(value) {
* @private
* @returns {string}
*/
function getStringFromArray(array) {
function getStringFromArray(array: string[]) {
let res = '';
for (let i = 0; i < array.length; i++) {
@ -965,4 +988,5 @@ function getStringFromArray(array) {
return res;
}
// @ts-ignore
export default translate(withStyles(styles)(ConnectionStatsTable));

View File

@ -1,24 +1,28 @@
/* @flow */
/* eslint-disable lines-around-comment */
import { withStyles } from '@material-ui/styles';
import React, { Component } from 'react';
import { WithTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import type { Dispatch } from 'redux';
import { translate } from '../../../base/i18n';
import { IState } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import {
getParticipantDisplayName,
getParticipantById
} from '../../../base/participants';
import { connect } from '../../../base/redux';
} from '../../../base/participants/functions';
// @ts-ignore
import { updateSettings } from '../../../base/settings';
// @ts-ignore
import { Tooltip } from '../../../base/tooltip';
// @ts-ignore
import { getIndicatorsTooltipPosition } from '../../../filmstrip/functions.web';
import { appendSuffix } from '../../functions';
/**
* The type of the React {@code Component} props of {@link DisplayName}.
*/
type Props = {
interface Props extends WithTranslation {
/**
* The participant's current display name which should be shown when in
@ -36,6 +40,11 @@ type Props = {
*/
allowEditing: boolean,
/**
* An object containing the CSS classes.
*/
classes: any,
/**
* Invoked to update the participant's display name.
*/
@ -46,11 +55,6 @@ type Props = {
*/
displayNameSuffix: string,
/**
* An object containing the CSS classes.
*/
classes: Object,
/**
* The ID attribute to add to the component. Useful for global querying for
* the component by legacy components and torture tests.
@ -62,16 +66,11 @@ type Props = {
*/
participantID: string,
/**
* Invoked to obtain translated strings.
*/
t: Function,
/**
* The type of thumbnail.
*/
thumbnailType: string
};
}
/**
* The type of the React {@code Component} state of {@link DisplayName}.
@ -89,7 +88,7 @@ type State = {
isEditing: boolean
};
const styles = theme => {
const styles = (theme: any) => {
return {
displayName: {
...theme.typography.labelBold,
@ -119,7 +118,7 @@ const styles = theme => {
* @augments Component
*/
class DisplayName extends Component<Props, State> {
_nameInput: ?HTMLInputElement;
_nameInput?: HTMLInputElement;
static defaultProps = {
_configuredDisplayName: ''
@ -148,7 +147,7 @@ class DisplayName extends Component<Props, State> {
* @private
* @type {HTMLInputElement}
*/
this._nameInput = null;
this._nameInput = undefined;
// Bind event handlers so they are only bound once for every instance.
this._onChange = this._onChange.bind(this);
@ -165,7 +164,7 @@ class DisplayName extends Component<Props, State> {
* @inheritdoc
* @returns {void}
*/
componentDidUpdate(previousProps, previousState) {
componentDidUpdate(previousProps: Props, previousState: State) {
if (!previousState.isEditing
&& this.state.isEditing
&& this._nameInput) {
@ -229,12 +228,10 @@ class DisplayName extends Component<Props, State> {
* @private
* @returns {void}
*/
_onClick(e) {
_onClick(e: React.MouseEvent) {
e.stopPropagation();
}
_onChange: () => void;
/**
* Updates the internal state of the display name entered into the edit
* field.
@ -243,14 +240,12 @@ class DisplayName extends Component<Props, State> {
* @private
* @returns {void}
*/
_onChange(event) {
_onChange(event: React.ChangeEvent<HTMLInputElement>) {
this.setState({
editDisplayNameValue: event.target.value
});
}
_onKeyDown: () => void;
/**
* Submits the edited display name update if the enter key is pressed.
*
@ -258,14 +253,12 @@ class DisplayName extends Component<Props, State> {
* @private
* @returns {void}
*/
_onKeyDown(event) {
_onKeyDown(event: React.KeyboardEvent) {
if (event.key === 'Enter') {
this._onSubmit();
}
}
_onStartEditing: () => void;
/**
* Updates the component to display an editable input field and sets the
* initial value to the current display name.
@ -274,7 +267,7 @@ class DisplayName extends Component<Props, State> {
* @private
* @returns {void}
*/
_onStartEditing(e) {
_onStartEditing(e: React.MouseEvent) {
if (this.props.allowEditing) {
e.stopPropagation();
this.setState({
@ -284,8 +277,6 @@ class DisplayName extends Component<Props, State> {
}
}
_onSubmit: () => void;
/**
* Dispatches an action to update the display name if any change has
* occurred after editing. Clears any temporary state used to keep track
@ -309,11 +300,9 @@ class DisplayName extends Component<Props, State> {
editDisplayNameValue: ''
});
this._nameInput = null;
this._nameInput = undefined;
}
_setNameInputRef: (HTMLInputElement | null) => void;
/**
* Sets the internal reference to the HTML element backing the React
* {@code Component} input with id {@code editDisplayName}.
@ -323,7 +312,7 @@ class DisplayName extends Component<Props, State> {
* @private
* @returns {void}
*/
_setNameInputRef(element) {
_setNameInputRef(element: HTMLInputElement) {
this._nameInput = element;
}
}
@ -339,13 +328,13 @@ class DisplayName extends Component<Props, State> {
* _nameToDisplay: string
* }}
*/
function _mapStateToProps(state, ownProps) {
function _mapStateToProps(state: IState, ownProps: Partial<Props>) {
const { participantID } = ownProps;
const participant = getParticipantById(state, participantID);
const participant = getParticipantById(state, participantID ?? '');
return {
_configuredDisplayName: participant && participant.name,
_nameToDisplay: getParticipantDisplayName(state, participantID)
_nameToDisplay: getParticipantDisplayName(state, participantID ?? '')
};
}

View File

@ -1,20 +1,25 @@
// @flow
/* eslint-disable lines-around-comment */
import { makeStyles } from '@material-ui/core/styles';
import clsx from 'clsx';
import React from 'react';
import { useSelector } from 'react-redux';
import { IState } from '../../../app/types';
// @ts-ignore
import { isDisplayNameVisible } from '../../../base/config/functions.any';
import { getLocalParticipant, getParticipantDisplayName } from '../../../base/participants';
import { getLocalParticipant, getParticipantDisplayName } from '../../../base/participants/functions';
import { Participant } from '../../../base/participants/reducer';
import { withPixelLineHeight } from '../../../base/styles/functions.web';
// @ts-ignore
import { getLargeVideoParticipant } from '../../../large-video/functions';
// @ts-ignore
import { isToolboxVisible } from '../../../toolbox/functions.web';
// @ts-ignore
import { isLayoutTileView } from '../../../video-layout';
import DisplayNameBadge from './DisplayNameBadge';
const useStyles = makeStyles(theme => {
const useStyles = makeStyles((theme: any) => {
return {
badgeContainer: {
...withPixelLineHeight(theme.typography.bodyShortRegularLarge),
@ -43,15 +48,15 @@ const useStyles = makeStyles(theme => {
*/
const StageParticipantNameLabel = () => {
const classes = useStyles();
const largeVideoParticipant = useSelector(getLargeVideoParticipant);
const largeVideoParticipant: Participant = useSelector(getLargeVideoParticipant);
const selectedId = largeVideoParticipant?.id;
const nameToDisplay = useSelector(state => getParticipantDisplayName(state, selectedId));
const nameToDisplay = useSelector((state: IState) => getParticipantDisplayName(state, selectedId));
const localParticipant = useSelector(getLocalParticipant);
const localId = localParticipant?.id;
const isTileView = useSelector(isLayoutTileView);
const toolboxVisible = useSelector(isToolboxVisible);
const toolboxVisible: boolean = useSelector(isToolboxVisible);
const showDisplayName = useSelector(isDisplayNameVisible);
if (showDisplayName && nameToDisplay && selectedId !== localId && !isTileView) {

View File

@ -1,5 +1,3 @@
// @flow
import { createMuiTheme } from '@material-ui/core/styles';
import { font, colors, colorMap, spacing, shape, typography, breakpoints } from '../base/ui/Tokens';
@ -11,7 +9,7 @@ import { createColorTokens } from '../base/ui/utils';
* @param {Object} customTheme - The branded custom theme.
* @returns {Object} - The MUI theme.
*/
export function createMuiBrandingTheme(customTheme: Object) {
export function createMuiBrandingTheme(customTheme: any) {
const {
palette: customPalette,
shape: customShape,
@ -82,9 +80,10 @@ export function createMuiBrandingTheme(customTheme: Object) {
function overwriteRecurrsive(obj1: Object, obj2: Object) {
Object.keys(obj2).forEach(key => {
if (obj1.hasOwnProperty(key)) {
if (typeof obj1[key] === 'object') {
overwriteRecurrsive(obj1[key], obj2[key]);
if (typeof obj1[key as keyof typeof obj1] === 'object') {
overwriteRecurrsive(obj1[key as keyof typeof obj1], obj2[key as keyof typeof obj2]);
} else {
// @ts-ignore
obj1[key] = obj2[key];
}
}

View File

@ -1,9 +1,9 @@
/* @flow */
/* eslint-disable lines-around-comment */
import { withStyles } from '@material-ui/styles';
import clsx from 'clsx';
import _ from 'lodash';
import React, { PureComponent } from 'react';
import { WithTranslation } from 'react-i18next';
import { FixedSizeList, FixedSizeGrid } from 'react-window';
import type { Dispatch } from 'redux';
@ -11,15 +11,23 @@ import {
createShortcutEvent,
createToolbarEvent,
sendAnalytics
// @ts-ignore
} from '../../../analytics';
// @ts-ignore
import { getSourceNameSignalingFeatureFlag, getToolbarButtons } from '../../../base/config';
import { isMobileBrowser } from '../../../base/environment/utils';
import { translate } from '../../../base/i18n';
import { Icon, IconMenuDown, IconMenuUp } from '../../../base/icons';
import { connect } from '../../../base/redux';
import { translate } from '../../../base/i18n/functions';
import Icon from '../../../base/icons/components/Icon';
import { IconMenuDown, IconMenuUp } from '../../../base/icons/svg/index';
import { Participant } from '../../../base/participants/reducer';
import { connect } from '../../../base/redux/functions';
// @ts-ignore
import { shouldHideSelfView } from '../../../base/settings/functions.any';
// @ts-ignore
import { showToolbox } from '../../../toolbox/actions.web';
// @ts-ignore
import { isButtonEnabled, isToolboxVisible } from '../../../toolbox/functions.web';
// @ts-ignore
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
import {
setFilmstripVisible,
@ -28,6 +36,7 @@ import {
setUserIsResizing,
setTopPanelVisible,
setVisibleRemoteParticipants
// @ts-ignore
} from '../../actions';
import {
ASPECT_RATIO_BREAKPOINT,
@ -43,51 +52,55 @@ import {
getVerticalViewMaxWidth,
shouldRemoteVideosBeVisible,
isStageFilmstripTopPanel
// @ts-ignore
} from '../../functions';
// @ts-ignore
import AudioTracksContainer from './AudioTracksContainer';
// @ts-ignore
import Thumbnail from './Thumbnail';
// @ts-ignore
import ThumbnailWrapper from './ThumbnailWrapper';
// @ts-ignore
import { styles } from './styles';
declare var APP: Object;
declare var interfaceConfig: Object;
declare let APP: any;
/**
* The type of the React {@code Component} props of {@link Filmstrip}.
*/
type Props = {
interface Props extends WithTranslation {
/**
* Additional CSS class names top add to the root.
*/
_className: string,
/**
* The current layout of the filmstrip.
*/
_currentLayout: string,
/**
* The number of columns in tile view.
*/
_columns: number,
/**
* The current layout of the filmstrip.
*/
_currentLayout: string,
/**
* Whether or not to hide the self view.
*/
_disableSelfView: boolean,
/**
* The width of the filmstrip.
*/
_filmstripWidth: number,
/**
* The height of the filmstrip.
*/
_filmstripHeight: number,
/**
* The width of the filmstrip.
*/
_filmstripWidth: number,
/**
* Whether or not we have scroll on the filmstrip.
*/
@ -116,7 +129,7 @@ type Props = {
/**
* The local screen share participant. This prop is behind the sourceNameSignaling feature flag.
*/
_localScreenShare: Object,
_localScreenShare: Participant,
/**
* Whether or not the filmstrip videos should currently be displayed.
@ -173,16 +186,16 @@ type Props = {
*/
_topPanelFilmstrip: boolean,
/**
* The height of the top panel (user resized).
*/
_topPanelHeight?: number,
/**
* The max height of the top panel.
*/
_topPanelMaxHeight: number,
/**
* The height of the top panel (user resized).
*/
_topPanelHeight: ?number,
/**
* Whether or not the top panel is visible.
*/
@ -191,7 +204,7 @@ type Props = {
/**
* The width of the vertical filmstrip (user resized).
*/
_verticalFilmstripWidth: ?number,
_verticalFilmstripWidth?: number,
/**
* Whether or not the vertical filmstrip should have a background color.
@ -216,7 +229,7 @@ type Props = {
/**
* An object containing the CSS classes.
*/
classes: Object,
classes: any,
/**
* The redux {@code dispatch} function.
@ -226,16 +239,21 @@ type Props = {
/**
* The type of filmstrip to be displayed.
*/
filmstripType: string,
/**
* Invoked to obtain translated strings.
*/
t: Function
};
filmstripType: string
}
type State = {
/**
* Initial top panel height on drag handle mouse down.
*/
dragFilmstripHeight?: number,
/**
* Initial filmstrip width on drag handle mouse down.
*/
dragFilmstripWidth?: number|null,
/**
* Whether or not the mouse is pressed.
*/
@ -244,17 +262,7 @@ type State = {
/**
* Initial mouse position on drag handle mouse down.
*/
mousePosition: ?number,
/**
* Initial filmstrip width on drag handle mouse down.
*/
dragFilmstripWidth: ?number,
/**
* Initial top panel height on drag handle mouse down.
*/
dragFilmstripHeight: ?number
mousePosition?: number|null
}
/**
@ -317,6 +325,7 @@ class Filmstrip extends PureComponent <Props, State> {
'keyboardShortcuts.toggleFilmstrip'
);
document.addEventListener('mouseup', this._onDragMouseUp);
// @ts-ignore
document.addEventListener('mousemove', this._throttledResize);
}
@ -328,6 +337,7 @@ class Filmstrip extends PureComponent <Props, State> {
componentWillUnmount() {
APP.keyboardshortcut.unregisterShortcut('F');
document.removeEventListener('mouseup', this._onDragMouseUp);
// @ts-ignore
document.removeEventListener('mousemove', this._throttledResize);
}
@ -338,7 +348,7 @@ class Filmstrip extends PureComponent <Props, State> {
* @returns {ReactElement}
*/
render() {
const filmstripStyle = { };
const filmstripStyle: any = { };
const {
_currentLayout,
_disableSelfView,
@ -466,15 +476,13 @@ class Filmstrip extends PureComponent <Props, State> {
);
}
_onDragHandleMouseDown: (MouseEvent) => void;
/**
* Handles mouse down on the drag handle.
*
* @param {MouseEvent} e - The mouse down event.
* @returns {void}
*/
_onDragHandleMouseDown(e) {
_onDragHandleMouseDown(e: React.MouseEvent) {
const { _topPanelFilmstrip, _topPanelHeight, _verticalFilmstripWidth } = this.props;
this.setState({
@ -486,8 +494,6 @@ class Filmstrip extends PureComponent <Props, State> {
this.props.dispatch(setUserIsResizing(true));
}
_onDragMouseUp: () => void;
/**
* Drag handle mouse up handler.
*
@ -502,15 +508,13 @@ class Filmstrip extends PureComponent <Props, State> {
}
}
_onFilmstripResize: (MouseEvent) => void;
/**
* Handles drag handle mouse move.
*
* @param {MouseEvent} e - The mousemove event.
* @returns {void}
*/
_onFilmstripResize(e) {
_onFilmstripResize(e: React.MouseEvent) {
if (this.state.isMouseDown) {
const {
dispatch,
@ -523,9 +527,9 @@ class Filmstrip extends PureComponent <Props, State> {
const { dragFilmstripWidth, dragFilmstripHeight, mousePosition } = this.state;
if (_topPanelFilmstrip) {
const diff = e.clientY - mousePosition;
const diff = e.clientY - (mousePosition ?? 0);
const height = Math.max(
Math.min(dragFilmstripHeight + diff, _maxTopPanelHeight),
Math.min((dragFilmstripHeight ?? 0) + diff, _maxTopPanelHeight),
TOP_FILMSTRIP_HEIGHT
);
@ -533,9 +537,9 @@ class Filmstrip extends PureComponent <Props, State> {
dispatch(setUserFilmstripHeight(height));
}
} else {
const diff = mousePosition - e.clientX;
const diff = (mousePosition ?? 0) - e.clientX;
const width = Math.max(
Math.min(dragFilmstripWidth + diff, _maxFilmstripWidth),
Math.min((dragFilmstripWidth ?? 0) + diff, _maxFilmstripWidth),
DEFAULT_FILMSTRIP_WIDTH
);
@ -553,7 +557,7 @@ class Filmstrip extends PureComponent <Props, State> {
* @param {number} stopIndex - The stop index.
* @returns {Object}
*/
_calculateIndices(startIndex, stopIndex) {
_calculateIndices(startIndex: number, stopIndex: number) {
const { _currentLayout, _iAmRecorder, _thumbnailsReordered, _disableSelfView } = this.props;
let start = startIndex;
let stop = stopIndex;
@ -573,8 +577,6 @@ class Filmstrip extends PureComponent <Props, State> {
};
}
_onTabIn: () => void;
/**
* Toggle the toolbar visibility when tabbing into it.
*
@ -586,15 +588,13 @@ class Filmstrip extends PureComponent <Props, State> {
}
}
_listItemKey: number => string;
/**
* The key to be used for every ThumbnailWrapper element in stage view.
*
* @param {number} index - The index of the ThumbnailWrapper instance.
* @returns {string} - The key.
*/
_listItemKey(index) {
_listItemKey(index: number) {
const { _remoteParticipants, _remoteParticipantsLength } = this.props;
if (typeof index !== 'number' || _remoteParticipantsLength <= index) {
@ -604,15 +604,13 @@ class Filmstrip extends PureComponent <Props, State> {
return _remoteParticipants[index];
}
_gridItemKey: Object => string;
/**
* The key to be used for every ThumbnailWrapper element in tile views.
*
* @param {Object} data - An object with the indexes identifying the ThumbnailWrapper instance.
* @returns {string} - The key.
*/
_gridItemKey({ columnIndex, rowIndex }) {
_gridItemKey({ columnIndex, rowIndex }: {columnIndex: number, rowIndex: number}) {
const {
_disableSelfView,
_columns,
@ -638,23 +636,20 @@ class Filmstrip extends PureComponent <Props, State> {
return _remoteParticipants[remoteIndex];
}
_onListItemsRendered: Object => void;
/**
* Handles items rendered changes in stage view.
*
* @param {Object} data - Information about the rendered items.
* @returns {void}
*/
_onListItemsRendered({ visibleStartIndex, visibleStopIndex }) {
_onListItemsRendered({ visibleStartIndex, visibleStopIndex }
: { visibleStartIndex: number, visibleStopIndex: number }) {
const { dispatch } = this.props;
const { startIndex, stopIndex } = this._calculateIndices(visibleStartIndex, visibleStopIndex);
dispatch(setVisibleRemoteParticipants(startIndex, stopIndex));
}
_onGridItemsRendered: Object => void;
/**
* Handles items rendered changes in tile view.
*
@ -666,6 +661,11 @@ class Filmstrip extends PureComponent <Props, State> {
visibleColumnStopIndex,
visibleRowStartIndex,
visibleRowStopIndex
}: {
visibleColumnStartIndex: number,
visibleColumnStopIndex: number,
visibleRowStartIndex: number,
visibleRowStopIndex: number
}) {
const { _columns, dispatch } = this.props;
const start = (visibleRowStartIndex * _columns) + visibleColumnStartIndex;
@ -713,6 +713,7 @@ class Filmstrip extends PureComponent <Props, State> {
initialScrollLeft = { 0 }
initialScrollTop = { 0 }
itemData = {{ filmstripType }}
// @ts-ignore
itemKey = { this._gridItemKey }
onItemsRendered = { this._onGridItemsRendered }
overscanRowCount = { 1 }
@ -727,7 +728,7 @@ class Filmstrip extends PureComponent <Props, State> {
}
const props = {
const props: any = {
itemCount: _remoteParticipantsLength,
className: `filmstrip__videos remote-videos ${_resizableFilmstrip ? '' : 'height-transition'}`,
height: _filmstripHeight,
@ -746,8 +747,6 @@ class Filmstrip extends PureComponent <Props, State> {
const isNotOverflowing = !_hasScroll;
props.itemSize = itemSize;
// $FlowFixMe
props.layout = 'horizontal';
if (isNotOverflowing) {
props.className += ' is-not-overflowing';
@ -787,8 +786,6 @@ class Filmstrip extends PureComponent <Props, State> {
: dispatch(setFilmstripVisible(!_mainFilmstripVisible));
}
_onShortcutToggleFilmstrip: () => void;
/**
* Creates an analytics keyboard shortcut event and dispatches an action for
* toggling filmstrip visibility.
@ -806,8 +803,6 @@ class Filmstrip extends PureComponent <Props, State> {
this._doToggleFilmstrip();
}
_onToolbarToggleFilmstrip: () => void;
/**
* Creates an analytics toolbar event and dispatches an action for opening
* the speaker stats modal.
@ -825,8 +820,6 @@ class Filmstrip extends PureComponent <Props, State> {
this._doToggleFilmstrip();
}
_onToggleButtonTouch: (SyntheticEvent<HTMLButtonElement>) => void;
/**
* Handler for touch start event of the 'toggle button'.
*
@ -834,7 +827,7 @@ class Filmstrip extends PureComponent <Props, State> {
* @param {Object} e - The synthetic event.
* @returns {void}
*/
_onToggleButtonTouch(e: SyntheticEvent<HTMLButtonElement>) {
_onToggleButtonTouch(e: React.TouchEvent) {
// Don't propagate the touchStart event so the toolbar doesn't get toggled.
e.stopPropagation();
this._onToolbarToggleFilmstrip();
@ -893,7 +886,7 @@ class Filmstrip extends PureComponent <Props, State> {
* @private
* @returns {Props}
*/
function _mapStateToProps(state, ownProps) {
function _mapStateToProps(state: any, ownProps: any) {
const { _hasScroll = false, filmstripType, _topPanelFilmstrip, _remoteParticipants } = ownProps;
const toolbarButtons = getToolbarButtons(state);
const { testing = {}, iAmRecorder } = state['features/base/config'];

View File

@ -1,12 +1,13 @@
/* @flow */
import { makeStyles } from '@material-ui/styles';
import React from 'react';
import { useSelector } from 'react-redux';
import { IconPinParticipant } from '../../../base/icons';
import { getParticipantById } from '../../../base/participants';
import { BaseIndicator } from '../../../base/react';
import { IState } from '../../../app/types';
import { IconPinParticipant } from '../../../base/icons/svg/index';
import { getParticipantById } from '../../../base/participants/functions';
import BaseIndicator from '../../../base/react/components/web/BaseIndicator';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { getPinnedActiveParticipants, isStageFilmstripAvailable } from '../../functions.web';
/**
@ -55,8 +56,10 @@ const PinnedIndicator = ({
tooltipPosition
}: Props) => {
const stageFilmstrip = useSelector(isStageFilmstripAvailable);
const pinned = useSelector(state => getParticipantById(state, participantId))?.pinned;
const isPinned = useSelector(getPinnedActiveParticipants).find(p => p.participantId === participantId);
const pinned = useSelector((state: IState) => getParticipantById(state, participantId))?.pinned;
const activePinnedParticipants: Array<{participantId: string; pinned: boolean}>
= useSelector(getPinnedActiveParticipants);
const isPinned = activePinnedParticipants.find(p => p.participantId === participantId);
const styles = useStyles();
if ((stageFilmstrip && !isPinned) || (!stageFilmstrip && !pinned)) {

View File

@ -1,13 +1,13 @@
/* @flow */
import { makeStyles } from '@material-ui/styles';
import React from 'react';
import { useSelector } from 'react-redux';
import { IconRaisedHand } from '../../../base/icons';
import { getParticipantById, hasRaisedHand } from '../../../base/participants';
import { BaseIndicator } from '../../../base/react';
import BaseTheme from '../../../base/ui/components/BaseTheme';
import { IState } from '../../../app/types';
import { IconRaisedHand } from '../../../base/icons/svg/index';
import { getParticipantById, hasRaisedHand } from '../../../base/participants/functions';
import { Participant } from '../../../base/participants/reducer';
import BaseIndicator from '../../../base/react/components/web/BaseIndicator';
import BaseTheme from '../../../base/ui/components/BaseTheme.web';
/**
* The type of the React {@code Component} props of {@link RaisedHandIndicator}.
@ -31,7 +31,7 @@ type Props = {
tooltipPosition: string
};
const useStyles = makeStyles(theme => {
const useStyles = makeStyles((theme: any) => {
return {
raisedHandIndicator: {
backgroundColor: theme.palette.warning02,
@ -54,8 +54,9 @@ const RaisedHandIndicator = ({
participantId,
tooltipPosition
}: Props) => {
const _raisedHand = hasRaisedHand(useSelector(state =>
getParticipantById(state, participantId)));
const participant: Participant|undefined = useSelector((state: IState) =>
getParticipantById(state, participantId));
const _raisedHand = hasRaisedHand(participant);
const styles = useStyles();
if (!_raisedHand) {

View File

@ -67,7 +67,7 @@ type Props = {
/**
* Closes a drawer if open.
*/
closeDrawer?: Function,
closeDrawer?: () => void,
/**
* The participant for which the drawer is open.
@ -91,17 +91,17 @@ type Props = {
/**
* 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: (value?: boolean | React.MouseEvent) => void,
/**
* Participant reference.
@ -157,7 +157,7 @@ const ParticipantContextMenu = ({
const _isVideoForceMuted = useSelector(state =>
isForceMuted(participant, MEDIA_TYPE.VIDEO, state));
const _isAudioMuted = useSelector(state => isParticipantAudioMuted(participant, state));
const _overflowDrawer = useSelector(showOverflowDrawer);
const _overflowDrawer: boolean = useSelector(showOverflowDrawer);
const { remoteVideoMenu = {}, disableRemoteMute, startSilent }
= useSelector((state: IState) => state['features/base/config']);
const { disableKick, disableGrantModerator, disablePrivateChat } = remoteVideoMenu;
@ -315,7 +315,7 @@ const ParticipantContextMenu = ({
entity = { participant }
hidden = { thumbnailMenu ? false : undefined }
inDrawer = { thumbnailMenu && _overflowDrawer }
isDrawerOpen = { drawerParticipant }
isDrawerOpen = { Boolean(drawerParticipant) }
offsetTarget = { offsetTarget }
onClick = { onSelect }
onDrawerClose = { thumbnailMenu ? onSelect : closeDrawer }