ref: Convert files to TS (#12007)
Convert files that use material-ui to TS (needed for material-ui upgrade)
This commit is contained in:
parent
fc60ab8383
commit
3bd3be4df0
|
@ -143,6 +143,7 @@
|
||||||
"@types/react": "17.0.14",
|
"@types/react": "17.0.14",
|
||||||
"@types/react-native": "0.68.1",
|
"@types/react-native": "0.68.1",
|
||||||
"@types/react-redux": "7.1.24",
|
"@types/react-redux": "7.1.24",
|
||||||
|
"@types/react-window": "1.8.5",
|
||||||
"@types/unorm": "1.3.28",
|
"@types/unorm": "1.3.28",
|
||||||
"@types/uuid": "8.3.4",
|
"@types/uuid": "8.3.4",
|
||||||
"@types/zxcvbn": "4.4.1",
|
"@types/zxcvbn": "4.4.1",
|
||||||
|
@ -5534,6 +5535,15 @@
|
||||||
"@types/react": "*"
|
"@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": {
|
"node_modules/@types/retry": {
|
||||||
"version": "0.12.1",
|
"version": "0.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz",
|
||||||
|
@ -23993,6 +24003,15 @@
|
||||||
"@types/react": "*"
|
"@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": {
|
"@types/retry": {
|
||||||
"version": "0.12.1",
|
"version": "0.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz",
|
||||||
|
|
|
@ -148,6 +148,7 @@
|
||||||
"@types/react": "17.0.14",
|
"@types/react": "17.0.14",
|
||||||
"@types/react-native": "0.68.1",
|
"@types/react-native": "0.68.1",
|
||||||
"@types/react-redux": "7.1.24",
|
"@types/react-redux": "7.1.24",
|
||||||
|
"@types/react-window": "1.8.5",
|
||||||
"@types/unorm": "1.3.28",
|
"@types/unorm": "1.3.28",
|
||||||
"@types/uuid": "8.3.4",
|
"@types/uuid": "8.3.4",
|
||||||
"@types/zxcvbn": "4.4.1",
|
"@types/zxcvbn": "4.4.1",
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { PureComponent } from 'react';
|
import { PureComponent } from 'react';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
|
@ -32,21 +30,21 @@ export type Props = {
|
||||||
/**
|
/**
|
||||||
* The URL of the avatar to render.
|
* 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
|
* Implements an abstract stateless avatar component that renders an avatar purely from what gets passed through
|
||||||
* props.
|
* 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.
|
* Checks if the passed prop is a loaded icon or not.
|
||||||
*
|
*
|
||||||
* @param {string? | Object?} iconProp - The prop to check.
|
* @param {string? | Object?} iconProp - The prop to check.
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
_isIcon(iconProp: ?string | ?Object): boolean {
|
_isIcon(iconProp?: string | Function): iconProp is Function {
|
||||||
return Boolean(iconProp) && (typeof iconProp === 'object' || typeof iconProp === 'function');
|
return Boolean(iconProp) && (typeof iconProp === 'object' || typeof iconProp === 'function');
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,25 +1,23 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { withStyles } from '@material-ui/core/styles';
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Icon } from '../../../icons';
|
import Icon from '../../../icons/components/Icon';
|
||||||
import AbstractStatelessAvatar, { type Props as AbstractProps } from '../AbstractStatelessAvatar';
|
import AbstractStatelessAvatar, { type Props as AbstractProps } from '../AbstractStatelessAvatar';
|
||||||
import { PRESENCE_AVAILABLE_COLOR, PRESENCE_AWAY_COLOR, PRESENCE_BUSY_COLOR, PRESENCE_IDLE_COLOR } from '../styles';
|
import { PRESENCE_AVAILABLE_COLOR, PRESENCE_AWAY_COLOR, PRESENCE_BUSY_COLOR, PRESENCE_IDLE_COLOR } from '../styles';
|
||||||
|
|
||||||
type Props = AbstractProps & {
|
type Props = AbstractProps & {
|
||||||
|
|
||||||
/**
|
|
||||||
* An object containing the CSS classes.
|
|
||||||
*/
|
|
||||||
classes: Object,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* External class name passed through props.
|
* External class name passed through props.
|
||||||
*/
|
*/
|
||||||
className?: string,
|
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).
|
* 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.
|
* 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.
|
* TestId of the element, if any.
|
||||||
|
@ -43,7 +41,7 @@ type Props = AbstractProps & {
|
||||||
/**
|
/**
|
||||||
* Indicates whether to load the avatar using CORS or not.
|
* 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.
|
* 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}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
_getAvatarStyle(color) {
|
_getAvatarStyle(color?: string) {
|
||||||
const { size } = this.props;
|
const { size } = this.props;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -231,7 +229,7 @@ class StatelessAvatar extends AbstractStatelessAvatar<Props> {
|
||||||
* @param {string} additional - Any additional class to add.
|
* @param {string} additional - Any additional class to add.
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
_getAvatarClassName(additional) {
|
_getAvatarClassName(additional?: string) {
|
||||||
return clsx('avatar', additional, this.props.className, this.props.classes.avatar);
|
return clsx('avatar', additional, this.props.className, this.props.classes.avatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,10 +248,6 @@ class StatelessAvatar extends AbstractStatelessAvatar<Props> {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
_isIcon: (?string | ?Object) => boolean;
|
|
||||||
|
|
||||||
_onAvatarLoadError: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles avatar load errors.
|
* Handles avatar load errors.
|
||||||
*
|
*
|
||||||
|
@ -268,4 +262,5 @@ class StatelessAvatar extends AbstractStatelessAvatar<Props> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
export default withStyles(styles)(StatelessAvatar);
|
export default withStyles(styles)(StatelessAvatar);
|
|
@ -1,17 +1,15 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
/* eslint-disable react/jsx-no-bind */
|
/* eslint-disable react/jsx-no-bind */
|
||||||
|
|
||||||
import { withStyles } from '@material-ui/styles';
|
import { withStyles } from '@material-ui/styles';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React, { useEffect, useState } from 'react';
|
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 { withPixelLineHeight } from '../styles/functions.web';
|
||||||
import { copyText } from '../util';
|
import { Theme } from '../ui/types';
|
||||||
|
import { copyText } from '../util/helpers';
|
||||||
|
|
||||||
|
const styles = (theme: Theme) => {
|
||||||
const styles = theme => {
|
|
||||||
return {
|
return {
|
||||||
copyButton: {
|
copyButton: {
|
||||||
...withPixelLineHeight(theme.typography.bodyLongRegular),
|
...withPixelLineHeight(theme.typography.bodyLongRegular),
|
||||||
|
@ -54,34 +52,29 @@ const styles = theme => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
let mounted;
|
let mounted: boolean;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
||||||
/**
|
|
||||||
* An object containing the CSS classes.
|
|
||||||
*/
|
|
||||||
classes: Object,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Css class to apply on container.
|
* Css class to apply on container.
|
||||||
*/
|
*/
|
||||||
className: string,
|
className: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object containing the CSS classes.
|
||||||
|
*/
|
||||||
|
classes: any,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The displayed text.
|
* The displayed text.
|
||||||
*/
|
*/
|
||||||
displayedText: string,
|
displayedText: string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The text that needs to be copied (might differ from the displayedText).
|
* The id of the button.
|
||||||
*/
|
*/
|
||||||
textToCopy: string,
|
id?: string,
|
||||||
|
|
||||||
/**
|
|
||||||
* The text displayed on mouse hover.
|
|
||||||
*/
|
|
||||||
textOnHover: string,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The text displayed on copy success.
|
* The text displayed on copy success.
|
||||||
|
@ -89,9 +82,14 @@ type Props = {
|
||||||
textOnCopySuccess: string,
|
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}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function onKeyPress(e) {
|
function onKeyPress(e: React.KeyboardEvent) {
|
||||||
if (onClick && (e.key === ' ' || e.key === 'Enter')) {
|
if (onClick && (e.key === ' ' || e.key === 'Enter')) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onClick();
|
onClick();
|
||||||
|
@ -216,4 +214,5 @@ CopyButton.defaultProps = {
|
||||||
className: ''
|
className: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
export default withStyles(styles)(CopyButton);
|
export default withStyles(styles)(CopyButton);
|
|
@ -1,11 +1,14 @@
|
||||||
// @flow
|
/* eslint-disable lines-around-comment */
|
||||||
import { makeStyles } from '@material-ui/core';
|
import { makeStyles } from '@material-ui/core';
|
||||||
import clsx from 'clsx';
|
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';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
import { getComputedOuterHeight } from '../../../participants-pane/functions';
|
import { getComputedOuterHeight } from '../../../participants-pane/functions';
|
||||||
|
// @ts-ignore
|
||||||
import { Drawer, JitsiPortal } from '../../../toolbox/components/web';
|
import { Drawer, JitsiPortal } from '../../../toolbox/components/web';
|
||||||
|
// @ts-ignore
|
||||||
import { showOverflowDrawer } from '../../../toolbox/functions.web';
|
import { showOverflowDrawer } from '../../../toolbox/functions.web';
|
||||||
import participantsPaneTheme from '../themes/participantsPaneTheme.json';
|
import participantsPaneTheme from '../themes/participantsPaneTheme.json';
|
||||||
|
|
||||||
|
@ -19,12 +22,12 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* Children of the context menu.
|
* Children of the context menu.
|
||||||
*/
|
*/
|
||||||
children: React$Node,
|
children: ReactNode,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class name for context menu. Used to overwrite default styles.
|
* Class name for context menu. Used to overwrite default styles.
|
||||||
*/
|
*/
|
||||||
className?: ?string,
|
className?: string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entity for which the context menu is displayed.
|
* 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.
|
* Whether or not the menu is already in a drawer.
|
||||||
*/
|
*/
|
||||||
inDrawer?: ?boolean,
|
inDrawer?: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not drawer should be open.
|
* Whether or not drawer should be open.
|
||||||
|
@ -54,32 +57,32 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* Callback for click on an item in the menu.
|
* Callback for click on an item in the menu.
|
||||||
*/
|
*/
|
||||||
onClick?: Function,
|
onClick?: (e?: React.MouseEvent) => void,
|
||||||
|
|
||||||
/**
|
|
||||||
* Keydown handler.
|
|
||||||
*/
|
|
||||||
onKeyDown?: Function,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for drawer close.
|
* 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.
|
* Callback for the mouse entering the component.
|
||||||
*/
|
*/
|
||||||
onMouseEnter?: Function,
|
onMouseEnter?: (e?: React.MouseEvent) => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for the mouse leaving the component.
|
* Callback for the mouse leaving the component.
|
||||||
*/
|
*/
|
||||||
onMouseLeave?: Function
|
onMouseLeave?: (e?: React.MouseEvent) => void
|
||||||
};
|
};
|
||||||
|
|
||||||
const MAX_HEIGHT = 400;
|
const MAX_HEIGHT = 400;
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => {
|
const useStyles = makeStyles((theme: any) => {
|
||||||
return {
|
return {
|
||||||
contextMenu: {
|
contextMenu: {
|
||||||
backgroundColor: theme.palette.ui02,
|
backgroundColor: theme.palette.ui02,
|
|
@ -1,12 +1,11 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/styles';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
import { showOverflowDrawer } from '../../../toolbox/functions.web';
|
import { showOverflowDrawer } from '../../../toolbox/functions.web';
|
||||||
import { Icon } from '../../icons';
|
import Icon from '../../icons/components/Icon';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
|
|
||||||
|
@ -24,37 +23,37 @@ export type Props = {
|
||||||
* Custom icon. If used, the icon prop is ignored.
|
* Custom icon. If used, the icon prop is ignored.
|
||||||
* Used to allow custom children instead of just the default icons.
|
* Used to allow custom children instead of just the default icons.
|
||||||
*/
|
*/
|
||||||
customIcon?: React$Node,
|
customIcon?: ReactNode,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the action is disabled.
|
* Whether or not the action is disabled.
|
||||||
*/
|
*/
|
||||||
disabled?: boolean,
|
disabled?: boolean,
|
||||||
|
|
||||||
/**
|
|
||||||
* Id of the action container.
|
|
||||||
*/
|
|
||||||
id?: string,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default icon for action.
|
* Default icon for action.
|
||||||
*/
|
*/
|
||||||
icon?: Function,
|
icon?: Function,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id of the action container.
|
||||||
|
*/
|
||||||
|
id?: string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Click handler.
|
* Click handler.
|
||||||
*/
|
*/
|
||||||
onClick?: Function,
|
onClick?: (e?: React.MouseEvent) => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keydown handler.
|
* Keydown handler.
|
||||||
*/
|
*/
|
||||||
onKeyDown?: Function,
|
onKeyDown?: (e?: React.KeyboardEvent) => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keypress handler.
|
* Keypress handler.
|
||||||
*/
|
*/
|
||||||
onKeyPress?: Function,
|
onKeyPress?: (e?: React.KeyboardEvent) => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TestId of the element, if any.
|
* TestId of the element, if any.
|
||||||
|
@ -72,7 +71,7 @@ export type Props = {
|
||||||
textClassName?: string
|
textClassName?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => {
|
const useStyles = makeStyles((theme: any) => {
|
||||||
return {
|
return {
|
||||||
contextMenuItem: {
|
contextMenuItem: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
@ -121,7 +120,7 @@ const ContextMenuItem = ({
|
||||||
text,
|
text,
|
||||||
textClassName }: Props) => {
|
textClassName }: Props) => {
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
const _overflowDrawer = useSelector(showOverflowDrawer);
|
const _overflowDrawer: boolean = useSelector(showOverflowDrawer);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
|
@ -1,8 +1,7 @@
|
||||||
// @flow
|
|
||||||
import { makeStyles } from '@material-ui/core';
|
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 = {
|
type Props = {
|
||||||
|
@ -10,15 +9,15 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* List of actions in this group.
|
* List of actions in this group.
|
||||||
*/
|
*/
|
||||||
actions?: Array<Object>,
|
actions?: Array<ItemProps>,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The children of the component.
|
* The children of the component.
|
||||||
*/
|
*/
|
||||||
children?: React$Node,
|
children?: ReactNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => {
|
const useStyles = makeStyles((theme: any) => {
|
||||||
return {
|
return {
|
||||||
contextMenuItemGroup: {
|
contextMenuItemGroup: {
|
||||||
'&:not(:empty)': {
|
'&:not(:empty)': {
|
|
@ -1,9 +1,8 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/styles';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
import { ACTION_TRIGGER } from '../../../participants-pane/constants';
|
import { ACTION_TRIGGER } from '../../../participants-pane/constants';
|
||||||
import { isMobileBrowser } from '../../environment/utils';
|
import { isMobileBrowser } from '../../environment/utils';
|
||||||
import participantsPaneTheme from '../themes/participantsPaneTheme.json';
|
import participantsPaneTheme from '../themes/participantsPaneTheme.json';
|
||||||
|
@ -13,32 +12,32 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* List item actions.
|
* List item actions.
|
||||||
*/
|
*/
|
||||||
actions: React$Node,
|
actions: ReactNode,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List item container class name.
|
* List item container class name.
|
||||||
*/
|
*/
|
||||||
className: string,
|
className: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the actions should be hidden.
|
||||||
|
*/
|
||||||
|
hideActions?: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon to be displayed on the list item. (Avatar for participants).
|
* Icon to be displayed on the list item. (Avatar for participants).
|
||||||
*/
|
*/
|
||||||
icon: React$Node,
|
icon: ReactNode,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Id of the container.
|
* Id of the container.
|
||||||
*/
|
*/
|
||||||
id: string,
|
id: string,
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the actions should be hidden.
|
|
||||||
*/
|
|
||||||
hideActions?: Boolean,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicators to be displayed on the list item.
|
* Indicators to be displayed on the list item.
|
||||||
*/
|
*/
|
||||||
indicators?: React$Node,
|
indicators?: ReactNode,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the item is highlighted.
|
* Whether or not the item is highlighted.
|
||||||
|
@ -48,17 +47,17 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* Click handler.
|
* Click handler.
|
||||||
*/
|
*/
|
||||||
onClick: Function,
|
onClick: (e?: React.MouseEvent) => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Long press handler.
|
* Long press handler.
|
||||||
*/
|
*/
|
||||||
onLongPress: Function,
|
onLongPress: (e?: EventTarget) => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mouse leave handler.
|
* Mouse leave handler.
|
||||||
*/
|
*/
|
||||||
onMouseLeave: Function,
|
onMouseLeave: (e?: React.MouseEvent) => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data test id.
|
* Data test id.
|
||||||
|
@ -68,7 +67,7 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* Text children to be displayed on the list item.
|
* Text children to be displayed on the list item.
|
||||||
*/
|
*/
|
||||||
textChildren: React$Node | string,
|
textChildren: ReactNode | string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The actions trigger. Can be Hover or Permanent.
|
* The actions trigger. Can be Hover or Permanent.
|
||||||
|
@ -77,7 +76,7 @@ type Props = {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => {
|
const useStyles = makeStyles((theme: any) => {
|
||||||
return {
|
return {
|
||||||
container: {
|
container: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
@ -194,7 +193,7 @@ const ListItem = ({
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
const _isMobile = isMobileBrowser();
|
const _isMobile = isMobileBrowser();
|
||||||
let timeoutHandler;
|
let timeoutHandler: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set calling long press handler after x milliseconds.
|
* Set calling long press handler after x milliseconds.
|
||||||
|
@ -202,10 +201,10 @@ const ListItem = ({
|
||||||
* @param {TouchEvent} e - Touch start event.
|
* @param {TouchEvent} e - Touch start event.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function _onTouchStart(e) {
|
function _onTouchStart(e: React.TouchEvent) {
|
||||||
const target = e.touches[0].target;
|
const target = e.touches[0].target;
|
||||||
|
|
||||||
timeoutHandler = setTimeout(() => onLongPress(target), 600);
|
timeoutHandler = window.setTimeout(() => onLongPress(target), 600);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -1,4 +1,4 @@
|
||||||
// @flow
|
/* eslint-disable lines-around-comment */
|
||||||
/* eslint-disable react/no-multi-comp */
|
/* eslint-disable react/no-multi-comp */
|
||||||
import ErrorIcon from '@atlaskit/icon/glyph/error';
|
import ErrorIcon from '@atlaskit/icon/glyph/error';
|
||||||
import WarningIcon from '@atlaskit/icon/glyph/warning';
|
import WarningIcon from '@atlaskit/icon/glyph/warning';
|
||||||
|
@ -7,12 +7,15 @@ import {
|
||||||
Title,
|
Title,
|
||||||
titleIconWrapperStyles,
|
titleIconWrapperStyles,
|
||||||
TitleText
|
TitleText
|
||||||
|
// @ts-ignore
|
||||||
} from '@atlaskit/modal-dialog/dist/es2019/styled/Content';
|
} from '@atlaskit/modal-dialog/dist/es2019/styled/Content';
|
||||||
import { withStyles } from '@material-ui/core/styles';
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { WithTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { translate } from '../../../i18n';
|
import { translate } from '../../../i18n/functions';
|
||||||
import { IconClose } from '../../../icons/svg/index';
|
import { IconClose } from '../../../icons/svg/index';
|
||||||
|
// @ts-ignore
|
||||||
import { withPixelLineHeight } from '../../../styles/functions';
|
import { withPixelLineHeight } from '../../../styles/functions';
|
||||||
import Button from '../../../ui/components/web/Button';
|
import Button from '../../../ui/components/web/Button';
|
||||||
import { BUTTON_TYPES } from '../../../ui/constants';
|
import { BUTTON_TYPES } from '../../../ui/constants';
|
||||||
|
@ -31,17 +34,16 @@ const TitleIcon = ({ appearance }: { appearance?: 'danger' | 'warning' }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
interface Props extends WithTranslation {
|
||||||
id: string,
|
|
||||||
appearance?: 'danger' | 'warning',
|
appearance?: 'danger' | 'warning',
|
||||||
classes: Object,
|
classes: any,
|
||||||
heading: string,
|
heading: string,
|
||||||
hideCloseIconButton: boolean,
|
hideCloseIconButton: boolean,
|
||||||
onClose: Function,
|
id?: string,
|
||||||
showKeyline: boolean,
|
|
||||||
isHeadingMultiline: boolean,
|
isHeadingMultiline: boolean,
|
||||||
testId: string,
|
onClose: (e?: any) => void,
|
||||||
t: Function
|
showKeyline: boolean,
|
||||||
|
testId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,7 +53,7 @@ type Props = {
|
||||||
*
|
*
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
const styles = theme => {
|
const styles = (theme: any) => {
|
||||||
return {
|
return {
|
||||||
closeButton: {
|
closeButton: {
|
||||||
borderRadius: theme.shape.borderRadius,
|
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
|
* @param {*} props - The read-only properties with which the new instance
|
||||||
* is to be initialized.
|
* is to be initialized.
|
||||||
*/
|
*/
|
||||||
constructor(props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
// Bind event handler so it is only bound once for every instance.
|
// Bind event handler so it is only bound once for every instance.
|
||||||
this._onKeyPress = this._onKeyPress.bind(this);
|
this._onKeyPress = this._onKeyPress.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onKeyPress: (Object) => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* KeyPress handler for accessibility.
|
* KeyPress handler for accessibility.
|
||||||
*
|
*
|
||||||
|
@ -111,7 +111,7 @@ class ModalHeader extends React.Component<Props> {
|
||||||
*
|
*
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onKeyPress(e) {
|
_onKeyPress(e: React.KeyboardEvent) {
|
||||||
if (this.props.onClose && (e.key === ' ' || e.key === 'Enter')) {
|
if (this.props.onClose && (e.key === ' ' || e.key === 'Enter')) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.onClose();
|
this.props.onClose();
|
|
@ -1,9 +1,8 @@
|
||||||
// @flow
|
/* eslint-disable lines-around-comment */
|
||||||
|
|
||||||
import Modal, { ModalFooter } from '@atlaskit/modal-dialog';
|
import Modal, { ModalFooter } from '@atlaskit/modal-dialog';
|
||||||
import { withStyles } from '@material-ui/core/styles';
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
import _ from 'lodash';
|
import React, { Component, ReactElement } from 'react';
|
||||||
import React, { Component } from 'react';
|
import { WithTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { translate } from '../../../i18n/functions';
|
import { translate } from '../../../i18n/functions';
|
||||||
import Button from '../../../ui/components/web/Button';
|
import Button from '../../../ui/components/web/Button';
|
||||||
|
@ -31,17 +30,23 @@ const OK_BUTTON_ID = 'modal-dialog-ok-button';
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
type Props = DialogProps & {
|
interface Props extends DialogProps, WithTranslation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object containing the CSS classes.
|
* An object containing the CSS classes.
|
||||||
*/
|
*/
|
||||||
classes: Object,
|
classes: any,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom dialog header that replaces the standard heading.
|
* 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.
|
* True if listening for the Enter key should be disabled.
|
||||||
|
@ -49,10 +54,9 @@ type Props = DialogProps & {
|
||||||
disableEnter: boolean,
|
disableEnter: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables dismissing the dialog when the blanket is clicked. Enabled
|
* If true, no footer will be displayed.
|
||||||
* by default.
|
|
||||||
*/
|
*/
|
||||||
disableBlanketClickDismiss: boolean,
|
disableFooter?: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, the cancel button will not display but cancel actions, like
|
* If true, the cancel button will not display but cancel actions, like
|
||||||
|
@ -65,13 +69,6 @@ type Props = DialogProps & {
|
||||||
*/
|
*/
|
||||||
hideCloseIconButton: boolean,
|
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
|
* Whether the dialog is modal. This means clicking on the blanket will
|
||||||
* leave the dialog open. No cancel button.
|
* leave the dialog open. No cancel button.
|
||||||
|
@ -82,7 +79,7 @@ type Props = DialogProps & {
|
||||||
* The handler for the event when clicking the 'confirmNo' button.
|
* The handler for the event when clicking the 'confirmNo' button.
|
||||||
* Defaults to onCancel if absent.
|
* Defaults to onCancel if absent.
|
||||||
*/
|
*/
|
||||||
onDecline?: Function,
|
onDecline?: () => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback invoked when setting the ref of the Dialog.
|
* Callback invoked when setting the ref of the Dialog.
|
||||||
|
@ -94,11 +91,6 @@ type Props = DialogProps & {
|
||||||
*/
|
*/
|
||||||
submitDisabled: boolean,
|
submitDisabled: boolean,
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to be used to retrieve translated i18n labels.
|
|
||||||
*/
|
|
||||||
t: Function,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Width of the dialog, can be:
|
* Width of the dialog, can be:
|
||||||
* - 'small' (400px), 'medium' (600px), 'large' (800px),
|
* - 'small' (400px), 'medium' (600px), 'large' (800px),
|
||||||
|
@ -107,7 +99,7 @@ type Props = DialogProps & {
|
||||||
* - string value for percentage.
|
* - string value for percentage.
|
||||||
*/
|
*/
|
||||||
width: string
|
width: string
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the styles for the component.
|
* Creates the styles for the component.
|
||||||
|
@ -115,7 +107,7 @@ type Props = DialogProps & {
|
||||||
* @param {Object} theme - The theme.
|
* @param {Object} theme - The theme.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
const styles = theme => {
|
const styles = (theme: any) => {
|
||||||
return {
|
return {
|
||||||
footer: {
|
footer: {
|
||||||
boxShadow: 'none'
|
boxShadow: 'none'
|
||||||
|
@ -139,20 +131,13 @@ class StatelessDialog extends Component<Props> {
|
||||||
hideCloseIconButton: false
|
hideCloseIconButton: false
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* The functional component to be used for rendering the modal footer.
|
|
||||||
*/
|
|
||||||
_Footer: ?Function;
|
|
||||||
|
|
||||||
_dialogElement: ?HTMLElement;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new {@code StatelessDialog} instance.
|
* Initializes a new {@code StatelessDialog} instance.
|
||||||
*
|
*
|
||||||
* @param {Object} props - The read-only properties with which the new
|
* @param {Object} props - The read-only properties with which the new
|
||||||
* instance is to be initialized.
|
* instance is to be initialized.
|
||||||
*/
|
*/
|
||||||
constructor(props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
// Bind event handlers so they are only bound once for every instance.
|
// Bind event handlers so they are only bound once for every instance.
|
||||||
|
@ -175,7 +160,7 @@ class StatelessDialog extends Component<Props> {
|
||||||
customHeader,
|
customHeader,
|
||||||
children,
|
children,
|
||||||
hideCloseIconButton,
|
hideCloseIconButton,
|
||||||
t /* The following fixes a flow error: */ = _.identity,
|
t,
|
||||||
titleString,
|
titleString,
|
||||||
titleKey,
|
titleKey,
|
||||||
width
|
width
|
||||||
|
@ -185,10 +170,12 @@ class StatelessDialog extends Component<Props> {
|
||||||
<Modal
|
<Modal
|
||||||
autoFocus = { true }
|
autoFocus = { true }
|
||||||
components = {{
|
components = {{
|
||||||
|
// @ts-ignore
|
||||||
Header: customHeader ? customHeader : props => (
|
Header: customHeader ? customHeader : props => (
|
||||||
|
// @ts-ignore
|
||||||
<ModalHeader
|
<ModalHeader
|
||||||
{ ...props }
|
{ ...props }
|
||||||
heading = { titleString || t(titleKey) }
|
heading = { titleString || t(titleKey ?? '') }
|
||||||
hideCloseIconButton = { hideCloseIconButton } />
|
hideCloseIconButton = { hideCloseIconButton } />
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
@ -212,8 +199,6 @@ class StatelessDialog extends Component<Props> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderFooter: () => React$Node;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a ReactElement to display buttons for closing the modal.
|
* Returns a ReactElement to display buttons for closing the modal.
|
||||||
*
|
*
|
||||||
|
@ -222,7 +207,7 @@ class StatelessDialog extends Component<Props> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
_renderFooter(propsFromModalFooter) {
|
_renderFooter(propsFromModalFooter: any) {
|
||||||
// Filter out falsy (null) values because {@code ButtonGroup} will error
|
// Filter out falsy (null) values because {@code ButtonGroup} will error
|
||||||
// if passed in anything but buttons with valid type props.
|
// if passed in anything but buttons with valid type props.
|
||||||
const buttons = [
|
const buttons = [
|
||||||
|
@ -252,8 +237,6 @@ class StatelessDialog extends Component<Props> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onCancel: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatches action to hide the dialog.
|
* Dispatches action to hide the dialog.
|
||||||
*
|
*
|
||||||
|
@ -267,8 +250,6 @@ class StatelessDialog extends Component<Props> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDialogDismissed: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles click on the blanket area.
|
* 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.
|
* Dispatches the action when submitting the dialog.
|
||||||
*
|
*
|
||||||
|
@ -289,7 +268,7 @@ class StatelessDialog extends Component<Props> {
|
||||||
* @param {string} value - The submitted value if any.
|
* @param {string} value - The submitted value if any.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onSubmit(value) {
|
_onSubmit(value?: any) {
|
||||||
const { onSubmit } = this.props;
|
const { onSubmit } = this.props;
|
||||||
|
|
||||||
onSubmit && onSubmit(value);
|
onSubmit && onSubmit(value);
|
||||||
|
@ -310,12 +289,13 @@ class StatelessDialog extends Component<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
t /* The following fixes a flow error: */ = _.identity,
|
t,
|
||||||
onDecline
|
onDecline
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
|
accessibilityLabel = { t(this.props.cancelKey || 'dialog.Cancel') }
|
||||||
id = { CANCEL_BUTTON_ID }
|
id = { CANCEL_BUTTON_ID }
|
||||||
key = { CANCEL_BUTTON_ID }
|
key = { CANCEL_BUTTON_ID }
|
||||||
label = { t(this.props.cancelKey || 'dialog.Cancel') }
|
label = { t(this.props.cancelKey || 'dialog.Cancel') }
|
||||||
|
@ -332,16 +312,18 @@ class StatelessDialog extends Component<Props> {
|
||||||
* @returns {ReactElement|null} The OK button if enabled.
|
* @returns {ReactElement|null} The OK button if enabled.
|
||||||
*/
|
*/
|
||||||
_renderOKButton() {
|
_renderOKButton() {
|
||||||
if (this.props.submitDisabled) {
|
const {
|
||||||
|
submitDisabled,
|
||||||
|
t
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if (submitDisabled) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
|
||||||
t /* The following fixes a flow error: */ = _.identity
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
|
accessibilityLabel = { t(this.props.okKey || 'dialog.Ok') }
|
||||||
disabled = { this.props.okDisabled }
|
disabled = { this.props.okDisabled }
|
||||||
id = { OK_BUTTON_ID }
|
id = { OK_BUTTON_ID }
|
||||||
key = { 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.
|
* 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.
|
* 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
|
* @private
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onDialogRef(element: ?Element) {
|
_onDialogRef(element?: any) {
|
||||||
this.props.onDialogRef && this.props.onDialogRef(element && element.parentNode);
|
this.props.onDialogRef && this.props.onDialogRef(element && element.parentNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onKeyPress: (Object) => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles 'Enter' key in the dialog to submit/hide dialog depending on
|
* Handles 'Enter' key in the dialog to submit/hide dialog depending on
|
||||||
* the available buttons and their disabled state.
|
* the available buttons and their disabled state.
|
||||||
|
@ -375,7 +353,7 @@ class StatelessDialog extends Component<Props> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onKeyPress(event) {
|
_onKeyPress(event: React.KeyboardEvent) {
|
||||||
// If the event coming to the dialog has been subject to preventDefault
|
// If the event coming to the dialog has been subject to preventDefault
|
||||||
// we don't handle it here.
|
// we don't handle it here.
|
||||||
if (event.defaultPrevented) {
|
if (event.defaultPrevented) {
|
|
@ -1,31 +1,31 @@
|
||||||
// @flow
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
export type DialogProps = {
|
export type DialogProps = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether cancel button is disabled. Enabled by default.
|
* Whether cancel button is disabled. Enabled by default.
|
||||||
*/
|
*/
|
||||||
cancelDisabled: ?boolean,
|
cancelDisabled?: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional i18n key to change the cancel button title.
|
* Optional i18n key to change the cancel button title.
|
||||||
*/
|
*/
|
||||||
cancelKey: ?string,
|
cancelKey?: string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The React {@code Component} children which represents the dialog's body.
|
* The React {@code Component} children which represents the dialog's body.
|
||||||
*/
|
*/
|
||||||
children: ?React$Node,
|
children?: ReactNode,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is ok button enabled/disabled. Enabled by default.
|
* Is ok button enabled/disabled. Enabled by default.
|
||||||
*/
|
*/
|
||||||
okDisabled: ?boolean,
|
okDisabled?: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional i18n key to change the ok button title.
|
* Optional i18n key to change the ok button title.
|
||||||
*/
|
*/
|
||||||
okKey: ?string,
|
okKey?: string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The handler for onCancel event.
|
* The handler for onCancel event.
|
||||||
|
@ -47,14 +47,14 @@ export type DialogProps = {
|
||||||
/**
|
/**
|
||||||
* Key to use for showing a title.
|
* 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
|
* 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.
|
* value is specified, it takes precedence over {@code titleKey} i.e.
|
||||||
* The latter is unused.
|
* The latter is unused.
|
||||||
*/
|
*/
|
||||||
titleString: ?string
|
titleString?: string
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -159,7 +159,7 @@ export function getFirstLoadableAvatarUrl(participant: Participant, store: IStor
|
||||||
* features/base/participants.
|
* features/base/participants.
|
||||||
* @returns {(Participant|undefined)}
|
* @returns {(Participant|undefined)}
|
||||||
*/
|
*/
|
||||||
export function getLocalParticipant(stateful: IStore | Function) {
|
export function getLocalParticipant(stateful: IStore | Function | IState) {
|
||||||
const state = toState(stateful)['features/base/participants'];
|
const state = toState(stateful)['features/base/participants'];
|
||||||
|
|
||||||
return state.local;
|
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.
|
* @param {string} id - The ID of the participant's display name to retrieve.
|
||||||
* @returns {string}
|
* @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 participant = getParticipantById(stateful, id);
|
||||||
const {
|
const {
|
||||||
defaultLocalDisplayName,
|
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.
|
* @param {string} id - The ID of the screenshare participant's display name to retrieve.
|
||||||
* @returns {string}
|
* @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));
|
const ownerDisplayName = getParticipantDisplayName(stateful, getVirtualScreenshareParticipantOwnerId(id));
|
||||||
|
|
||||||
return i18next.t('screenshareDisplayName', { name: ownerDisplayName });
|
return i18next.t('screenshareDisplayName', { name: ownerDisplayName });
|
||||||
|
@ -648,6 +648,6 @@ export function getRaiseHandsQueue(stateful: IStore | Function): Array<Object> {
|
||||||
* @param {Object} participant - The participant.
|
* @param {Object} participant - The participant.
|
||||||
* @returns {boolean} - Whether participant has raise hand or not.
|
* @returns {boolean} - Whether participant has raise hand or not.
|
||||||
*/
|
*/
|
||||||
export function hasRaisedHand(participant: Participant): boolean {
|
export function hasRaisedHand(participant?: Participant): boolean {
|
||||||
return Boolean(participant && participant.raisedHandTimestamp);
|
return Boolean(participant?.raisedHandTimestamp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,48 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { withStyles } from '@material-ui/styles';
|
import { withStyles } from '@material-ui/styles';
|
||||||
import clsx from 'clsx';
|
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';
|
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||||
|
|
||||||
type Props = {
|
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.
|
* Text css class of the button.
|
||||||
*/
|
*/
|
||||||
className?: string,
|
className?: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object containing the CSS classes.
|
||||||
|
*/
|
||||||
|
classes: any,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the button is disabled or not.
|
* If the button is disabled or not.
|
||||||
*/
|
*/
|
||||||
|
@ -34,10 +53,26 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
hasOptions?: boolean,
|
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.
|
* 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.
|
* The type of th button: primary, secondary, text.
|
||||||
*/
|
*/
|
||||||
type: string,
|
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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,7 +92,7 @@ type Props = {
|
||||||
*
|
*
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
const styles = theme => {
|
const styles = (theme: any) => {
|
||||||
return {
|
return {
|
||||||
actionButton: {
|
actionButton: {
|
||||||
...withPixelLineHeight(theme.typography.bodyLongBold),
|
...withPixelLineHeight(theme.typography.bodyLongBold),
|
||||||
|
@ -254,4 +253,5 @@ function ActionButton({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
export default withStyles(styles)(ActionButton);
|
export default withStyles(styles)(ActionButton);
|
|
@ -1,16 +1,21 @@
|
||||||
// @flow
|
/* eslint-disable lines-around-comment */
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/styles';
|
||||||
import React, { useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
|
import { WithTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { translate } from '../../../i18n';
|
import { IState } from '../../../../app/types';
|
||||||
import { Icon, IconArrowDownSmall, IconWifi1Bar, IconWifi2Bars, IconWifi3Bars } from '../../../icons';
|
import { translate } from '../../../i18n/functions';
|
||||||
import { connect } from '../../../redux';
|
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';
|
import { PREJOIN_DEFAULT_CONTENT_WIDTH } from '../../../ui/components/variables';
|
||||||
|
// @ts-ignore
|
||||||
import { CONNECTION_TYPE } from '../../constants';
|
import { CONNECTION_TYPE } from '../../constants';
|
||||||
|
// @ts-ignore
|
||||||
import { getConnectionData } from '../../functions';
|
import { getConnectionData } from '../../functions';
|
||||||
|
|
||||||
type Props = {
|
interface Props extends WithTranslation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of strings with details about the connection.
|
* 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'.
|
* The type of the connection. Can be: 'none', 'poor', 'nonOptimal' or 'good'.
|
||||||
*/
|
*/
|
||||||
connectionType: string,
|
connectionType: string
|
||||||
|
|
||||||
/**
|
|
||||||
* Used for translation.
|
|
||||||
*/
|
|
||||||
t: Function
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => {
|
const useStyles = makeStyles((theme: any) => {
|
||||||
return {
|
return {
|
||||||
connectionStatus: {
|
connectionStatus: {
|
||||||
borderRadius: '6px',
|
borderRadius: '6px',
|
||||||
|
@ -121,7 +121,7 @@ const useStyles = makeStyles(theme => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const CONNECTION_TYPE_MAP = {
|
const CONNECTION_TYPE_MAP: any = {
|
||||||
[CONNECTION_TYPE.POOR]: {
|
[CONNECTION_TYPE.POOR]: {
|
||||||
connectionClass: 'con-status--poor',
|
connectionClass: 'con-status--poor',
|
||||||
icon: IconWifi1Bar,
|
icon: IconWifi1Bar,
|
||||||
|
@ -152,7 +152,7 @@ function ConnectionStatus({ connectionDetails, t, connectionType }: Props) {
|
||||||
const arrowClassName = showDetails
|
const arrowClassName = showDetails
|
||||||
? 'con-status-arrow con-status-arrow--up'
|
? 'con-status-arrow con-status-arrow--up'
|
||||||
: 'con-status-arrow';
|
: 'con-status-arrow';
|
||||||
const detailsText = connectionDetails.map(t).join(' ');
|
const detailsText = connectionDetails.map(d => t(d)).join(' ');
|
||||||
const detailsClassName = showDetails
|
const detailsClassName = showDetails
|
||||||
? 'con-status-details-visible'
|
? 'con-status-details-visible'
|
||||||
: 'con-status-details-hidden';
|
: 'con-status-details-hidden';
|
||||||
|
@ -202,7 +202,7 @@ function ConnectionStatus({ connectionDetails, t, connectionType }: Props) {
|
||||||
tabIndex = { 0 } />
|
tabIndex = { 0 } />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
aria-level = '2'
|
aria-level = { 2 }
|
||||||
className = { `con-status-details ${detailsClassName}` }
|
className = { `con-status-details ${detailsClassName}` }
|
||||||
role = 'heading'>
|
role = 'heading'>
|
||||||
{detailsText}</div>
|
{detailsText}</div>
|
||||||
|
@ -216,7 +216,7 @@ function ConnectionStatus({ connectionDetails, t, connectionType }: Props) {
|
||||||
* @param {Object} state - The redux state.
|
* @param {Object} state - The redux state.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
function mapStateToProps(state): Object {
|
function mapStateToProps(state: IState): Object {
|
||||||
const { connectionDetails, connectionType } = getConnectionData(state);
|
const { connectionDetails, connectionType } = getConnectionData(state);
|
||||||
|
|
||||||
return {
|
return {
|
|
@ -1,36 +1,37 @@
|
||||||
/* @flow */
|
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/core';
|
import { makeStyles } from '@material-ui/core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { WithTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { translate } from '../../../i18n';
|
import { translate } from '../../../i18n/functions';
|
||||||
import { Icon } from '../../../icons';
|
import Icon from '../../../icons/components/Icon';
|
||||||
|
// eslint-disable-next-line lines-around-comment
|
||||||
|
// @ts-ignore
|
||||||
import { Tooltip } from '../../../tooltip';
|
import { Tooltip } from '../../../tooltip';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} props of {@link BaseIndicator}.
|
* The type of the React {@code Component} props of {@link BaseIndicator}.
|
||||||
*/
|
*/
|
||||||
type Props = {
|
interface Props extends WithTranslation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Additional CSS class name.
|
* Additional CSS class name.
|
||||||
*/
|
*/
|
||||||
className: string,
|
className?: string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The icon component to use.
|
* The icon component to use.
|
||||||
*/
|
*/
|
||||||
icon: Object,
|
icon: Function,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The CSS classnames to set on the icon element of the component.
|
* The CSS classnames to set on the icon element of the component.
|
||||||
*/
|
*/
|
||||||
iconClassName: string,
|
iconClassName?: string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The color of the icon.
|
* The color of the icon.
|
||||||
*/
|
*/
|
||||||
iconColor: ?string,
|
iconColor?: string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Id of the icon to be rendered.
|
* 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.
|
* The ID attribute to set on the root element of the component.
|
||||||
*/
|
*/
|
||||||
id: string,
|
id?: string,
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked to obtain translated strings.
|
|
||||||
*/
|
|
||||||
t: Function,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The translation key to use for displaying a tooltip when hovering over
|
* The translation key to use for displaying a tooltip when hovering over
|
||||||
|
@ -63,7 +59,7 @@ type Props = {
|
||||||
* defaulting to "top".
|
* defaulting to "top".
|
||||||
*/
|
*/
|
||||||
tooltipPosition: string
|
tooltipPosition: string
|
||||||
};
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles(() => {
|
const useStyles = makeStyles(() => {
|
||||||
return {
|
return {
|
||||||
|
@ -95,7 +91,7 @@ const BaseIndicator = ({
|
||||||
tooltipPosition = 'top'
|
tooltipPosition = 'top'
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
const style = {};
|
const style: any = {};
|
||||||
|
|
||||||
if (iconSize) {
|
if (iconSize) {
|
||||||
style.fontSize = iconSize;
|
style.fontSize = iconSize;
|
|
@ -1,8 +1,8 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { createStyles, makeStyles } from '@material-ui/core';
|
import { createStyles, makeStyles } from '@material-ui/core';
|
||||||
|
|
||||||
import { commonStyles, getGlobalStyles } from '../constants';
|
import { commonStyles, getGlobalStyles } from '../constants';
|
||||||
|
// eslint-disable-next-line lines-around-comment
|
||||||
|
// @ts-ignore
|
||||||
import { formatCommonClasses } from '../functions';
|
import { formatCommonClasses } from '../functions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,7 +12,7 @@ import { formatCommonClasses } from '../functions';
|
||||||
*
|
*
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
const useStyles = makeStyles(theme =>
|
const useStyles = makeStyles((theme: any) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
'@global': {
|
'@global': {
|
||||||
...formatCommonClasses(commonStyles(theme)),
|
...formatCommonClasses(commonStyles(theme)),
|
|
@ -1,5 +1,3 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/styles';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/core/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React, { useEffect, useRef } from 'react';
|
import React, { ReactElement, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
import { isMobileBrowser } from '../../../base/environment/utils';
|
import { isMobileBrowser } from '../../../base/environment/utils';
|
||||||
|
|
||||||
|
@ -11,7 +9,7 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* The component(s) that need to be scrollable on mobile.
|
* The component(s) that need to be scrollable on mobile.
|
||||||
*/
|
*/
|
||||||
children: React$Node,
|
children: ReactElement,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the component should be flex container or not.
|
* Whether the component should be flex container or not.
|
||||||
|
@ -48,7 +46,7 @@ function TouchmoveHack({ children, isModal, flex }: Props) {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
const touchMoveElementRef = useRef(null);
|
const touchMoveElementRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atlaskit's {@code Modal} uses a third party library to disable touchmove events
|
* Atlaskit's {@code Modal} uses a third party library to disable touchmove events
|
|
@ -1,15 +1,20 @@
|
||||||
|
/* eslint-disable lines-around-comment */
|
||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/styles';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
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';
|
import { Label } from '../../../base/label';
|
||||||
|
// @ts-ignore
|
||||||
import { Tooltip } from '../../../base/tooltip';
|
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';
|
import { open as openParticipantsPane } from '../../../participants-pane/actions';
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => {
|
const useStyles = makeStyles((theme: any) => {
|
||||||
return {
|
return {
|
||||||
label: {
|
label: {
|
||||||
backgroundColor: theme.palette.warning02,
|
backgroundColor: theme.palette.warning02,
|
||||||
|
@ -22,7 +27,7 @@ const useStyles = makeStyles(theme => {
|
||||||
const RaisedHandsCountLabel = () => {
|
const RaisedHandsCountLabel = () => {
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const raisedHandsCount = useSelector(state =>
|
const raisedHandsCount = useSelector((state: IState) =>
|
||||||
(state['features/base/participants'].raisedHandsQueue || []).length);
|
(state['features/base/participants'].raisedHandsQueue || []).length);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const onClick = useCallback(() => {
|
const onClick = useCallback(() => {
|
||||||
|
@ -38,7 +43,7 @@ const RaisedHandsCountLabel = () => {
|
||||||
iconColor = { BaseTheme.palette.uiBackground }
|
iconColor = { BaseTheme.palette.uiBackground }
|
||||||
id = 'raisedHandsCountLabel'
|
id = 'raisedHandsCountLabel'
|
||||||
onClick = { onClick }
|
onClick = { onClick }
|
||||||
text = { raisedHandsCount } />
|
text = { `${raisedHandsCount}` } />
|
||||||
</Tooltip>);
|
</Tooltip>);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,33 +1,40 @@
|
||||||
// @flow
|
/* eslint-disable lines-around-comment */
|
||||||
|
|
||||||
import { withStyles } from '@material-ui/styles';
|
import { withStyles } from '@material-ui/styles';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { WithTranslation } from 'react-i18next';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
import type { Dispatch } from 'redux';
|
import type { Dispatch } from 'redux';
|
||||||
|
|
||||||
|
import { IState } from '../../../app/types';
|
||||||
|
// @ts-ignore
|
||||||
import { getSourceNameSignalingFeatureFlag } from '../../../base/config';
|
import { getSourceNameSignalingFeatureFlag } from '../../../base/config';
|
||||||
import { translate } from '../../../base/i18n';
|
import { translate } from '../../../base/i18n/functions';
|
||||||
import { MEDIA_TYPE } from '../../../base/media';
|
import { MEDIA_TYPE } from '../../../base/media/constants';
|
||||||
import { getLocalParticipant, getParticipantById } from '../../../base/participants';
|
import { getLocalParticipant, getParticipantById } from '../../../base/participants/functions';
|
||||||
|
// @ts-ignore
|
||||||
import { Popover } from '../../../base/popover';
|
import { Popover } from '../../../base/popover';
|
||||||
import { connect } from '../../../base/redux';
|
|
||||||
import {
|
import {
|
||||||
getVirtualScreenshareParticipantTrack,
|
getVirtualScreenshareParticipantTrack,
|
||||||
getSourceNameByParticipantId,
|
getSourceNameByParticipantId, // @ts-ignore
|
||||||
getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
|
getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
|
||||||
import {
|
import {
|
||||||
isParticipantConnectionStatusInactive,
|
isParticipantConnectionStatusInactive,
|
||||||
isParticipantConnectionStatusInterrupted,
|
isParticipantConnectionStatusInterrupted,
|
||||||
isTrackStreamingStatusInactive,
|
isTrackStreamingStatusInactive,
|
||||||
isTrackStreamingStatusInterrupted
|
isTrackStreamingStatusInterrupted
|
||||||
|
// @ts-ignore
|
||||||
} from '../../functions';
|
} from '../../functions';
|
||||||
import AbstractConnectionIndicator, {
|
import AbstractConnectionIndicator, {
|
||||||
INDICATOR_DISPLAY_THRESHOLD,
|
INDICATOR_DISPLAY_THRESHOLD,
|
||||||
type Props as AbstractProps,
|
type Props as AbstractProps,
|
||||||
type State as AbstractState
|
type State as AbstractState
|
||||||
|
// @ts-ignore
|
||||||
} from '../AbstractConnectionIndicator';
|
} from '../AbstractConnectionIndicator';
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
import ConnectionIndicatorContent from './ConnectionIndicatorContent';
|
import ConnectionIndicatorContent from './ConnectionIndicatorContent';
|
||||||
|
// @ts-ignore
|
||||||
import { ConnectionIndicatorIcon } from './ConnectionIndicatorIcon';
|
import { ConnectionIndicatorIcon } from './ConnectionIndicatorIcon';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,7 +44,11 @@ import { ConnectionIndicatorIcon } from './ConnectionIndicatorIcon';
|
||||||
*
|
*
|
||||||
* @type {Object[]}
|
* @type {Object[]}
|
||||||
*/
|
*/
|
||||||
const QUALITY_TO_WIDTH: Array<Object> = [
|
const QUALITY_TO_WIDTH: Array<{
|
||||||
|
colorClass: string;
|
||||||
|
percent: number;
|
||||||
|
tip: string;
|
||||||
|
}> = [
|
||||||
|
|
||||||
// Full (3 bars)
|
// Full (3 bars)
|
||||||
{
|
{
|
||||||
|
@ -66,7 +77,12 @@ const QUALITY_TO_WIDTH: Array<Object> = [
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} props of {@link ConnectionIndicator}.
|
* 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
|
* The current condition of the user's connection, matching one of the
|
||||||
|
@ -74,16 +90,21 @@ type Props = AbstractProps & {
|
||||||
*/
|
*/
|
||||||
_connectionStatus: string,
|
_connectionStatus: string,
|
||||||
|
|
||||||
/**
|
|
||||||
* Disable/enable inactive indicator.
|
|
||||||
*/
|
|
||||||
_connectionIndicatorInactiveDisabled: boolean,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the indicator popover is disabled.
|
* Whether the indicator popover is disabled.
|
||||||
*/
|
*/
|
||||||
_popoverDisabled: boolean,
|
_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
|
* Whether or not the component should ignore setting a visibility class for
|
||||||
* hiding the component when the connection quality is not strong.
|
* hiding the component when the connection quality is not strong.
|
||||||
|
@ -95,6 +116,7 @@ type Props = AbstractProps & {
|
||||||
*/
|
*/
|
||||||
audioSsrc: number,
|
audioSsrc: number,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object containing the CSS classes.
|
* An object containing the CSS classes.
|
||||||
*/
|
*/
|
||||||
|
@ -105,7 +127,6 @@ type Props = AbstractProps & {
|
||||||
*/
|
*/
|
||||||
dispatch: Dispatch<any>,
|
dispatch: Dispatch<any>,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not clicking the indicator should display a popover for more
|
* Whether or not clicking the indicator should display a popover for more
|
||||||
* details.
|
* details.
|
||||||
|
@ -121,22 +142,7 @@ type Props = AbstractProps & {
|
||||||
* Relative to the icon from where the popover for more connection details
|
* Relative to the icon from where the popover for more connection details
|
||||||
* should display.
|
* should display.
|
||||||
*/
|
*/
|
||||||
statsPopoverPosition: string,
|
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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = AbstractState & {
|
type State = AbstractState & {
|
||||||
|
@ -147,7 +153,7 @@ type State = AbstractState & {
|
||||||
popoverVisible: boolean
|
popoverVisible: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = theme => {
|
const styles = (theme: any) => {
|
||||||
return {
|
return {
|
||||||
container: {
|
container: {
|
||||||
display: 'inline-block'
|
display: 'inline-block'
|
||||||
|
@ -209,6 +215,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
this.state = {
|
this.state = {
|
||||||
showIndicator: false,
|
showIndicator: false,
|
||||||
stats: {},
|
stats: {},
|
||||||
|
@ -225,9 +232,11 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
|
// @ts-ignore
|
||||||
const { enableStatsDisplay, participantId, statsPopoverPosition, classes } = this.props;
|
const { enableStatsDisplay, participantId, statsPopoverPosition, classes } = this.props;
|
||||||
const visibilityClass = this._getVisibilityClass();
|
const visibilityClass = this._getVisibilityClass();
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
if (this.props._popoverDisabled) {
|
if (this.props._popoverDisabled) {
|
||||||
return this._renderIndicator();
|
return this._renderIndicator();
|
||||||
}
|
}
|
||||||
|
@ -236,6 +245,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
|
||||||
<Popover
|
<Popover
|
||||||
className = { clsx(classes.container, visibilityClass) }
|
className = { clsx(classes.container, visibilityClass) }
|
||||||
content = { <ConnectionIndicatorContent
|
content = { <ConnectionIndicatorContent
|
||||||
|
// @ts-ignore
|
||||||
inheritedStats = { this.state.stats }
|
inheritedStats = { this.state.stats }
|
||||||
participantId = { participantId } /> }
|
participantId = { participantId } /> }
|
||||||
disablePopover = { !enableStatsDisplay }
|
disablePopover = { !enableStatsDisplay }
|
||||||
|
@ -244,6 +254,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
|
||||||
onPopoverClose = { this._onHidePopover }
|
onPopoverClose = { this._onHidePopover }
|
||||||
onPopoverOpen = { this._onShowPopover }
|
onPopoverOpen = { this._onShowPopover }
|
||||||
position = { statsPopoverPosition }
|
position = { statsPopoverPosition }
|
||||||
|
// @ts-ignore
|
||||||
visible = { this.state.popoverVisible }>
|
visible = { this.state.popoverVisible }>
|
||||||
{ this._renderIndicator() }
|
{ this._renderIndicator() }
|
||||||
</Popover>
|
</Popover>
|
||||||
|
@ -259,12 +270,14 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
|
||||||
*/
|
*/
|
||||||
_getConnectionColorClass() {
|
_getConnectionColorClass() {
|
||||||
// TODO We currently do not have logic to emit and handle stats changes for tracks.
|
// TODO We currently do not have logic to emit and handle stats changes for tracks.
|
||||||
|
// @ts-ignore
|
||||||
const { percent } = this.state.stats;
|
const { percent } = this.state.stats;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
_isConnectionStatusInactive,
|
_isConnectionStatusInactive,
|
||||||
_isConnectionStatusInterrupted,
|
_isConnectionStatusInterrupted,
|
||||||
_connectionIndicatorInactiveDisabled
|
_connectionIndicatorInactiveDisabled
|
||||||
|
// @ts-ignore
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (_isConnectionStatusInactive) {
|
if (_isConnectionStatusInactive) {
|
||||||
|
@ -293,7 +306,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
_getDisplayConfiguration(percent: number): Object {
|
_getDisplayConfiguration(percent: number): any {
|
||||||
return QUALITY_TO_WIDTH.find(x => percent >= x.percent) || {};
|
return QUALITY_TO_WIDTH.find(x => percent >= x.percent) || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,17 +318,18 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
_getVisibilityClass() {
|
_getVisibilityClass() {
|
||||||
|
// @ts-ignore
|
||||||
const { _isConnectionStatusInactive, _isConnectionStatusInterrupted, classes } = this.props;
|
const { _isConnectionStatusInactive, _isConnectionStatusInterrupted, classes } = this.props;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
return this.state.showIndicator
|
return this.state.showIndicator
|
||||||
|
// @ts-ignore
|
||||||
|| this.props.alwaysVisible
|
|| this.props.alwaysVisible
|
||||||
|| _isConnectionStatusInterrupted
|
|| _isConnectionStatusInterrupted
|
||||||
|| _isConnectionStatusInactive
|
|| _isConnectionStatusInactive
|
||||||
? '' : classes.hidden;
|
? '' : classes.hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onHidePopover: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hides popover.
|
* Hides popover.
|
||||||
*
|
*
|
||||||
|
@ -323,12 +337,10 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onHidePopover() {
|
_onHidePopover() {
|
||||||
|
// @ts-ignore
|
||||||
this.setState({ popoverVisible: false });
|
this.setState({ popoverVisible: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_onShowPopover: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows popover.
|
* Shows popover.
|
||||||
*
|
*
|
||||||
|
@ -336,6 +348,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onShowPopover() {
|
_onShowPopover() {
|
||||||
|
// @ts-ignore
|
||||||
this.setState({ popoverVisible: true });
|
this.setState({ popoverVisible: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,6 +366,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
|
||||||
_videoTrack,
|
_videoTrack,
|
||||||
classes,
|
classes,
|
||||||
iconSize
|
iconSize
|
||||||
|
// @ts-ignore
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -377,7 +391,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<Props, State> {
|
||||||
* @param {Props} ownProps - The own props of the component.
|
* @param {Props} ownProps - The own props of the component.
|
||||||
* @returns {Props}
|
* @returns {Props}
|
||||||
*/
|
*/
|
||||||
export function _mapStateToProps(state: Object, ownProps: Props) {
|
export function _mapStateToProps(state: IState, ownProps: Props) {
|
||||||
const { participantId } = ownProps;
|
const { participantId } = ownProps;
|
||||||
const tracks = state['features/base/tracks'];
|
const tracks = state['features/base/tracks'];
|
||||||
const sourceNameSignalingEnabled = getSourceNameSignalingFeatureFlag(state);
|
const sourceNameSignalingEnabled = getSourceNameSignalingFeatureFlag(state);
|
||||||
|
@ -411,4 +425,5 @@ export function _mapStateToProps(state: Object, ownProps: Props) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export default translate(connect(_mapStateToProps)(
|
export default translate(connect(_mapStateToProps)(
|
||||||
|
// @ts-ignore
|
||||||
withStyles(styles)(ConnectionIndicator)));
|
withStyles(styles)(ConnectionIndicator)));
|
|
@ -1,18 +1,22 @@
|
||||||
/* @flow */
|
|
||||||
|
|
||||||
import { withStyles } from '@material-ui/styles';
|
import { withStyles } from '@material-ui/styles';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React, { Component } from 'react';
|
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 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
|
* The type of the React {@code Component} props of
|
||||||
* {@link ConnectionStatsTable}.
|
* {@link ConnectionStatsTable}.
|
||||||
*/
|
*/
|
||||||
type Props = {
|
interface Props extends WithTranslation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The audio SSRC of this client.
|
* The audio SSRC of this client.
|
||||||
|
@ -26,7 +30,7 @@ type Props = {
|
||||||
* upload: Number
|
* upload: Number
|
||||||
* }}.
|
* }}.
|
||||||
*/
|
*/
|
||||||
bandwidth: Object,
|
bandwidth: DownloadUpload,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Statistics related to bitrate.
|
* Statistics related to bitrate.
|
||||||
|
@ -35,7 +39,7 @@ type Props = {
|
||||||
* upload: Number
|
* upload: Number
|
||||||
* }}.
|
* }}.
|
||||||
*/
|
*/
|
||||||
bitrate: Object,
|
bitrate: DownloadUpload,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of bridges (aka media servers) currently used in the
|
* The number of bridges (aka media servers) currently used in the
|
||||||
|
@ -46,18 +50,28 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* An object containing the CSS classes.
|
* An object containing the CSS classes.
|
||||||
*/
|
*/
|
||||||
classes: Object,
|
classes: any,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Audio/video codecs in use for the connection.
|
* Audio/video codecs in use for the connection.
|
||||||
*/
|
*/
|
||||||
codec: Object,
|
codec: {
|
||||||
|
[key: string]: {
|
||||||
|
audio: string;
|
||||||
|
video: string;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A message describing the connection quality.
|
* A message describing the connection quality.
|
||||||
*/
|
*/
|
||||||
connectionSummary: string,
|
connectionSummary: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not should display the "Show More" link.
|
||||||
|
*/
|
||||||
|
disableShowMoreStats: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The end-to-end round-trip-time.
|
* The end-to-end round-trip-time.
|
||||||
*/
|
*/
|
||||||
|
@ -68,16 +82,6 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
enableSaveLogs: boolean,
|
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.
|
* 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.
|
* 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.
|
* Callback to invoke when the show additional stats link is clicked.
|
||||||
*/
|
*/
|
||||||
onShowMore: Function,
|
onShowMore: (e?: React.MouseEvent) => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Statistics related to packet loss.
|
* Statistics related to packet loss.
|
||||||
|
@ -119,7 +123,12 @@ type Props = {
|
||||||
* upload: Number
|
* upload: Number
|
||||||
* }}.
|
* }}.
|
||||||
*/
|
*/
|
||||||
packetLoss: Object,
|
packetLoss: DownloadUpload,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The endpoint id of this client.
|
||||||
|
*/
|
||||||
|
participantId: string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The region that we think the client is in.
|
* 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.
|
* The region of the media server that we are connected to.
|
||||||
|
@ -149,25 +163,28 @@ type Props = {
|
||||||
shouldShowMore: boolean,
|
shouldShowMore: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked to obtain translated strings.
|
* Whether source name signaling is enabled.
|
||||||
*/
|
*/
|
||||||
t: Function,
|
sourceNameSignalingEnabled: boolean,
|
||||||
|
|
||||||
/**
|
|
||||||
* The video SSRC of this client.
|
|
||||||
*/
|
|
||||||
videoSsrc: number,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Statistics related to transports.
|
* 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.
|
* Click handler.
|
||||||
|
@ -175,13 +192,13 @@ type Props = {
|
||||||
* @param {SyntheticEvent} event - The click event.
|
* @param {SyntheticEvent} event - The click event.
|
||||||
* @returns {void}
|
* @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
|
// If the event is propagated to the thumbnail container the participant will be pinned. That's why the propagation
|
||||||
// needs to be stopped.
|
// needs to be stopped.
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = theme => {
|
const styles = (theme: any) => {
|
||||||
return {
|
return {
|
||||||
actions: {
|
actions: {
|
||||||
margin: '10px auto',
|
margin: '10px auto',
|
||||||
|
@ -599,7 +616,7 @@ class ConnectionStatsTable extends Component<Props> {
|
||||||
frameRateString = framerate || 'N/A';
|
frameRateString = framerate || 'N/A';
|
||||||
} else {
|
} else {
|
||||||
frameRateString = Object.keys(framerate || {})
|
frameRateString = Object.keys(framerate || {})
|
||||||
.map(ssrc => framerate[ssrc])
|
.map(ssrc => framerate[ssrc as keyof typeof framerate])
|
||||||
.join(', ') || 'N/A';
|
.join(', ') || 'N/A';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -791,7 +808,13 @@ class ConnectionStatsTable extends Component<Props> {
|
||||||
return [ NA ];
|
return [ NA ];
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
const data: {
|
||||||
|
localIP: string[],
|
||||||
|
localPort: string[],
|
||||||
|
remoteIP: string[],
|
||||||
|
remotePort: string[],
|
||||||
|
transportType: string[]
|
||||||
|
} = {
|
||||||
localIP: [],
|
localIP: [],
|
||||||
localPort: [],
|
localPort: [],
|
||||||
remoteIP: [],
|
remoteIP: [],
|
||||||
|
@ -897,7 +920,7 @@ class ConnectionStatsTable extends Component<Props> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
_renderTransportTableRow(config: Object) {
|
_renderTransportTableRow(config: any) {
|
||||||
const { additionalData, data, key, label } = config;
|
const { additionalData, data, key, label } = config;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -924,7 +947,7 @@ class ConnectionStatsTable extends Component<Props> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
function getIP(value) {
|
function getIP(value: string) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -940,7 +963,7 @@ function getIP(value) {
|
||||||
* @private
|
* @private
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
function getPort(value) {
|
function getPort(value: string) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -955,7 +978,7 @@ function getPort(value) {
|
||||||
* @private
|
* @private
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
function getStringFromArray(array) {
|
function getStringFromArray(array: string[]) {
|
||||||
let res = '';
|
let res = '';
|
||||||
|
|
||||||
for (let i = 0; i < array.length; i++) {
|
for (let i = 0; i < array.length; i++) {
|
||||||
|
@ -965,4 +988,5 @@ function getStringFromArray(array) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
export default translate(withStyles(styles)(ConnectionStatsTable));
|
export default translate(withStyles(styles)(ConnectionStatsTable));
|
|
@ -1,24 +1,28 @@
|
||||||
/* @flow */
|
/* eslint-disable lines-around-comment */
|
||||||
|
|
||||||
import { withStyles } from '@material-ui/styles';
|
import { withStyles } from '@material-ui/styles';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import { WithTranslation } from 'react-i18next';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
import type { Dispatch } from 'redux';
|
import type { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { translate } from '../../../base/i18n';
|
import { IState } from '../../../app/types';
|
||||||
|
import { translate } from '../../../base/i18n/functions';
|
||||||
import {
|
import {
|
||||||
getParticipantDisplayName,
|
getParticipantDisplayName,
|
||||||
getParticipantById
|
getParticipantById
|
||||||
} from '../../../base/participants';
|
} from '../../../base/participants/functions';
|
||||||
import { connect } from '../../../base/redux';
|
// @ts-ignore
|
||||||
import { updateSettings } from '../../../base/settings';
|
import { updateSettings } from '../../../base/settings';
|
||||||
|
// @ts-ignore
|
||||||
import { Tooltip } from '../../../base/tooltip';
|
import { Tooltip } from '../../../base/tooltip';
|
||||||
|
// @ts-ignore
|
||||||
import { getIndicatorsTooltipPosition } from '../../../filmstrip/functions.web';
|
import { getIndicatorsTooltipPosition } from '../../../filmstrip/functions.web';
|
||||||
import { appendSuffix } from '../../functions';
|
import { appendSuffix } from '../../functions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} props of {@link DisplayName}.
|
* 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
|
* The participant's current display name which should be shown when in
|
||||||
|
@ -36,6 +40,11 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
allowEditing: boolean,
|
allowEditing: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object containing the CSS classes.
|
||||||
|
*/
|
||||||
|
classes: any,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked to update the participant's display name.
|
* Invoked to update the participant's display name.
|
||||||
*/
|
*/
|
||||||
|
@ -46,11 +55,6 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
displayNameSuffix: string,
|
displayNameSuffix: string,
|
||||||
|
|
||||||
/**
|
|
||||||
* An object containing the CSS classes.
|
|
||||||
*/
|
|
||||||
classes: Object,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ID attribute to add to the component. Useful for global querying for
|
* The ID attribute to add to the component. Useful for global querying for
|
||||||
* the component by legacy components and torture tests.
|
* the component by legacy components and torture tests.
|
||||||
|
@ -62,16 +66,11 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
participantID: string,
|
participantID: string,
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked to obtain translated strings.
|
|
||||||
*/
|
|
||||||
t: Function,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of thumbnail.
|
* The type of thumbnail.
|
||||||
*/
|
*/
|
||||||
thumbnailType: string
|
thumbnailType: string
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} state of {@link DisplayName}.
|
* The type of the React {@code Component} state of {@link DisplayName}.
|
||||||
|
@ -89,7 +88,7 @@ type State = {
|
||||||
isEditing: boolean
|
isEditing: boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = theme => {
|
const styles = (theme: any) => {
|
||||||
return {
|
return {
|
||||||
displayName: {
|
displayName: {
|
||||||
...theme.typography.labelBold,
|
...theme.typography.labelBold,
|
||||||
|
@ -119,7 +118,7 @@ const styles = theme => {
|
||||||
* @augments Component
|
* @augments Component
|
||||||
*/
|
*/
|
||||||
class DisplayName extends Component<Props, State> {
|
class DisplayName extends Component<Props, State> {
|
||||||
_nameInput: ?HTMLInputElement;
|
_nameInput?: HTMLInputElement;
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
_configuredDisplayName: ''
|
_configuredDisplayName: ''
|
||||||
|
@ -148,7 +147,7 @@ class DisplayName extends Component<Props, State> {
|
||||||
* @private
|
* @private
|
||||||
* @type {HTMLInputElement}
|
* @type {HTMLInputElement}
|
||||||
*/
|
*/
|
||||||
this._nameInput = null;
|
this._nameInput = undefined;
|
||||||
|
|
||||||
// Bind event handlers so they are only bound once for every instance.
|
// Bind event handlers so they are only bound once for every instance.
|
||||||
this._onChange = this._onChange.bind(this);
|
this._onChange = this._onChange.bind(this);
|
||||||
|
@ -165,7 +164,7 @@ class DisplayName extends Component<Props, State> {
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
componentDidUpdate(previousProps, previousState) {
|
componentDidUpdate(previousProps: Props, previousState: State) {
|
||||||
if (!previousState.isEditing
|
if (!previousState.isEditing
|
||||||
&& this.state.isEditing
|
&& this.state.isEditing
|
||||||
&& this._nameInput) {
|
&& this._nameInput) {
|
||||||
|
@ -229,12 +228,10 @@ class DisplayName extends Component<Props, State> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onClick(e) {
|
_onClick(e: React.MouseEvent) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onChange: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the internal state of the display name entered into the edit
|
* Updates the internal state of the display name entered into the edit
|
||||||
* field.
|
* field.
|
||||||
|
@ -243,14 +240,12 @@ class DisplayName extends Component<Props, State> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onChange(event) {
|
_onChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||||
this.setState({
|
this.setState({
|
||||||
editDisplayNameValue: event.target.value
|
editDisplayNameValue: event.target.value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_onKeyDown: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submits the edited display name update if the enter key is pressed.
|
* Submits the edited display name update if the enter key is pressed.
|
||||||
*
|
*
|
||||||
|
@ -258,14 +253,12 @@ class DisplayName extends Component<Props, State> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onKeyDown(event) {
|
_onKeyDown(event: React.KeyboardEvent) {
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
this._onSubmit();
|
this._onSubmit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onStartEditing: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the component to display an editable input field and sets the
|
* Updates the component to display an editable input field and sets the
|
||||||
* initial value to the current display name.
|
* initial value to the current display name.
|
||||||
|
@ -274,7 +267,7 @@ class DisplayName extends Component<Props, State> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onStartEditing(e) {
|
_onStartEditing(e: React.MouseEvent) {
|
||||||
if (this.props.allowEditing) {
|
if (this.props.allowEditing) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.setState({
|
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
|
* Dispatches an action to update the display name if any change has
|
||||||
* occurred after editing. Clears any temporary state used to keep track
|
* occurred after editing. Clears any temporary state used to keep track
|
||||||
|
@ -309,11 +300,9 @@ class DisplayName extends Component<Props, State> {
|
||||||
editDisplayNameValue: ''
|
editDisplayNameValue: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
this._nameInput = null;
|
this._nameInput = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
_setNameInputRef: (HTMLInputElement | null) => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the internal reference to the HTML element backing the React
|
* Sets the internal reference to the HTML element backing the React
|
||||||
* {@code Component} input with id {@code editDisplayName}.
|
* {@code Component} input with id {@code editDisplayName}.
|
||||||
|
@ -323,7 +312,7 @@ class DisplayName extends Component<Props, State> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_setNameInputRef(element) {
|
_setNameInputRef(element: HTMLInputElement) {
|
||||||
this._nameInput = element;
|
this._nameInput = element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,13 +328,13 @@ class DisplayName extends Component<Props, State> {
|
||||||
* _nameToDisplay: string
|
* _nameToDisplay: string
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
function _mapStateToProps(state, ownProps) {
|
function _mapStateToProps(state: IState, ownProps: Partial<Props>) {
|
||||||
const { participantID } = ownProps;
|
const { participantID } = ownProps;
|
||||||
const participant = getParticipantById(state, participantID);
|
const participant = getParticipantById(state, participantID ?? '');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_configuredDisplayName: participant && participant.name,
|
_configuredDisplayName: participant && participant.name,
|
||||||
_nameToDisplay: getParticipantDisplayName(state, participantID)
|
_nameToDisplay: getParticipantDisplayName(state, participantID ?? '')
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,25 @@
|
||||||
// @flow
|
/* eslint-disable lines-around-comment */
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/core/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
import { IState } from '../../../app/types';
|
||||||
|
// @ts-ignore
|
||||||
import { isDisplayNameVisible } from '../../../base/config/functions.any';
|
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';
|
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||||
|
// @ts-ignore
|
||||||
import { getLargeVideoParticipant } from '../../../large-video/functions';
|
import { getLargeVideoParticipant } from '../../../large-video/functions';
|
||||||
|
// @ts-ignore
|
||||||
import { isToolboxVisible } from '../../../toolbox/functions.web';
|
import { isToolboxVisible } from '../../../toolbox/functions.web';
|
||||||
|
// @ts-ignore
|
||||||
import { isLayoutTileView } from '../../../video-layout';
|
import { isLayoutTileView } from '../../../video-layout';
|
||||||
|
|
||||||
import DisplayNameBadge from './DisplayNameBadge';
|
import DisplayNameBadge from './DisplayNameBadge';
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => {
|
const useStyles = makeStyles((theme: any) => {
|
||||||
return {
|
return {
|
||||||
badgeContainer: {
|
badgeContainer: {
|
||||||
...withPixelLineHeight(theme.typography.bodyShortRegularLarge),
|
...withPixelLineHeight(theme.typography.bodyShortRegularLarge),
|
||||||
|
@ -43,15 +48,15 @@ const useStyles = makeStyles(theme => {
|
||||||
*/
|
*/
|
||||||
const StageParticipantNameLabel = () => {
|
const StageParticipantNameLabel = () => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const largeVideoParticipant = useSelector(getLargeVideoParticipant);
|
const largeVideoParticipant: Participant = useSelector(getLargeVideoParticipant);
|
||||||
const selectedId = largeVideoParticipant?.id;
|
const selectedId = largeVideoParticipant?.id;
|
||||||
const nameToDisplay = useSelector(state => getParticipantDisplayName(state, selectedId));
|
const nameToDisplay = useSelector((state: IState) => getParticipantDisplayName(state, selectedId));
|
||||||
|
|
||||||
const localParticipant = useSelector(getLocalParticipant);
|
const localParticipant = useSelector(getLocalParticipant);
|
||||||
const localId = localParticipant?.id;
|
const localId = localParticipant?.id;
|
||||||
|
|
||||||
const isTileView = useSelector(isLayoutTileView);
|
const isTileView = useSelector(isLayoutTileView);
|
||||||
const toolboxVisible = useSelector(isToolboxVisible);
|
const toolboxVisible: boolean = useSelector(isToolboxVisible);
|
||||||
const showDisplayName = useSelector(isDisplayNameVisible);
|
const showDisplayName = useSelector(isDisplayNameVisible);
|
||||||
|
|
||||||
if (showDisplayName && nameToDisplay && selectedId !== localId && !isTileView) {
|
if (showDisplayName && nameToDisplay && selectedId !== localId && !isTileView) {
|
|
@ -1,5 +1,3 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { createMuiTheme } from '@material-ui/core/styles';
|
import { createMuiTheme } from '@material-ui/core/styles';
|
||||||
|
|
||||||
import { font, colors, colorMap, spacing, shape, typography, breakpoints } from '../base/ui/Tokens';
|
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.
|
* @param {Object} customTheme - The branded custom theme.
|
||||||
* @returns {Object} - The MUI theme.
|
* @returns {Object} - The MUI theme.
|
||||||
*/
|
*/
|
||||||
export function createMuiBrandingTheme(customTheme: Object) {
|
export function createMuiBrandingTheme(customTheme: any) {
|
||||||
const {
|
const {
|
||||||
palette: customPalette,
|
palette: customPalette,
|
||||||
shape: customShape,
|
shape: customShape,
|
||||||
|
@ -82,9 +80,10 @@ export function createMuiBrandingTheme(customTheme: Object) {
|
||||||
function overwriteRecurrsive(obj1: Object, obj2: Object) {
|
function overwriteRecurrsive(obj1: Object, obj2: Object) {
|
||||||
Object.keys(obj2).forEach(key => {
|
Object.keys(obj2).forEach(key => {
|
||||||
if (obj1.hasOwnProperty(key)) {
|
if (obj1.hasOwnProperty(key)) {
|
||||||
if (typeof obj1[key] === 'object') {
|
if (typeof obj1[key as keyof typeof obj1] === 'object') {
|
||||||
overwriteRecurrsive(obj1[key], obj2[key]);
|
overwriteRecurrsive(obj1[key as keyof typeof obj1], obj2[key as keyof typeof obj2]);
|
||||||
} else {
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
obj1[key] = obj2[key];
|
obj1[key] = obj2[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
/* @flow */
|
/* eslint-disable lines-around-comment */
|
||||||
|
|
||||||
import { withStyles } from '@material-ui/styles';
|
import { withStyles } from '@material-ui/styles';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import { WithTranslation } from 'react-i18next';
|
||||||
import { FixedSizeList, FixedSizeGrid } from 'react-window';
|
import { FixedSizeList, FixedSizeGrid } from 'react-window';
|
||||||
import type { Dispatch } from 'redux';
|
import type { Dispatch } from 'redux';
|
||||||
|
|
||||||
|
@ -11,15 +11,23 @@ import {
|
||||||
createShortcutEvent,
|
createShortcutEvent,
|
||||||
createToolbarEvent,
|
createToolbarEvent,
|
||||||
sendAnalytics
|
sendAnalytics
|
||||||
|
// @ts-ignore
|
||||||
} from '../../../analytics';
|
} from '../../../analytics';
|
||||||
|
// @ts-ignore
|
||||||
import { getSourceNameSignalingFeatureFlag, getToolbarButtons } from '../../../base/config';
|
import { getSourceNameSignalingFeatureFlag, getToolbarButtons } from '../../../base/config';
|
||||||
import { isMobileBrowser } from '../../../base/environment/utils';
|
import { isMobileBrowser } from '../../../base/environment/utils';
|
||||||
import { translate } from '../../../base/i18n';
|
import { translate } from '../../../base/i18n/functions';
|
||||||
import { Icon, IconMenuDown, IconMenuUp } from '../../../base/icons';
|
import Icon from '../../../base/icons/components/Icon';
|
||||||
import { connect } from '../../../base/redux';
|
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';
|
import { shouldHideSelfView } from '../../../base/settings/functions.any';
|
||||||
|
// @ts-ignore
|
||||||
import { showToolbox } from '../../../toolbox/actions.web';
|
import { showToolbox } from '../../../toolbox/actions.web';
|
||||||
|
// @ts-ignore
|
||||||
import { isButtonEnabled, isToolboxVisible } from '../../../toolbox/functions.web';
|
import { isButtonEnabled, isToolboxVisible } from '../../../toolbox/functions.web';
|
||||||
|
// @ts-ignore
|
||||||
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
|
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
|
||||||
import {
|
import {
|
||||||
setFilmstripVisible,
|
setFilmstripVisible,
|
||||||
|
@ -28,6 +36,7 @@ import {
|
||||||
setUserIsResizing,
|
setUserIsResizing,
|
||||||
setTopPanelVisible,
|
setTopPanelVisible,
|
||||||
setVisibleRemoteParticipants
|
setVisibleRemoteParticipants
|
||||||
|
// @ts-ignore
|
||||||
} from '../../actions';
|
} from '../../actions';
|
||||||
import {
|
import {
|
||||||
ASPECT_RATIO_BREAKPOINT,
|
ASPECT_RATIO_BREAKPOINT,
|
||||||
|
@ -43,51 +52,55 @@ import {
|
||||||
getVerticalViewMaxWidth,
|
getVerticalViewMaxWidth,
|
||||||
shouldRemoteVideosBeVisible,
|
shouldRemoteVideosBeVisible,
|
||||||
isStageFilmstripTopPanel
|
isStageFilmstripTopPanel
|
||||||
|
// @ts-ignore
|
||||||
} from '../../functions';
|
} from '../../functions';
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
import AudioTracksContainer from './AudioTracksContainer';
|
import AudioTracksContainer from './AudioTracksContainer';
|
||||||
|
// @ts-ignore
|
||||||
import Thumbnail from './Thumbnail';
|
import Thumbnail from './Thumbnail';
|
||||||
|
// @ts-ignore
|
||||||
import ThumbnailWrapper from './ThumbnailWrapper';
|
import ThumbnailWrapper from './ThumbnailWrapper';
|
||||||
|
// @ts-ignore
|
||||||
import { styles } from './styles';
|
import { styles } from './styles';
|
||||||
|
|
||||||
declare var APP: Object;
|
declare let APP: any;
|
||||||
declare var interfaceConfig: Object;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} props of {@link Filmstrip}.
|
* 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.
|
* Additional CSS class names top add to the root.
|
||||||
*/
|
*/
|
||||||
_className: string,
|
_className: string,
|
||||||
|
|
||||||
/**
|
|
||||||
* The current layout of the filmstrip.
|
|
||||||
*/
|
|
||||||
_currentLayout: string,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of columns in tile view.
|
* The number of columns in tile view.
|
||||||
*/
|
*/
|
||||||
_columns: number,
|
_columns: number,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current layout of the filmstrip.
|
||||||
|
*/
|
||||||
|
_currentLayout: string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not to hide the self view.
|
* Whether or not to hide the self view.
|
||||||
*/
|
*/
|
||||||
_disableSelfView: boolean,
|
_disableSelfView: boolean,
|
||||||
|
|
||||||
/**
|
|
||||||
* The width of the filmstrip.
|
|
||||||
*/
|
|
||||||
_filmstripWidth: number,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The height of the filmstrip.
|
* The height of the filmstrip.
|
||||||
*/
|
*/
|
||||||
_filmstripHeight: number,
|
_filmstripHeight: number,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The width of the filmstrip.
|
||||||
|
*/
|
||||||
|
_filmstripWidth: number,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not we have scroll on the filmstrip.
|
* 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.
|
* 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.
|
* Whether or not the filmstrip videos should currently be displayed.
|
||||||
|
@ -173,16 +186,16 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
_topPanelFilmstrip: boolean,
|
_topPanelFilmstrip: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The height of the top panel (user resized).
|
||||||
|
*/
|
||||||
|
_topPanelHeight?: number,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The max height of the top panel.
|
* The max height of the top panel.
|
||||||
*/
|
*/
|
||||||
_topPanelMaxHeight: number,
|
_topPanelMaxHeight: number,
|
||||||
|
|
||||||
/**
|
|
||||||
* The height of the top panel (user resized).
|
|
||||||
*/
|
|
||||||
_topPanelHeight: ?number,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the top panel is visible.
|
* Whether or not the top panel is visible.
|
||||||
*/
|
*/
|
||||||
|
@ -191,7 +204,7 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* The width of the vertical filmstrip (user resized).
|
* The width of the vertical filmstrip (user resized).
|
||||||
*/
|
*/
|
||||||
_verticalFilmstripWidth: ?number,
|
_verticalFilmstripWidth?: number,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the vertical filmstrip should have a background color.
|
* Whether or not the vertical filmstrip should have a background color.
|
||||||
|
@ -216,7 +229,7 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* An object containing the CSS classes.
|
* An object containing the CSS classes.
|
||||||
*/
|
*/
|
||||||
classes: Object,
|
classes: any,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The redux {@code dispatch} function.
|
* The redux {@code dispatch} function.
|
||||||
|
@ -226,16 +239,21 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* The type of filmstrip to be displayed.
|
* The type of filmstrip to be displayed.
|
||||||
*/
|
*/
|
||||||
filmstripType: string,
|
filmstripType: string
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Invoked to obtain translated strings.
|
|
||||||
*/
|
|
||||||
t: Function
|
|
||||||
};
|
|
||||||
|
|
||||||
type State = {
|
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.
|
* Whether or not the mouse is pressed.
|
||||||
*/
|
*/
|
||||||
|
@ -244,17 +262,7 @@ type State = {
|
||||||
/**
|
/**
|
||||||
* Initial mouse position on drag handle mouse down.
|
* Initial mouse position on drag handle mouse down.
|
||||||
*/
|
*/
|
||||||
mousePosition: ?number,
|
mousePosition?: number|null
|
||||||
|
|
||||||
/**
|
|
||||||
* Initial filmstrip width on drag handle mouse down.
|
|
||||||
*/
|
|
||||||
dragFilmstripWidth: ?number,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initial top panel height on drag handle mouse down.
|
|
||||||
*/
|
|
||||||
dragFilmstripHeight: ?number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -317,6 +325,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
'keyboardShortcuts.toggleFilmstrip'
|
'keyboardShortcuts.toggleFilmstrip'
|
||||||
);
|
);
|
||||||
document.addEventListener('mouseup', this._onDragMouseUp);
|
document.addEventListener('mouseup', this._onDragMouseUp);
|
||||||
|
// @ts-ignore
|
||||||
document.addEventListener('mousemove', this._throttledResize);
|
document.addEventListener('mousemove', this._throttledResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,6 +337,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
APP.keyboardshortcut.unregisterShortcut('F');
|
APP.keyboardshortcut.unregisterShortcut('F');
|
||||||
document.removeEventListener('mouseup', this._onDragMouseUp);
|
document.removeEventListener('mouseup', this._onDragMouseUp);
|
||||||
|
// @ts-ignore
|
||||||
document.removeEventListener('mousemove', this._throttledResize);
|
document.removeEventListener('mousemove', this._throttledResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +348,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const filmstripStyle = { };
|
const filmstripStyle: any = { };
|
||||||
const {
|
const {
|
||||||
_currentLayout,
|
_currentLayout,
|
||||||
_disableSelfView,
|
_disableSelfView,
|
||||||
|
@ -466,15 +476,13 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDragHandleMouseDown: (MouseEvent) => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles mouse down on the drag handle.
|
* Handles mouse down on the drag handle.
|
||||||
*
|
*
|
||||||
* @param {MouseEvent} e - The mouse down event.
|
* @param {MouseEvent} e - The mouse down event.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onDragHandleMouseDown(e) {
|
_onDragHandleMouseDown(e: React.MouseEvent) {
|
||||||
const { _topPanelFilmstrip, _topPanelHeight, _verticalFilmstripWidth } = this.props;
|
const { _topPanelFilmstrip, _topPanelHeight, _verticalFilmstripWidth } = this.props;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -486,8 +494,6 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
this.props.dispatch(setUserIsResizing(true));
|
this.props.dispatch(setUserIsResizing(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDragMouseUp: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drag handle mouse up handler.
|
* Drag handle mouse up handler.
|
||||||
*
|
*
|
||||||
|
@ -502,15 +508,13 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onFilmstripResize: (MouseEvent) => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles drag handle mouse move.
|
* Handles drag handle mouse move.
|
||||||
*
|
*
|
||||||
* @param {MouseEvent} e - The mousemove event.
|
* @param {MouseEvent} e - The mousemove event.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onFilmstripResize(e) {
|
_onFilmstripResize(e: React.MouseEvent) {
|
||||||
if (this.state.isMouseDown) {
|
if (this.state.isMouseDown) {
|
||||||
const {
|
const {
|
||||||
dispatch,
|
dispatch,
|
||||||
|
@ -523,9 +527,9 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
const { dragFilmstripWidth, dragFilmstripHeight, mousePosition } = this.state;
|
const { dragFilmstripWidth, dragFilmstripHeight, mousePosition } = this.state;
|
||||||
|
|
||||||
if (_topPanelFilmstrip) {
|
if (_topPanelFilmstrip) {
|
||||||
const diff = e.clientY - mousePosition;
|
const diff = e.clientY - (mousePosition ?? 0);
|
||||||
const height = Math.max(
|
const height = Math.max(
|
||||||
Math.min(dragFilmstripHeight + diff, _maxTopPanelHeight),
|
Math.min((dragFilmstripHeight ?? 0) + diff, _maxTopPanelHeight),
|
||||||
TOP_FILMSTRIP_HEIGHT
|
TOP_FILMSTRIP_HEIGHT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -533,9 +537,9 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
dispatch(setUserFilmstripHeight(height));
|
dispatch(setUserFilmstripHeight(height));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const diff = mousePosition - e.clientX;
|
const diff = (mousePosition ?? 0) - e.clientX;
|
||||||
const width = Math.max(
|
const width = Math.max(
|
||||||
Math.min(dragFilmstripWidth + diff, _maxFilmstripWidth),
|
Math.min((dragFilmstripWidth ?? 0) + diff, _maxFilmstripWidth),
|
||||||
DEFAULT_FILMSTRIP_WIDTH
|
DEFAULT_FILMSTRIP_WIDTH
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -553,7 +557,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
* @param {number} stopIndex - The stop index.
|
* @param {number} stopIndex - The stop index.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
_calculateIndices(startIndex, stopIndex) {
|
_calculateIndices(startIndex: number, stopIndex: number) {
|
||||||
const { _currentLayout, _iAmRecorder, _thumbnailsReordered, _disableSelfView } = this.props;
|
const { _currentLayout, _iAmRecorder, _thumbnailsReordered, _disableSelfView } = this.props;
|
||||||
let start = startIndex;
|
let start = startIndex;
|
||||||
let stop = stopIndex;
|
let stop = stopIndex;
|
||||||
|
@ -573,8 +577,6 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_onTabIn: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle the toolbar visibility when tabbing into it.
|
* 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.
|
* The key to be used for every ThumbnailWrapper element in stage view.
|
||||||
*
|
*
|
||||||
* @param {number} index - The index of the ThumbnailWrapper instance.
|
* @param {number} index - The index of the ThumbnailWrapper instance.
|
||||||
* @returns {string} - The key.
|
* @returns {string} - The key.
|
||||||
*/
|
*/
|
||||||
_listItemKey(index) {
|
_listItemKey(index: number) {
|
||||||
const { _remoteParticipants, _remoteParticipantsLength } = this.props;
|
const { _remoteParticipants, _remoteParticipantsLength } = this.props;
|
||||||
|
|
||||||
if (typeof index !== 'number' || _remoteParticipantsLength <= index) {
|
if (typeof index !== 'number' || _remoteParticipantsLength <= index) {
|
||||||
|
@ -604,15 +604,13 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
return _remoteParticipants[index];
|
return _remoteParticipants[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
_gridItemKey: Object => string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key to be used for every ThumbnailWrapper element in tile views.
|
* The key to be used for every ThumbnailWrapper element in tile views.
|
||||||
*
|
*
|
||||||
* @param {Object} data - An object with the indexes identifying the ThumbnailWrapper instance.
|
* @param {Object} data - An object with the indexes identifying the ThumbnailWrapper instance.
|
||||||
* @returns {string} - The key.
|
* @returns {string} - The key.
|
||||||
*/
|
*/
|
||||||
_gridItemKey({ columnIndex, rowIndex }) {
|
_gridItemKey({ columnIndex, rowIndex }: {columnIndex: number, rowIndex: number}) {
|
||||||
const {
|
const {
|
||||||
_disableSelfView,
|
_disableSelfView,
|
||||||
_columns,
|
_columns,
|
||||||
|
@ -638,23 +636,20 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
return _remoteParticipants[remoteIndex];
|
return _remoteParticipants[remoteIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
_onListItemsRendered: Object => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles items rendered changes in stage view.
|
* Handles items rendered changes in stage view.
|
||||||
*
|
*
|
||||||
* @param {Object} data - Information about the rendered items.
|
* @param {Object} data - Information about the rendered items.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onListItemsRendered({ visibleStartIndex, visibleStopIndex }) {
|
_onListItemsRendered({ visibleStartIndex, visibleStopIndex }
|
||||||
|
: { visibleStartIndex: number, visibleStopIndex: number }) {
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
const { startIndex, stopIndex } = this._calculateIndices(visibleStartIndex, visibleStopIndex);
|
const { startIndex, stopIndex } = this._calculateIndices(visibleStartIndex, visibleStopIndex);
|
||||||
|
|
||||||
dispatch(setVisibleRemoteParticipants(startIndex, stopIndex));
|
dispatch(setVisibleRemoteParticipants(startIndex, stopIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
_onGridItemsRendered: Object => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles items rendered changes in tile view.
|
* Handles items rendered changes in tile view.
|
||||||
*
|
*
|
||||||
|
@ -666,6 +661,11 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
visibleColumnStopIndex,
|
visibleColumnStopIndex,
|
||||||
visibleRowStartIndex,
|
visibleRowStartIndex,
|
||||||
visibleRowStopIndex
|
visibleRowStopIndex
|
||||||
|
}: {
|
||||||
|
visibleColumnStartIndex: number,
|
||||||
|
visibleColumnStopIndex: number,
|
||||||
|
visibleRowStartIndex: number,
|
||||||
|
visibleRowStopIndex: number
|
||||||
}) {
|
}) {
|
||||||
const { _columns, dispatch } = this.props;
|
const { _columns, dispatch } = this.props;
|
||||||
const start = (visibleRowStartIndex * _columns) + visibleColumnStartIndex;
|
const start = (visibleRowStartIndex * _columns) + visibleColumnStartIndex;
|
||||||
|
@ -713,6 +713,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
initialScrollLeft = { 0 }
|
initialScrollLeft = { 0 }
|
||||||
initialScrollTop = { 0 }
|
initialScrollTop = { 0 }
|
||||||
itemData = {{ filmstripType }}
|
itemData = {{ filmstripType }}
|
||||||
|
// @ts-ignore
|
||||||
itemKey = { this._gridItemKey }
|
itemKey = { this._gridItemKey }
|
||||||
onItemsRendered = { this._onGridItemsRendered }
|
onItemsRendered = { this._onGridItemsRendered }
|
||||||
overscanRowCount = { 1 }
|
overscanRowCount = { 1 }
|
||||||
|
@ -727,7 +728,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const props = {
|
const props: any = {
|
||||||
itemCount: _remoteParticipantsLength,
|
itemCount: _remoteParticipantsLength,
|
||||||
className: `filmstrip__videos remote-videos ${_resizableFilmstrip ? '' : 'height-transition'}`,
|
className: `filmstrip__videos remote-videos ${_resizableFilmstrip ? '' : 'height-transition'}`,
|
||||||
height: _filmstripHeight,
|
height: _filmstripHeight,
|
||||||
|
@ -746,8 +747,6 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
const isNotOverflowing = !_hasScroll;
|
const isNotOverflowing = !_hasScroll;
|
||||||
|
|
||||||
props.itemSize = itemSize;
|
props.itemSize = itemSize;
|
||||||
|
|
||||||
// $FlowFixMe
|
|
||||||
props.layout = 'horizontal';
|
props.layout = 'horizontal';
|
||||||
if (isNotOverflowing) {
|
if (isNotOverflowing) {
|
||||||
props.className += ' is-not-overflowing';
|
props.className += ' is-not-overflowing';
|
||||||
|
@ -787,8 +786,6 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
: dispatch(setFilmstripVisible(!_mainFilmstripVisible));
|
: dispatch(setFilmstripVisible(!_mainFilmstripVisible));
|
||||||
}
|
}
|
||||||
|
|
||||||
_onShortcutToggleFilmstrip: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an analytics keyboard shortcut event and dispatches an action for
|
* Creates an analytics keyboard shortcut event and dispatches an action for
|
||||||
* toggling filmstrip visibility.
|
* toggling filmstrip visibility.
|
||||||
|
@ -806,8 +803,6 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
this._doToggleFilmstrip();
|
this._doToggleFilmstrip();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onToolbarToggleFilmstrip: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an analytics toolbar event and dispatches an action for opening
|
* Creates an analytics toolbar event and dispatches an action for opening
|
||||||
* the speaker stats modal.
|
* the speaker stats modal.
|
||||||
|
@ -825,8 +820,6 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
this._doToggleFilmstrip();
|
this._doToggleFilmstrip();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onToggleButtonTouch: (SyntheticEvent<HTMLButtonElement>) => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for touch start event of the 'toggle button'.
|
* 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.
|
* @param {Object} e - The synthetic event.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onToggleButtonTouch(e: SyntheticEvent<HTMLButtonElement>) {
|
_onToggleButtonTouch(e: React.TouchEvent) {
|
||||||
// Don't propagate the touchStart event so the toolbar doesn't get toggled.
|
// Don't propagate the touchStart event so the toolbar doesn't get toggled.
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this._onToolbarToggleFilmstrip();
|
this._onToolbarToggleFilmstrip();
|
||||||
|
@ -893,7 +886,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {Props}
|
* @returns {Props}
|
||||||
*/
|
*/
|
||||||
function _mapStateToProps(state, ownProps) {
|
function _mapStateToProps(state: any, ownProps: any) {
|
||||||
const { _hasScroll = false, filmstripType, _topPanelFilmstrip, _remoteParticipants } = ownProps;
|
const { _hasScroll = false, filmstripType, _topPanelFilmstrip, _remoteParticipants } = ownProps;
|
||||||
const toolbarButtons = getToolbarButtons(state);
|
const toolbarButtons = getToolbarButtons(state);
|
||||||
const { testing = {}, iAmRecorder } = state['features/base/config'];
|
const { testing = {}, iAmRecorder } = state['features/base/config'];
|
|
@ -1,12 +1,13 @@
|
||||||
/* @flow */
|
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/styles';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
import { IconPinParticipant } from '../../../base/icons';
|
import { IState } from '../../../app/types';
|
||||||
import { getParticipantById } from '../../../base/participants';
|
import { IconPinParticipant } from '../../../base/icons/svg/index';
|
||||||
import { BaseIndicator } from '../../../base/react';
|
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';
|
import { getPinnedActiveParticipants, isStageFilmstripAvailable } from '../../functions.web';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,8 +56,10 @@ const PinnedIndicator = ({
|
||||||
tooltipPosition
|
tooltipPosition
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const stageFilmstrip = useSelector(isStageFilmstripAvailable);
|
const stageFilmstrip = useSelector(isStageFilmstripAvailable);
|
||||||
const pinned = useSelector(state => getParticipantById(state, participantId))?.pinned;
|
const pinned = useSelector((state: IState) => getParticipantById(state, participantId))?.pinned;
|
||||||
const isPinned = useSelector(getPinnedActiveParticipants).find(p => p.participantId === participantId);
|
const activePinnedParticipants: Array<{participantId: string; pinned: boolean}>
|
||||||
|
= useSelector(getPinnedActiveParticipants);
|
||||||
|
const isPinned = activePinnedParticipants.find(p => p.participantId === participantId);
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
|
|
||||||
if ((stageFilmstrip && !isPinned) || (!stageFilmstrip && !pinned)) {
|
if ((stageFilmstrip && !isPinned) || (!stageFilmstrip && !pinned)) {
|
|
@ -1,13 +1,13 @@
|
||||||
/* @flow */
|
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/styles';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
import { IconRaisedHand } from '../../../base/icons';
|
import { IState } from '../../../app/types';
|
||||||
import { getParticipantById, hasRaisedHand } from '../../../base/participants';
|
import { IconRaisedHand } from '../../../base/icons/svg/index';
|
||||||
import { BaseIndicator } from '../../../base/react';
|
import { getParticipantById, hasRaisedHand } from '../../../base/participants/functions';
|
||||||
import BaseTheme from '../../../base/ui/components/BaseTheme';
|
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}.
|
* The type of the React {@code Component} props of {@link RaisedHandIndicator}.
|
||||||
|
@ -31,7 +31,7 @@ type Props = {
|
||||||
tooltipPosition: string
|
tooltipPosition: string
|
||||||
};
|
};
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => {
|
const useStyles = makeStyles((theme: any) => {
|
||||||
return {
|
return {
|
||||||
raisedHandIndicator: {
|
raisedHandIndicator: {
|
||||||
backgroundColor: theme.palette.warning02,
|
backgroundColor: theme.palette.warning02,
|
||||||
|
@ -54,8 +54,9 @@ const RaisedHandIndicator = ({
|
||||||
participantId,
|
participantId,
|
||||||
tooltipPosition
|
tooltipPosition
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const _raisedHand = hasRaisedHand(useSelector(state =>
|
const participant: Participant|undefined = useSelector((state: IState) =>
|
||||||
getParticipantById(state, participantId)));
|
getParticipantById(state, participantId));
|
||||||
|
const _raisedHand = hasRaisedHand(participant);
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
|
|
||||||
if (!_raisedHand) {
|
if (!_raisedHand) {
|
|
@ -67,7 +67,7 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* Closes a drawer if open.
|
* Closes a drawer if open.
|
||||||
*/
|
*/
|
||||||
closeDrawer?: Function,
|
closeDrawer?: () => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The participant for which the drawer is open.
|
* The participant for which the drawer is open.
|
||||||
|
@ -91,17 +91,17 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* Callback for the mouse entering the component.
|
* Callback for the mouse entering the component.
|
||||||
*/
|
*/
|
||||||
onEnter?: Function,
|
onEnter?: (e?: React.MouseEvent) => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for the mouse leaving the component.
|
* Callback for the mouse leaving the component.
|
||||||
*/
|
*/
|
||||||
onLeave?: Function,
|
onLeave?: (e?: React.MouseEvent) => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for making a selection in the menu.
|
* Callback for making a selection in the menu.
|
||||||
*/
|
*/
|
||||||
onSelect: Function,
|
onSelect: (value?: boolean | React.MouseEvent) => void,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Participant reference.
|
* Participant reference.
|
||||||
|
@ -157,7 +157,7 @@ const ParticipantContextMenu = ({
|
||||||
const _isVideoForceMuted = useSelector(state =>
|
const _isVideoForceMuted = useSelector(state =>
|
||||||
isForceMuted(participant, MEDIA_TYPE.VIDEO, state));
|
isForceMuted(participant, MEDIA_TYPE.VIDEO, state));
|
||||||
const _isAudioMuted = useSelector(state => isParticipantAudioMuted(participant, state));
|
const _isAudioMuted = useSelector(state => isParticipantAudioMuted(participant, state));
|
||||||
const _overflowDrawer = useSelector(showOverflowDrawer);
|
const _overflowDrawer: boolean = useSelector(showOverflowDrawer);
|
||||||
const { remoteVideoMenu = {}, disableRemoteMute, startSilent }
|
const { remoteVideoMenu = {}, disableRemoteMute, startSilent }
|
||||||
= useSelector((state: IState) => state['features/base/config']);
|
= useSelector((state: IState) => state['features/base/config']);
|
||||||
const { disableKick, disableGrantModerator, disablePrivateChat } = remoteVideoMenu;
|
const { disableKick, disableGrantModerator, disablePrivateChat } = remoteVideoMenu;
|
||||||
|
@ -315,7 +315,7 @@ const ParticipantContextMenu = ({
|
||||||
entity = { participant }
|
entity = { participant }
|
||||||
hidden = { thumbnailMenu ? false : undefined }
|
hidden = { thumbnailMenu ? false : undefined }
|
||||||
inDrawer = { thumbnailMenu && _overflowDrawer }
|
inDrawer = { thumbnailMenu && _overflowDrawer }
|
||||||
isDrawerOpen = { drawerParticipant }
|
isDrawerOpen = { Boolean(drawerParticipant) }
|
||||||
offsetTarget = { offsetTarget }
|
offsetTarget = { offsetTarget }
|
||||||
onClick = { onSelect }
|
onClick = { onSelect }
|
||||||
onDrawerClose = { thumbnailMenu ? onSelect : closeDrawer }
|
onDrawerClose = { thumbnailMenu ? onSelect : closeDrawer }
|
||||||
|
|
Loading…
Reference in New Issue