ref: Convert material-ui files to TS (#12013)
Convert files that use material-ui to TS (needed for material-ui upgrade)
This commit is contained in:
parent
94dc6309de
commit
dfb2a07cfa
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
export type Props = {
|
||||
|
@ -7,7 +5,7 @@ export type Props = {
|
|||
/**
|
||||
* An SVG icon to be rendered as the content of the label.
|
||||
*/
|
||||
icon: Component<any>,
|
||||
icon: Function,
|
||||
|
||||
/**
|
||||
* String or component that will be rendered as the label itself.
|
||||
|
@ -18,6 +16,6 @@ export type Props = {
|
|||
/**
|
||||
* Abstract class for the {@code Label} component.
|
||||
*/
|
||||
export default class Label<P: Props, S: *>
|
||||
export default class Label<P extends Props, S>
|
||||
extends Component<P, S> {
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './native';
|
|
@ -0,0 +1 @@
|
|||
export * from './web';
|
|
@ -1,2 +1 @@
|
|||
export { default as Label } from './Label';
|
||||
export { default as ExpandedLabel } from './ExpandedLabel';
|
||||
export * from './_';
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
import React from 'react';
|
||||
import { Animated, Text } from 'react-native';
|
||||
|
||||
import Icon from '../../icons/components/Icon';
|
||||
import { combineStyles, type StyleType } from '../../styles';
|
||||
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { combineStyles, type StyleType } from '../../../styles';
|
||||
import AbstractLabel, {
|
||||
type Props as AbstractProps
|
||||
} from './AbstractLabel';
|
||||
} from '../AbstractLabel';
|
||||
|
||||
import styles from './styles';
|
||||
|
||||
/**
|
|
@ -0,0 +1,2 @@
|
|||
export { default as Label } from './Label';
|
||||
export { default as ExpandedLabel } from './ExpandedLabel';
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import { ColorPalette } from '../../styles';
|
||||
import BaseTheme from '../../ui/components/BaseTheme';
|
||||
import { ColorPalette } from '../../../styles';
|
||||
import BaseTheme from '../../../ui/components/BaseTheme';
|
||||
|
||||
/**
|
||||
* The default color of the {@code Label} and {@code ExpandedLabel}.
|
|
@ -1,48 +1,46 @@
|
|||
// @flow
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
|
||||
import Icon from '../../icons/components/Icon';
|
||||
import { withPixelLineHeight } from '../../styles/functions.web';
|
||||
import { COLORS } from '../constants';
|
||||
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { COLORS } from '../../constants';
|
||||
import AbstractLabel, {
|
||||
type Props as AbstractProps
|
||||
} from './AbstractLabel';
|
||||
} from '../AbstractLabel';
|
||||
|
||||
type Props = AbstractProps & {
|
||||
|
||||
/**
|
||||
* An object containing the CSS classes.
|
||||
*/
|
||||
classes: Object,
|
||||
|
||||
/**
|
||||
* Own CSS class name.
|
||||
*/
|
||||
className: string,
|
||||
|
||||
/**
|
||||
* An object containing the CSS classes.
|
||||
*/
|
||||
classes: any,
|
||||
|
||||
/**
|
||||
* The color of the label.
|
||||
*/
|
||||
color: string,
|
||||
|
||||
|
||||
/**
|
||||
* HTML ID attribute to add to the root of {@code Label}.
|
||||
*/
|
||||
id: string,
|
||||
|
||||
/**
|
||||
* Color for the icon.
|
||||
*/
|
||||
iconColor?: string,
|
||||
|
||||
/**
|
||||
* HTML ID attribute to add to the root of {@code Label}.
|
||||
*/
|
||||
id: string,
|
||||
|
||||
/**
|
||||
* Click handler if any.
|
||||
*/
|
||||
onClick?: Function,
|
||||
onClick?: (e?: React.MouseEvent) => void,
|
||||
|
||||
};
|
||||
|
||||
|
@ -53,7 +51,7 @@ type Props = AbstractProps & {
|
|||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
const styles = theme => {
|
||||
const styles = (theme: any) => {
|
||||
return {
|
||||
label: {
|
||||
...withPixelLineHeight(theme.typography.labelRegular),
|
||||
|
@ -96,7 +94,7 @@ const styles = theme => {
|
|||
*
|
||||
* @augments Component
|
||||
*/
|
||||
class Label extends AbstractLabel<Props, *> {
|
||||
class Label extends AbstractLabel<Props, any> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
|
@ -0,0 +1,2 @@
|
|||
export { default as Label } from './Label';
|
||||
export { default as ExpandedLabel } from './ExpandedLabel';
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
export const COLORS = {
|
||||
white: 'white',
|
||||
green: 'green',
|
|
@ -581,7 +581,7 @@ export function participantKicked(kicker: any, kicked: any) {
|
|||
* }
|
||||
* }}
|
||||
*/
|
||||
export function pinParticipant(id: string) {
|
||||
export function pinParticipant(id: string|null) {
|
||||
return {
|
||||
type: PIN_PARTICIPANT,
|
||||
participant: {
|
||||
|
|
|
@ -224,7 +224,7 @@ export function getNormalizedDisplayName(name: string) {
|
|||
* @returns {(Participant|undefined)}
|
||||
*/
|
||||
export function getParticipantById(
|
||||
stateful: IStore | Function, id: string): Participant|undefined {
|
||||
stateful: IStore | Function | IState, id: string): Participant|undefined {
|
||||
const state = toState(stateful)['features/base/participants'];
|
||||
const { local, localScreenShare, remote } = state;
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@ const useStyles = makeStyles((theme: Theme) => {
|
|||
};
|
||||
});
|
||||
|
||||
const Button = ({
|
||||
const Button = React.forwardRef<any, any>(({
|
||||
accessibilityLabel,
|
||||
className,
|
||||
disabled,
|
||||
|
@ -191,7 +191,7 @@ const Button = ({
|
|||
size = 'medium',
|
||||
testId,
|
||||
type = BUTTON_TYPES.PRIMARY
|
||||
}: IButtonProps) => {
|
||||
}: IButtonProps, ref) => {
|
||||
const styles = useStyles();
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
@ -206,6 +206,7 @@ const Button = ({
|
|||
disabled = { disabled }
|
||||
{ ...(id ? { id } : {}) }
|
||||
onClick = { onClick }
|
||||
ref = { ref }
|
||||
title = { accessibilityLabel }
|
||||
type = { isSubmit ? 'submit' : 'button' }>
|
||||
{icon && <Icon
|
||||
|
@ -216,6 +217,6 @@ const Button = ({
|
|||
</span>}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default Button;
|
||||
|
|
|
@ -1,24 +1,29 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { withStyles } from '@material-ui/styles';
|
||||
import clsx from 'clsx';
|
||||
import debounce from 'lodash/debounce';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
// @ts-ignore
|
||||
import { createScreenSharingIssueEvent, sendAnalytics } from '../../../analytics';
|
||||
// @ts-ignore
|
||||
import { Avatar } from '../../../base/avatar';
|
||||
// @ts-ignore
|
||||
import { getMultipleVideoSupportFeatureFlag, getSourceNameSignalingFeatureFlag } from '../../../base/config';
|
||||
import { isMobileBrowser } from '../../../base/environment/utils';
|
||||
import { JitsiTrackEvents } from '../../../base/lib-jitsi-meet';
|
||||
// @ts-ignore
|
||||
import { MEDIA_TYPE, VideoTrack } from '../../../base/media';
|
||||
import { pinParticipant } from '../../../base/participants/actions';
|
||||
import {
|
||||
getLocalParticipant,
|
||||
getParticipantByIdOrUndefined,
|
||||
hasRaisedHand,
|
||||
pinParticipant
|
||||
} from '../../../base/participants';
|
||||
import { connect } from '../../../base/redux';
|
||||
hasRaisedHand
|
||||
} from '../../../base/participants/functions';
|
||||
import { Participant } from '../../../base/participants/reducer';
|
||||
import { connect } from '../../../base/redux/functions';
|
||||
import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui/constants';
|
||||
// @ts-ignore
|
||||
import { isTestModeEnabled } from '../../../base/testing';
|
||||
import {
|
||||
getLocalAudioTrack,
|
||||
|
@ -27,12 +32,19 @@ import {
|
|||
getVirtualScreenshareParticipantTrack,
|
||||
updateLastTrackVideoMediaEvent,
|
||||
trackStreamingStatusChanged
|
||||
// @ts-ignore
|
||||
} from '../../../base/tracks';
|
||||
// @ts-ignore
|
||||
import { getVideoObjectPosition } from '../../../face-landmarks/functions';
|
||||
// @ts-ignore
|
||||
import { hideGif, showGif } from '../../../gifs/actions';
|
||||
// @ts-ignore
|
||||
import { getGifDisplayMode, getGifForParticipant } from '../../../gifs/functions';
|
||||
// @ts-ignore
|
||||
import { PresenceLabel } from '../../../presence-status';
|
||||
// @ts-ignore
|
||||
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
|
||||
// @ts-ignore
|
||||
import { togglePinStageParticipant } from '../../actions';
|
||||
import {
|
||||
DISPLAY_MODE_TO_CLASS_NAME,
|
||||
|
@ -50,20 +62,22 @@ import {
|
|||
isVideoPlayable,
|
||||
isStageFilmstripAvailable,
|
||||
showGridInVerticalView
|
||||
// @ts-ignore
|
||||
} from '../../functions';
|
||||
|
||||
// @ts-ignore
|
||||
import ThumbnailAudioIndicator from './ThumbnailAudioIndicator';
|
||||
import ThumbnailBottomIndicators from './ThumbnailBottomIndicators';
|
||||
import ThumbnailTopIndicators from './ThumbnailTopIndicators';
|
||||
// @ts-ignore
|
||||
import VirtualScreenshareParticipant from './VirtualScreenshareParticipant';
|
||||
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
declare let interfaceConfig: any;
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link Thumbnail}.
|
||||
*/
|
||||
export type State = {|
|
||||
export type State = {
|
||||
|
||||
/**
|
||||
* Indicates that the canplay event has been received.
|
||||
|
@ -75,26 +89,26 @@ export type State = {|
|
|||
*/
|
||||
displayMode: number,
|
||||
|
||||
/**
|
||||
* Whether popover is visible or not.
|
||||
*/
|
||||
popoverVisible: boolean,
|
||||
|
||||
/**
|
||||
* Indicates whether the thumbnail is hovered or not.
|
||||
*/
|
||||
isHovered: boolean
|
||||
|};
|
||||
isHovered: boolean,
|
||||
|
||||
/**
|
||||
* Whether popover is visible or not.
|
||||
*/
|
||||
popoverVisible: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Thumbnail}.
|
||||
*/
|
||||
export type Props = {|
|
||||
export type Props = {
|
||||
|
||||
/**
|
||||
* The audio track related to the participant.
|
||||
*/
|
||||
_audioTrack: ?Object,
|
||||
_audioTrack?: Object,
|
||||
|
||||
/**
|
||||
* Indicates whether the local video flip feature is disabled or not.
|
||||
|
@ -109,7 +123,7 @@ export type Props = {|
|
|||
/**
|
||||
* URL of GIF sent by this participant, null if there's none.
|
||||
*/
|
||||
_gifSrc ?: string,
|
||||
_gifSrc?: string,
|
||||
|
||||
/**
|
||||
* The height of the Thumbnail.
|
||||
|
@ -122,11 +136,6 @@ export type Props = {|
|
|||
*/
|
||||
_isActiveParticipant: boolean,
|
||||
|
||||
/**
|
||||
* Indicates whether the thumbnail should be hidden or not.
|
||||
*/
|
||||
_isHidden: boolean,
|
||||
|
||||
/**
|
||||
* Indicates whether audio only mode is enabled.
|
||||
*/
|
||||
|
@ -142,6 +151,11 @@ export type Props = {|
|
|||
*/
|
||||
_isDominantSpeakerDisabled: boolean,
|
||||
|
||||
/**
|
||||
* Indicates whether the thumbnail should be hidden or not.
|
||||
*/
|
||||
_isHidden: boolean,
|
||||
|
||||
/**
|
||||
* Whether we are currently running in a mobile browser.
|
||||
*/
|
||||
|
@ -181,7 +195,7 @@ export type Props = {|
|
|||
/**
|
||||
* An object with information about the participant related to the thumbnail.
|
||||
*/
|
||||
_participant: Object,
|
||||
_participant: Participant,
|
||||
|
||||
/**
|
||||
* Whether or not the participant has the hand raised.
|
||||
|
@ -218,7 +232,7 @@ export type Props = {|
|
|||
/**
|
||||
* The video track that will be displayed in the thumbnail.
|
||||
*/
|
||||
_videoTrack: ?Object,
|
||||
_videoTrack?: any,
|
||||
|
||||
/**
|
||||
* The width of the thumbnail.
|
||||
|
@ -228,7 +242,7 @@ export type Props = {|
|
|||
/**
|
||||
* An object containing CSS classes.
|
||||
*/
|
||||
classes: Object,
|
||||
classes: any,
|
||||
|
||||
/**
|
||||
* The redux dispatch function.
|
||||
|
@ -248,21 +262,21 @@ export type Props = {|
|
|||
/**
|
||||
* The ID of the participant related to the thumbnail.
|
||||
*/
|
||||
participantID: ?string,
|
||||
participantID?: string,
|
||||
|
||||
/**
|
||||
* Styles that will be set to the Thumbnail's main span element.
|
||||
*/
|
||||
style?: ?Object,
|
||||
style?: any,
|
||||
|
||||
/**
|
||||
/**
|
||||
* The width of the thumbnail. Used for expanding the width of the thumbnails on last row in case
|
||||
* there is empty space.
|
||||
*/
|
||||
width?: number
|
||||
|};
|
||||
};
|
||||
|
||||
const defaultStyles = theme => {
|
||||
const defaultStyles = (theme: any) => {
|
||||
return {
|
||||
indicatorsContainer: {
|
||||
position: 'absolute',
|
||||
|
@ -372,13 +386,13 @@ class Thumbnail extends Component<Props, State> {
|
|||
/**
|
||||
* The long touch setTimeout handler.
|
||||
*/
|
||||
timeoutHandle: Object;
|
||||
timeoutHandle?: number;
|
||||
|
||||
/**
|
||||
* Timeout used to detect double tapping.
|
||||
* It is active while user has tapped once.
|
||||
*/
|
||||
_firstTap: ?TimeoutID;
|
||||
_firstTap?: number;
|
||||
|
||||
/**
|
||||
* Initializes a new Thumbnail instance.
|
||||
|
@ -400,7 +414,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
...state,
|
||||
displayMode: computeDisplayModeFromInput(getDisplayModeInput(props, state))
|
||||
};
|
||||
this.timeoutHandle = null;
|
||||
this.timeoutHandle = undefined;
|
||||
|
||||
this._clearDoubleClickTimeout = this._clearDoubleClickTimeout.bind(this);
|
||||
this._onCanPlay = this._onCanPlay.bind(this);
|
||||
|
@ -505,7 +519,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
* @param {JitsiTrackStreamingStatus} streamingStatus - The updated track streaming status.
|
||||
* @returns {void}
|
||||
*/
|
||||
handleTrackStreamingStatusChanged(jitsiTrack, streamingStatus) {
|
||||
handleTrackStreamingStatusChanged(jitsiTrack: any, streamingStatus: any) {
|
||||
this.props.dispatch(trackStreamingStatusChanged(jitsiTrack, streamingStatus));
|
||||
}
|
||||
|
||||
|
@ -526,7 +540,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
* @param {Object} input - The input used to compute the thumbnail display mode.
|
||||
* @returns {void}
|
||||
*/
|
||||
_maybeSendScreenSharingIssueEvents(input) {
|
||||
_maybeSendScreenSharingIssueEvents(input: any) {
|
||||
const {
|
||||
_isAudioOnly,
|
||||
_isScreenSharing,
|
||||
|
@ -576,8 +590,6 @@ class Thumbnail extends Component<Props, State> {
|
|||
return null;
|
||||
}
|
||||
|
||||
_clearDoubleClickTimeout: () => void;
|
||||
|
||||
/**
|
||||
* Clears the first click timeout.
|
||||
*
|
||||
|
@ -588,8 +600,6 @@ class Thumbnail extends Component<Props, State> {
|
|||
this._firstTap = undefined;
|
||||
}
|
||||
|
||||
_showPopover: () => void;
|
||||
|
||||
/**
|
||||
* Shows popover.
|
||||
*
|
||||
|
@ -602,8 +612,6 @@ class Thumbnail extends Component<Props, State> {
|
|||
});
|
||||
}
|
||||
|
||||
_hidePopover: () => void;
|
||||
|
||||
/**
|
||||
* Hides popover.
|
||||
*
|
||||
|
@ -628,7 +636,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
*
|
||||
* @returns {Object} - The styles for the thumbnail.
|
||||
*/
|
||||
_getStyles(): Object {
|
||||
_getStyles(): any {
|
||||
const { canPlayEventReceived } = this.state;
|
||||
const {
|
||||
_disableTileEnlargement,
|
||||
|
@ -652,7 +660,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
|
||||
let styles: {
|
||||
avatar: Object,
|
||||
thumbnail: Object,
|
||||
thumbnail: any,
|
||||
video: Object
|
||||
} = {
|
||||
thumbnail: {},
|
||||
|
@ -667,7 +675,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
left += horizontalOffset;
|
||||
}
|
||||
|
||||
let videoStyles = null;
|
||||
let videoStyles: any = null;
|
||||
const doNotStretchVideo = (isPortraitVideo && isTileType)
|
||||
|| _disableTileEnlargement
|
||||
|| _isScreenSharing;
|
||||
|
@ -709,8 +717,6 @@ class Thumbnail extends Component<Props, State> {
|
|||
return styles;
|
||||
}
|
||||
|
||||
_onClick: () => void;
|
||||
|
||||
/**
|
||||
* On click handler.
|
||||
*
|
||||
|
@ -727,8 +733,6 @@ class Thumbnail extends Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
_onMouseEnter: () => void;
|
||||
|
||||
/**
|
||||
* Mouse enter handler.
|
||||
*
|
||||
|
@ -752,8 +756,6 @@ class Thumbnail extends Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
_onMouseLeave: () => void;
|
||||
|
||||
/**
|
||||
* Mouse leave handler.
|
||||
*
|
||||
|
@ -763,15 +765,13 @@ class Thumbnail extends Component<Props, State> {
|
|||
this.setState({ isHovered: false });
|
||||
}
|
||||
|
||||
_onTouchStart: () => void;
|
||||
|
||||
/**
|
||||
* Handler for touch start.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onTouchStart() {
|
||||
this.timeoutHandle = setTimeout(this._showPopover, SHOW_TOOLBAR_CONTEXT_MENU_AFTER);
|
||||
this.timeoutHandle = window.setTimeout(this._showPopover, SHOW_TOOLBAR_CONTEXT_MENU_AFTER);
|
||||
|
||||
if (this._firstTap) {
|
||||
this._clearDoubleClickTimeout();
|
||||
|
@ -780,11 +780,9 @@ class Thumbnail extends Component<Props, State> {
|
|||
return;
|
||||
}
|
||||
|
||||
this._firstTap = setTimeout(this._clearDoubleClickTimeout, 300);
|
||||
this._firstTap = window.setTimeout(this._clearDoubleClickTimeout, 300);
|
||||
}
|
||||
|
||||
_onTouchEnd: () => void;
|
||||
|
||||
/**
|
||||
* Cancel showing popover context menu after x miliseconds if the no. Of miliseconds is not reached yet,
|
||||
* or just clears the timeout.
|
||||
|
@ -795,8 +793,6 @@ class Thumbnail extends Component<Props, State> {
|
|||
clearTimeout(this.timeoutHandle);
|
||||
}
|
||||
|
||||
_onTouchMove: () => void;
|
||||
|
||||
/**
|
||||
* Cancel showing Context menu after x miliseconds if the number of miliseconds is not reached
|
||||
* before a touch move(drag), or just clears the timeout.
|
||||
|
@ -845,7 +841,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
* @param {Object} styles - The styles that will be applied to the avatar.
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderAvatar(styles) {
|
||||
_renderAvatar(styles: Object) {
|
||||
const { _participant } = this.props;
|
||||
const { id } = _participant;
|
||||
|
||||
|
@ -892,8 +888,6 @@ class Thumbnail extends Component<Props, State> {
|
|||
return className;
|
||||
}
|
||||
|
||||
_onGifMouseEnter: () => void;
|
||||
|
||||
/**
|
||||
* Keep showing the GIF for the current participant.
|
||||
*
|
||||
|
@ -905,8 +899,6 @@ class Thumbnail extends Component<Props, State> {
|
|||
dispatch(showGif(id));
|
||||
}
|
||||
|
||||
_onGifMouseLeave: () => void;
|
||||
|
||||
/**
|
||||
* Keep showing the GIF for the current participant.
|
||||
*
|
||||
|
@ -935,15 +927,13 @@ class Thumbnail extends Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
_onCanPlay: Object => void;
|
||||
|
||||
/**
|
||||
* Canplay event listener.
|
||||
*
|
||||
* @param {SyntheticEvent} event - The event.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onCanPlay(event) {
|
||||
_onCanPlay(event: any) {
|
||||
this.setState({ canPlayEventReceived: true });
|
||||
|
||||
const {
|
||||
|
@ -956,15 +946,13 @@ class Thumbnail extends Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
_onTestingEvent: Object => void;
|
||||
|
||||
/**
|
||||
* Event handler for testing events.
|
||||
*
|
||||
* @param {SyntheticEvent} event - The event.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onTestingEvent(event) {
|
||||
_onTestingEvent(event: any) {
|
||||
const {
|
||||
_videoTrack,
|
||||
dispatch
|
||||
|
@ -1004,7 +992,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
= !_disableLocalVideoFlip && _videoTrack && !_isScreenSharing && _localFlipX ? 'flipVideoX' : '';
|
||||
const jitsiVideoTrack = _videoTrack?.jitsiTrack;
|
||||
const videoTrackId = jitsiVideoTrack && jitsiVideoTrack.getId();
|
||||
const videoEventListeners = {};
|
||||
const videoEventListeners: any = {};
|
||||
|
||||
if (local) {
|
||||
if (_isMobilePortrait) {
|
||||
|
@ -1168,7 +1156,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
* @private
|
||||
* @returns {Props}
|
||||
*/
|
||||
function _mapStateToProps(state, ownProps): Object {
|
||||
function _mapStateToProps(state: any, ownProps: any): Object {
|
||||
const { participantID, filmstripType = FILMSTRIP_TYPE.MAIN } = ownProps;
|
||||
|
||||
const participant = getParticipantByIdOrUndefined(state, participantID);
|
||||
|
@ -1188,7 +1176,7 @@ function _mapStateToProps(state, ownProps): Object {
|
|||
const _audioTrack = isLocal
|
||||
? getLocalAudioTrack(tracks) : getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.AUDIO, participantID);
|
||||
const _currentLayout = getCurrentLayout(state);
|
||||
let size = {};
|
||||
let size: any = {};
|
||||
let _isMobilePortrait = false;
|
||||
const {
|
||||
defaultLocalDisplayName,
|
||||
|
@ -1287,7 +1275,7 @@ function _mapStateToProps(state, ownProps): Object {
|
|||
_defaultLocalDisplayName: defaultLocalDisplayName,
|
||||
_disableLocalVideoFlip: Boolean(disableLocalVideoFlip),
|
||||
_disableTileEnlargement: Boolean(disableTileEnlargement),
|
||||
_isActiveParticipant: activeParticipants.find(pId => pId === participantId),
|
||||
_isActiveParticipant: activeParticipants.find((pId: string) => pId === participantId),
|
||||
_isHidden: isLocal && iAmRecorder && !iAmSipGateway,
|
||||
_isAudioOnly: Boolean(state['features/base/audio-only'].enabled),
|
||||
_isCurrentlyOnLargeVideo: state['features/large-video']?.participantId === id,
|
||||
|
@ -1313,4 +1301,5 @@ function _mapStateToProps(state, ownProps): Object {
|
|||
};
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export default connect(_mapStateToProps)(withStyles(defaultStyles)(Thumbnail));
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
@ -8,13 +7,16 @@ import {
|
|||
getMultipleVideoSupportFeatureFlag,
|
||||
isDisplayNameVisible,
|
||||
isNameReadOnly
|
||||
// @ts-ignore
|
||||
} from '../../../base/config/functions.any';
|
||||
// @ts-ignore
|
||||
import DisplayName from '../../../display-name/components/web/DisplayName';
|
||||
import { THUMBNAIL_TYPE } from '../../constants';
|
||||
|
||||
// @ts-ignore
|
||||
import StatusIndicators from './StatusIndicators';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
declare let interfaceConfig: any;
|
||||
|
||||
type Props = {
|
||||
|
||||
|
@ -41,7 +43,7 @@ type Props = {
|
|||
/**
|
||||
* Whether or not to show the status indicators.
|
||||
*/
|
||||
showStatusIndicators: string,
|
||||
showStatusIndicators?: boolean,
|
||||
|
||||
/**
|
||||
* The type of thumbnail.
|
|
@ -1,22 +1,28 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { IState } from '../../../app/types';
|
||||
// @ts-ignore
|
||||
import { getMultipleVideoSupportFeatureFlag } from '../../../base/config';
|
||||
import { isMobileBrowser } from '../../../base/environment/utils';
|
||||
// @ts-ignore
|
||||
import ConnectionIndicator from '../../../connection-indicator/components/web/ConnectionIndicator';
|
||||
import { STATS_POPOVER_POSITION, THUMBNAIL_TYPE } from '../../constants';
|
||||
// @ts-ignore
|
||||
import { getIndicatorsTooltipPosition } from '../../functions.web';
|
||||
|
||||
// @ts-ignore
|
||||
import PinnedIndicator from './PinnedIndicator';
|
||||
// @ts-ignore
|
||||
import RaisedHandIndicator from './RaisedHandIndicator';
|
||||
// @ts-ignore
|
||||
import StatusIndicators from './StatusIndicators';
|
||||
import VideoMenuTriggerButton from './VideoMenuTriggerButton';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
declare let interfaceConfig: any;
|
||||
|
||||
type Props = {
|
||||
|
||||
|
@ -38,7 +44,7 @@ type Props = {
|
|||
/**
|
||||
* Whether or not the thumbnail is a virtual screen share participant.
|
||||
*/
|
||||
isVirtualScreenshareParticipant: boolean,
|
||||
isVirtualScreenshareParticipant?: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the indicators are for the local participant.
|
||||
|
@ -95,9 +101,9 @@ const ThumbnailTopIndicators = ({
|
|||
const { NORMAL = 16 } = interfaceConfig.INDICATOR_FONT_SIZES || {};
|
||||
const _indicatorIconSize = NORMAL;
|
||||
const _connectionIndicatorAutoHideEnabled = Boolean(
|
||||
useSelector(state => state['features/base/config'].connectionIndicators?.autoHide) ?? true);
|
||||
useSelector((state: IState) => state['features/base/config'].connectionIndicators?.autoHide) ?? true);
|
||||
const _connectionIndicatorDisabled = _isMobile
|
||||
|| Boolean(useSelector(state => state['features/base/config'].connectionIndicators?.disabled));
|
||||
|| Boolean(useSelector((state: IState) => state['features/base/config'].connectionIndicators?.disabled));
|
||||
const _isMultiStreamEnabled = useSelector(getMultipleVideoSupportFeatureFlag);
|
||||
const showConnectionIndicator = isHovered || !_connectionIndicatorAutoHideEnabled;
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
|
||||
// @ts-ignore
|
||||
import { BoxModel } from '../base/styles';
|
||||
|
||||
/**
|
|
@ -1,6 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import { GiphyFetch } from '@giphy/js-fetch-api';
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { GiphyFetch, TrendingOptions } from '@giphy/js-fetch-api';
|
||||
import { Grid } from '@giphy/react-components';
|
||||
import { makeStyles } from '@material-ui/core';
|
||||
import clsx from 'clsx';
|
||||
|
@ -8,21 +7,30 @@ import React, { useCallback, useEffect, useState } from 'react';
|
|||
import { useTranslation } from 'react-i18next';
|
||||
import { batch, useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
// @ts-ignore
|
||||
import { createGifSentEvent, sendAnalytics } from '../../../analytics';
|
||||
import { IState } from '../../../app/types';
|
||||
// @ts-ignore
|
||||
import InputField from '../../../base/premeeting/components/web/InputField';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.web';
|
||||
// @ts-ignore
|
||||
import { sendMessage } from '../../../chat/actions.any';
|
||||
import { SCROLL_SIZE } from '../../../filmstrip';
|
||||
import { SCROLL_SIZE } from '../../../filmstrip/constants';
|
||||
import { toggleReactionsMenuVisibility } from '../../../reactions/actions.web';
|
||||
// @ts-ignore
|
||||
import { setOverflowMenuVisible } from '../../../toolbox/actions.web';
|
||||
// @ts-ignore
|
||||
import { Drawer, JitsiPortal } from '../../../toolbox/components/web';
|
||||
// @ts-ignore
|
||||
import { showOverflowDrawer } from '../../../toolbox/functions.web';
|
||||
// @ts-ignore
|
||||
import { setGifDrawerVisibility } from '../../actions';
|
||||
// @ts-ignore
|
||||
import { formatGifUrlMessage, getGifAPIKey, getGifUrl } from '../../functions';
|
||||
|
||||
const OVERFLOW_DRAWER_PADDING = BaseTheme.spacing(3);
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
gifsMenu: {
|
||||
width: '100%',
|
||||
|
@ -87,17 +95,17 @@ const useStyles = makeStyles(theme => {
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
function GifsMenu() {
|
||||
const API_KEY = useSelector(getGifAPIKey);
|
||||
const API_KEY: string = useSelector(getGifAPIKey);
|
||||
const giphyFetch = new GiphyFetch(API_KEY);
|
||||
const [ searchKey, setSearchKey ] = useState();
|
||||
const [ searchKey, setSearchKey ] = useState<string>();
|
||||
const styles = useStyles();
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
const overflowDrawer = useSelector(showOverflowDrawer);
|
||||
const { clientWidth } = useSelector(state => state['features/base/responsive-ui']);
|
||||
const overflowDrawer: boolean = useSelector(showOverflowDrawer);
|
||||
const { clientWidth } = useSelector((state: IState) => state['features/base/responsive-ui']);
|
||||
|
||||
const fetchGifs = useCallback(async (offset = 0) => {
|
||||
const options = {
|
||||
const options: TrendingOptions = {
|
||||
rating: 'pg-13',
|
||||
limit: 20,
|
||||
offset
|
||||
|
@ -113,7 +121,7 @@ function GifsMenu() {
|
|||
const onDrawerClose = useCallback(() => {
|
||||
dispatch(setGifDrawerVisibility(false));
|
||||
dispatch(setOverflowMenuVisible(false));
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleGifClick = useCallback((gif, e) => {
|
||||
e?.stopPropagation();
|
||||
|
@ -135,26 +143,37 @@ function GifsMenu() {
|
|||
|
||||
const handleSearchKeyChange = useCallback(value => {
|
||||
setSearchKey(value);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleKeyDown = useCallback(e => {
|
||||
if (!document.activeElement) {
|
||||
return;
|
||||
}
|
||||
if (e.keyCode === 38) { // up arrow
|
||||
e.preventDefault();
|
||||
|
||||
// if the first gif is focused move focus to the input
|
||||
if (document.activeElement.previousElementSibling === null) {
|
||||
document.querySelector('.gif-input').focus();
|
||||
const element = document.querySelector('.gif-input') as HTMLElement;
|
||||
|
||||
element?.focus();
|
||||
} else {
|
||||
document.activeElement.previousElementSibling.focus();
|
||||
const element = document.activeElement.previousElementSibling as HTMLElement;
|
||||
|
||||
element?.focus();
|
||||
}
|
||||
} else if (e.keyCode === 40) { // down arrow
|
||||
e.preventDefault();
|
||||
|
||||
// if the input is focused move focus to the first gif
|
||||
if (document.activeElement.classList.contains('gif-input')) {
|
||||
document.querySelector('.giphy-gif').focus();
|
||||
const element = document.querySelector('.giphy-gif') as HTMLElement;
|
||||
|
||||
element?.focus();
|
||||
} else {
|
||||
document.activeElement.nextElementSibling.focus();
|
||||
const element = document.activeElement.nextElementSibling as HTMLElement;
|
||||
|
||||
element?.focus();
|
||||
}
|
||||
}
|
||||
}, []);
|
|
@ -0,0 +1 @@
|
|||
export * from './native';
|
|
@ -0,0 +1 @@
|
|||
export * from './web';
|
|
@ -1,2 +1 @@
|
|||
export { default as KeyboardShortcutsButton } from './KeyboardShortcutsButton';
|
||||
export { default as KeyboardShortcutsDialog } from './KeyboardShortcutsDialog';
|
||||
export * from './_';
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// @flow
|
||||
|
||||
import { createToolbarEvent, sendAnalytics } from '../../analytics';
|
||||
import { translate } from '../../base/i18n';
|
||||
import { IconDeviceDocument } from '../../base/icons';
|
||||
import { connect } from '../../base/redux';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../base/toolbox/components';
|
||||
import { openKeyboardShortcutsDialog } from '../actions';
|
||||
import { createToolbarEvent, sendAnalytics } from '../../../analytics';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { IconDeviceDocument } from '../../../base/icons';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
|
||||
import { openKeyboardShortcutsDialog } from '../../actions';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link KeyboardShortcutsButton}.
|
|
@ -1,33 +1,28 @@
|
|||
/* @flow */
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import clsx from 'clsx';
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { Dialog } from '../../base/dialog';
|
||||
import { translate } from '../../base/i18n';
|
||||
// @ts-ignore
|
||||
import { Dialog } from '../../../base/dialog';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
* {@link KeyboardShortcutsDialog}.
|
||||
*/
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* An object containing the CSS classes.
|
||||
*/
|
||||
classes: Object,
|
||||
classes: any,
|
||||
|
||||
/**
|
||||
* A Map with keyboard keys as keys and translation keys as values.
|
||||
*/
|
||||
shortcutDescriptions: Object,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
shortcutDescriptions: Map<string, string>
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the styles for the component.
|
||||
|
@ -36,7 +31,7 @@ type Props = {
|
|||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
const styles = theme => {
|
||||
const styles = (theme: any) => {
|
||||
return {
|
||||
list: {
|
||||
listStyleType: 'none',
|
||||
|
@ -86,7 +81,7 @@ class KeyboardShortcutsDialog extends Component<Props> {
|
|||
<ul
|
||||
className = { clsx('shortcuts-list', this.props.classes.list) }
|
||||
id = 'keyboard-shortcuts-list'>
|
||||
{ shortcuts }
|
||||
{shortcuts}
|
||||
</ul>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
@ -101,7 +96,7 @@ class KeyboardShortcutsDialog extends Component<Props> {
|
|||
* @private
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderShortcutsListItem(keyboardKey, translationKey) {
|
||||
_renderShortcutsListItem(keyboardKey: string, translationKey: string) {
|
||||
let modifierKey = 'Alt';
|
||||
|
||||
if (window.navigator?.platform) {
|
|
@ -0,0 +1,2 @@
|
|||
export { default as KeyboardShortcutsButton } from './KeyboardShortcutsButton';
|
||||
export { default as KeyboardShortcutsDialog } from './KeyboardShortcutsDialog';
|
|
@ -1,20 +1,23 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { FlagGroupContext } from '@atlaskit/flag/flag-group';
|
||||
import { AtlasKitThemeProvider } from '@atlaskit/theme';
|
||||
import { withStyles } from '@material-ui/styles';
|
||||
import clsx from 'clsx';
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { CSSTransition, TransitionGroup } from 'react-transition-group';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import { connect } from '../../../base/redux/functions';
|
||||
// @ts-ignore
|
||||
import { hideNotification } from '../../actions';
|
||||
// @ts-ignore
|
||||
import { areThereNotifications } from '../../functions';
|
||||
|
||||
// @ts-ignore
|
||||
import Notification from './Notification';
|
||||
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Whether we are a SIP gateway or not.
|
||||
|
@ -30,12 +33,15 @@ type Props = {
|
|||
* The notifications to be displayed, with the first index being the
|
||||
* notification at the top and the rest shown below it in order.
|
||||
*/
|
||||
_notifications: Array<Object>,
|
||||
_notifications: Array<{
|
||||
props: Object;
|
||||
uid: number;
|
||||
}>,
|
||||
|
||||
/**
|
||||
* JSS classes object.
|
||||
*/
|
||||
classes: Object,
|
||||
classes: any,
|
||||
|
||||
/**
|
||||
* Invoked to update the redux store in order to remove notifications.
|
||||
|
@ -45,15 +51,10 @@ type Props = {
|
|||
/**
|
||||
* Whether or not the notifications are displayed in a portal.
|
||||
*/
|
||||
portal?: boolean,
|
||||
portal?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
const useStyles = theme => {
|
||||
const useStyles = (theme: any) => {
|
||||
return {
|
||||
container: {
|
||||
position: 'absolute',
|
||||
|
@ -124,7 +125,7 @@ const useStyles = theme => {
|
|||
*/
|
||||
class NotificationsContainer extends Component<Props> {
|
||||
_api: Object;
|
||||
_timeouts: Map<string, TimeoutID>;
|
||||
_timeouts: Map<string, number>;
|
||||
|
||||
/**
|
||||
* Initializes a new {@code NotificationsContainer} instance.
|
||||
|
@ -161,6 +162,7 @@ class NotificationsContainer extends Component<Props> {
|
|||
|
||||
return (
|
||||
<AtlasKitThemeProvider mode = 'light'>
|
||||
{/* @ts-ignore */}
|
||||
<FlagGroupContext.Provider value = { this._api }>
|
||||
<div
|
||||
className = { clsx(this.props.classes.container, {
|
||||
|
@ -176,8 +178,6 @@ class NotificationsContainer extends Component<Props> {
|
|||
);
|
||||
}
|
||||
|
||||
_onDismissed: number => void;
|
||||
|
||||
/**
|
||||
* Emits an action to remove the notification from the redux store so it
|
||||
* stops displaying.
|
||||
|
@ -186,12 +186,12 @@ class NotificationsContainer extends Component<Props> {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onDismissed(uid) {
|
||||
const timeout = this._timeouts.get(uid);
|
||||
_onDismissed(uid: number) {
|
||||
const timeout = this._timeouts.get(`${uid}`);
|
||||
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
this._timeouts.delete(uid);
|
||||
this._timeouts.delete(`${uid}`);
|
||||
}
|
||||
|
||||
this.props.dispatch(hideNotification(uid));
|
||||
|
@ -238,7 +238,7 @@ class NotificationsContainer extends Component<Props> {
|
|||
* @private
|
||||
* @returns {Props}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
function _mapStateToProps(state: any) {
|
||||
const { notifications } = state['features/notifications'];
|
||||
const { iAmSipGateway } = state['features/base/config'];
|
||||
const { isOpen: isChatOpen } = state['features/chat'];
|
||||
|
@ -251,4 +251,5 @@ function _mapStateToProps(state) {
|
|||
};
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export default translate(connect(_mapStateToProps)(withStyles(useStyles)(NotificationsContainer)));
|
|
@ -1,18 +1,24 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import clsx from 'clsx';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import React, { ReactElement, useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { IState } from '../../../../../app/types';
|
||||
// @ts-ignore
|
||||
import { ListItem } from '../../../../../base/components';
|
||||
import { Icon, IconArrowDown, IconArrowUp } from '../../../../../base/icons';
|
||||
import { isLocalParticipantModerator } from '../../../../../base/participants';
|
||||
import Icon from '../../../../../base/icons/components/Icon';
|
||||
import { IconArrowDown, IconArrowUp } from '../../../../../base/icons/svg/index';
|
||||
import { isLocalParticipantModerator } from '../../../../../base/participants/functions';
|
||||
// @ts-ignore
|
||||
import { showOverflowDrawer } from '../../../../../toolbox/functions.web';
|
||||
// @ts-ignore
|
||||
import { ACTION_TRIGGER } from '../../../../constants';
|
||||
// @ts-ignore
|
||||
import { participantMatchesSearch } from '../../../../functions';
|
||||
import ParticipantActionEllipsis from '../../../web/ParticipantActionEllipsis';
|
||||
// @ts-ignore
|
||||
import ParticipantItem from '../../../web/ParticipantItem';
|
||||
|
||||
type Props = {
|
||||
|
@ -25,27 +31,29 @@ type Props = {
|
|||
/**
|
||||
* React children.
|
||||
*/
|
||||
children: React$Node,
|
||||
children: ReactElement,
|
||||
|
||||
/**
|
||||
* Is this item highlighted/raised.
|
||||
*/
|
||||
isHighlighted?: boolean,
|
||||
|
||||
/**
|
||||
* Callback to raise menu. Used to raise menu on mobile long press.
|
||||
*/
|
||||
onRaiseMenu: Function,
|
||||
|
||||
/**
|
||||
* Callback for when the mouse leaves this component.
|
||||
*/
|
||||
onLeave?: Function,
|
||||
|
||||
/**
|
||||
* Callback to raise menu. Used to raise menu on mobile long press.
|
||||
*/
|
||||
onRaiseMenu: Function,
|
||||
|
||||
/**
|
||||
* The raise context for the participant menu.
|
||||
*/
|
||||
participantContextEntity: ?Object,
|
||||
participantContextEntity?: {
|
||||
jid: string
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback to raise participant context menu.
|
||||
|
@ -55,7 +63,16 @@ type Props = {
|
|||
/**
|
||||
* Room reference.
|
||||
*/
|
||||
room: Object,
|
||||
room: {
|
||||
id: string;
|
||||
name: string;
|
||||
participants: {
|
||||
[jid: string]: {
|
||||
displayName: string;
|
||||
jid: string;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Participants search string.
|
||||
|
@ -68,7 +85,7 @@ type Props = {
|
|||
toggleParticipantMenu: Function
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
container: {
|
||||
boxShadow: 'none'
|
||||
|
@ -117,7 +134,7 @@ export const CollapsibleRoom = ({
|
|||
const raiseMenu = useCallback(target => {
|
||||
onRaiseMenu(target);
|
||||
}, [ onRaiseMenu ]);
|
||||
const { defaultRemoteDisplayName } = useSelector(state => state['features/base/config']);
|
||||
const { defaultRemoteDisplayName } = useSelector((state: IState) => state['features/base/config']);
|
||||
const overflowDrawer = useSelector(showOverflowDrawer);
|
||||
const moderator = useSelector(isLocalParticipantModerator);
|
||||
|
||||
|
@ -153,7 +170,7 @@ export const CollapsibleRoom = ({
|
|||
textChildren = { roomName }
|
||||
trigger = { actionsTrigger } />
|
||||
{!collapsed && room?.participants
|
||||
&& Object.values(room?.participants || {}).map((p: Object) =>
|
||||
&& Object.values(room?.participants || {}).map(p =>
|
||||
participantMatchesSearch(p, searchString) && (
|
||||
<ParticipantItem
|
||||
actionsTrigger = { ACTION_TRIGGER.HOVER }
|
||||
|
@ -166,6 +183,7 @@ export const CollapsibleRoom = ({
|
|||
participantID = { p.jid }>
|
||||
{!overflowDrawer && moderator && (
|
||||
<ParticipantActionEllipsis
|
||||
accessibilityLabel = { t('breakoutRoom.more') }
|
||||
onClick = { toggleParticipantMenu({ room,
|
||||
jid: p.jid,
|
||||
participantName: p.displayName }) } />
|
|
@ -1,5 +1,4 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
@ -10,32 +9,39 @@ import {
|
|||
requestDisableVideoModeration,
|
||||
requestEnableAudioModeration,
|
||||
requestEnableVideoModeration
|
||||
// @ts-ignore
|
||||
} from '../../../av-moderation/actions';
|
||||
import {
|
||||
isEnabled as isAvModerationEnabled,
|
||||
isSupported as isAvModerationSupported
|
||||
// @ts-ignore
|
||||
} from '../../../av-moderation/functions';
|
||||
// @ts-ignore
|
||||
import { ContextMenu, ContextMenuItemGroup } from '../../../base/components';
|
||||
// @ts-ignore
|
||||
import { openDialog } from '../../../base/dialog';
|
||||
import {
|
||||
IconCheck,
|
||||
IconHorizontalPoints,
|
||||
IconVideoOff
|
||||
} from '../../../base/icons';
|
||||
import { MEDIA_TYPE } from '../../../base/media';
|
||||
} from '../../../base/icons/svg';
|
||||
import { MEDIA_TYPE } from '../../../base/media/constants';
|
||||
import {
|
||||
getParticipantCount,
|
||||
isEveryoneModerator
|
||||
} from '../../../base/participants';
|
||||
} from '../../../base/participants/functions';
|
||||
// @ts-ignore
|
||||
import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
|
||||
import {
|
||||
SETTINGS_TABS,
|
||||
openSettingsDialog,
|
||||
shouldShowModeratorSettings
|
||||
// @ts-ignore
|
||||
} from '../../../settings';
|
||||
// @ts-ignore
|
||||
import { MuteEveryonesVideoDialog } from '../../../video-menu/components';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
contextMenu: {
|
||||
bottom: 'auto',
|
|
@ -1,40 +1,45 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React, { useCallback, useState, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
// @ts-ignore
|
||||
import { ContextMenu, ContextMenuItemGroup } from '../../../base/components';
|
||||
import { IconChat, IconCloseCircle, IconHorizontalPoints } from '../../../base/icons';
|
||||
import { hasRaisedHand } from '../../../base/participants';
|
||||
import { IconChat, IconCloseCircle, IconHorizontalPoints } from '../../../base/icons/svg/index';
|
||||
import { hasRaisedHand } from '../../../base/participants/functions';
|
||||
import { Participant } from '../../../base/participants/reducer';
|
||||
import Button from '../../../base/ui/components/web/Button';
|
||||
import { BUTTON_TYPES } from '../../../base/ui/constants';
|
||||
// @ts-ignore
|
||||
import { showLobbyChatButton } from '../../../lobby/functions';
|
||||
// @ts-ignore
|
||||
import { ACTION_TRIGGER, MEDIA_STATE } from '../../constants';
|
||||
// @ts-ignore
|
||||
import { useLobbyActions } from '../../hooks';
|
||||
|
||||
// @ts-ignore
|
||||
import ParticipantItem from './ParticipantItem';
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* If an overflow drawer should be displayed.
|
||||
*/
|
||||
overflowDrawer: boolean,
|
||||
|
||||
/**
|
||||
* Callback used to open a drawer with admit/reject actions.
|
||||
*/
|
||||
openDrawerForParticipant: Function,
|
||||
|
||||
/**
|
||||
* If an overflow drawer should be displayed.
|
||||
*/
|
||||
overflowDrawer: boolean,
|
||||
|
||||
/**
|
||||
* Participant reference.
|
||||
*/
|
||||
participant: Object
|
||||
participant: Participant
|
||||
};
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
button: {
|
||||
marginRight: `${theme.spacing(2)}px`
|
||||
|
@ -67,8 +72,8 @@ export const LobbyParticipantItem = ({
|
|||
|
||||
const moreButtonRef = useRef();
|
||||
|
||||
const openContextMenu = useCallback(() => setIsOpen(true));
|
||||
const closeContextMenu = useCallback(() => setIsOpen(false));
|
||||
const openContextMenu = useCallback(() => setIsOpen(true), []);
|
||||
const closeContextMenu = useCallback(() => setIsOpen(false), []);
|
||||
|
||||
const renderAdmitButton = () => (
|
||||
<Button
|
|
@ -1,22 +1,29 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
|
||||
// @ts-ignore
|
||||
import { Avatar } from '../../../base/avatar';
|
||||
import { Icon, IconCheck, IconClose } from '../../../base/icons';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconCheck, IconClose } from '../../../base/icons/svg/index';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
// @ts-ignore
|
||||
import { admitMultiple } from '../../../lobby/actions.web';
|
||||
// @ts-ignore
|
||||
import { getLobbyEnabled, getKnockingParticipants } from '../../../lobby/functions';
|
||||
// @ts-ignore
|
||||
import { Drawer, JitsiPortal } from '../../../toolbox/components/web';
|
||||
// @ts-ignore
|
||||
import { showOverflowDrawer } from '../../../toolbox/functions';
|
||||
// @ts-ignore
|
||||
import { useLobbyActions, useParticipantDrawer } from '../../hooks';
|
||||
|
||||
// @ts-ignore
|
||||
import LobbyParticipantItems from './LobbyParticipantItems';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
drawerActions: {
|
||||
listStyleType: 'none',
|
||||
|
@ -67,7 +74,7 @@ const useStyles = makeStyles(theme => {
|
|||
*/
|
||||
export default function LobbyParticipants() {
|
||||
const lobbyEnabled = useSelector(getLobbyEnabled);
|
||||
const participants = useSelector(getKnockingParticipants);
|
||||
const participants: Array<Object> = useSelector(getKnockingParticipants);
|
||||
const { t } = useTranslation();
|
||||
const classes = useStyles();
|
||||
const dispatch = useDispatch();
|
|
@ -1,30 +1,40 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { IState } from '../../../app/types';
|
||||
// @ts-ignore
|
||||
import { rejectParticipantAudio } from '../../../av-moderation/actions';
|
||||
// @ts-ignore
|
||||
import useContextMenu from '../../../base/components/context-menu/useContextMenu';
|
||||
import participantsPaneTheme from '../../../base/components/themes/participantsPaneTheme.json';
|
||||
// @ts-ignore
|
||||
import { isToolbarButtonEnabled } from '../../../base/config/functions.web';
|
||||
import { MEDIA_TYPE } from '../../../base/media';
|
||||
import { getParticipantById } from '../../../base/participants';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { MEDIA_TYPE } from '../../../base/media/constants';
|
||||
import { getParticipantById } from '../../../base/participants/functions';
|
||||
import { connect } from '../../../base/redux/functions';
|
||||
import Input from '../../../base/ui/components/web/Input';
|
||||
import { normalizeAccents } from '../../../base/util/strings';
|
||||
import { normalizeAccents } from '../../../base/util/strings.web';
|
||||
// @ts-ignore
|
||||
import { getBreakoutRooms, getCurrentRoomId, isInBreakoutRoom } from '../../../breakout-rooms/functions';
|
||||
// @ts-ignore
|
||||
import { showOverflowDrawer } from '../../../toolbox/functions';
|
||||
// @ts-ignore
|
||||
import { muteRemote } from '../../../video-menu/actions.any';
|
||||
// @ts-ignore
|
||||
import { getSortedParticipantIds, shouldRenderInviteButton } from '../../functions';
|
||||
// @ts-ignore
|
||||
import { useParticipantDrawer } from '../../hooks';
|
||||
|
||||
import { InviteButton } from './InviteButton';
|
||||
// @ts-ignore
|
||||
import MeetingParticipantContextMenu from './MeetingParticipantContextMenu';
|
||||
// @ts-ignore
|
||||
import MeetingParticipantItems from './MeetingParticipantItems';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
heading: {
|
||||
color: theme.palette.text02,
|
||||
|
@ -48,13 +58,13 @@ const useStyles = makeStyles(theme => {
|
|||
});
|
||||
|
||||
type Props = {
|
||||
currentRoom: ?Object,
|
||||
participantsCount: number,
|
||||
overflowDrawer: boolean,
|
||||
currentRoom?: {name: string},
|
||||
overflowDrawer?: boolean,
|
||||
participantsCount?: number,
|
||||
searchString: string,
|
||||
setSearchString: Function,
|
||||
showInviteButton: boolean,
|
||||
sortedParticipantIds: Array<string>
|
||||
setSearchString: (newValue: string) => void,
|
||||
showInviteButton?: boolean,
|
||||
sortedParticipantIds?: Array<string>
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -156,15 +166,15 @@ function MeetingParticipants({
|
|||
* @private
|
||||
* @returns {Props}
|
||||
*/
|
||||
function _mapStateToProps(state): Object {
|
||||
let sortedParticipantIds = getSortedParticipantIds(state);
|
||||
function _mapStateToProps(state: IState): Object {
|
||||
let sortedParticipantIds: any = getSortedParticipantIds(state);
|
||||
|
||||
// Filter out the virtual screenshare participants since we do not want them to be displayed as separate
|
||||
// participants in the participants pane.
|
||||
sortedParticipantIds = sortedParticipantIds.filter(id => {
|
||||
sortedParticipantIds = sortedParticipantIds.filter((id: any) => {
|
||||
const participant = getParticipantById(state, id);
|
||||
|
||||
return !participant.isVirtualScreenshareParticipant;
|
||||
return !participant?.isVirtualScreenshareParticipant;
|
||||
});
|
||||
|
||||
const participantsCount = sortedParticipantIds.length;
|
|
@ -1,10 +1,13 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React, { type Node, useCallback } from 'react';
|
||||
import React, { ReactElement, useCallback } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
// @ts-ignore
|
||||
import { Avatar } from '../../../base/avatar';
|
||||
// @ts-ignore
|
||||
import { ListItem } from '../../../base/components';
|
||||
// @ts-ignore
|
||||
import { translate } from '../../../base/i18n';
|
||||
import {
|
||||
ACTION_TRIGGER,
|
||||
|
@ -13,11 +16,13 @@ import {
|
|||
type ActionTrigger,
|
||||
type MediaState,
|
||||
VideoStateIcons
|
||||
// @ts-ignore
|
||||
} from '../../constants';
|
||||
|
||||
// @ts-ignore
|
||||
import { RaisedHandIndicator } from './RaisedHandIndicator';
|
||||
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Type of trigger for the participant actions.
|
||||
|
@ -32,7 +37,7 @@ type Props = {
|
|||
/**
|
||||
* React children.
|
||||
*/
|
||||
children?: Node,
|
||||
children?: ReactElement,
|
||||
|
||||
/**
|
||||
* Whether or not to disable the moderator indicator.
|
||||
|
@ -59,16 +64,16 @@ type Props = {
|
|||
*/
|
||||
local: boolean,
|
||||
|
||||
/**
|
||||
* Opens a drawer with participant actions.
|
||||
*/
|
||||
openDrawerForParticipant?: Function,
|
||||
|
||||
/**
|
||||
* Callback for when the mouse leaves this component.
|
||||
*/
|
||||
onLeave?: Function,
|
||||
|
||||
/**
|
||||
* Opens a drawer with participant actions.
|
||||
*/
|
||||
openDrawerForParticipant?: Function,
|
||||
|
||||
/**
|
||||
* If an overflow drawer can be opened.
|
||||
*/
|
||||
|
@ -89,18 +94,13 @@ type Props = {
|
|||
*/
|
||||
videoMediaState?: MediaState,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function,
|
||||
|
||||
/**
|
||||
* The translated "you" text.
|
||||
*/
|
||||
youText?: string
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
nameContainer: {
|
||||
display: 'flex',
|
||||
|
@ -150,7 +150,7 @@ function ParticipantItem({
|
|||
() => openDrawerForParticipant && openDrawerForParticipant({
|
||||
participantID,
|
||||
displayName
|
||||
}));
|
||||
}), []);
|
||||
|
||||
const styles = useStyles();
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
// @flow
|
||||
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React from 'react';
|
||||
|
||||
import { Icon, IconRaisedHandHollow } from '../../../base/icons';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconRaisedHandHollow } from '../../../base/icons/svg/index';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.web';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
indicator: {
|
||||
backgroundColor: theme.palette.warning02,
|
|
@ -1,16 +1,14 @@
|
|||
// @flow
|
||||
|
||||
import { withStyles } from '@material-ui/styles';
|
||||
import React from 'react';
|
||||
|
||||
import { Icon } from '../../base/icons';
|
||||
import Icon from '../../base/icons/components/Icon';
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The css classes generated from theme.
|
||||
*/
|
||||
classes: Object,
|
||||
classes: any,
|
||||
|
||||
/**
|
||||
* Attribute used in automated testing.
|
||||
|
@ -20,7 +18,7 @@ type Props = {
|
|||
/**
|
||||
* The button's icon.
|
||||
*/
|
||||
icon: HTMLElement,
|
||||
icon: Function,
|
||||
|
||||
/**
|
||||
* The button's label.
|
||||
|
@ -30,17 +28,12 @@ type Props = {
|
|||
/**
|
||||
* Function to be called when button is clicked.
|
||||
*/
|
||||
onButtonClick: Function,
|
||||
onButtonClick: (e?: React.MouseEvent) => void,
|
||||
|
||||
/**
|
||||
* Function to be called on key pressed.
|
||||
*/
|
||||
onKeyPressed: Function,
|
||||
|
||||
/**
|
||||
* Used for translation.
|
||||
*/
|
||||
t: Function
|
||||
onKeyPressed: (e?: React.KeyboardEvent) => void
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -50,7 +43,7 @@ type Props = {
|
|||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
const styles = theme => {
|
||||
const styles = (theme: any) => {
|
||||
return {
|
||||
prejoinPreviewDropdownBtn: {
|
||||
alignItems: 'center',
|
|
@ -1,14 +1,17 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
// @ts-ignore
|
||||
import { Avatar } from '../../../base/avatar';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { Icon, IconClose } from '../../../base/icons';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconClose } from '../../../base/icons/svg/index';
|
||||
// @ts-ignore
|
||||
import Label from '../Label';
|
||||
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* The phone number that is being called.
|
||||
|
@ -28,15 +31,10 @@ type Props = {
|
|||
/**
|
||||
* The status of the call.
|
||||
*/
|
||||
status: string,
|
||||
status: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for translation.
|
||||
*/
|
||||
t: Function,
|
||||
};
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
callingDialog: {
|
||||
padding: theme.spacing(3),
|
|
@ -1,15 +1,19 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { Icon, IconArrowLeft } from '../../../base/icons';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconArrowLeft } from '../../../base/icons/svg/index';
|
||||
// @ts-ignore
|
||||
import { ActionButton } from '../../../base/premeeting';
|
||||
// @ts-ignore
|
||||
import { getCountryCodeFromPhone } from '../../utils';
|
||||
// @ts-ignore
|
||||
import Label from '../Label';
|
||||
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* The number to call in order to join the conference.
|
||||
|
@ -21,11 +25,6 @@ type Props = {
|
|||
*/
|
||||
onBack: Function,
|
||||
|
||||
/**
|
||||
* Click handler for the text button.
|
||||
*/
|
||||
onTextButtonClick: Function,
|
||||
|
||||
/**
|
||||
* Click handler for primary button.
|
||||
*/
|
||||
|
@ -34,20 +33,20 @@ type Props = {
|
|||
/**
|
||||
* Click handler for the small additional text.
|
||||
*/
|
||||
onSmallTextClick: Function,
|
||||
onSmallTextClick: (e?: React.MouseEvent) => void,
|
||||
|
||||
/**
|
||||
* Click handler for the text button.
|
||||
*/
|
||||
onTextButtonClick: (e?: React.MouseEvent) => void,
|
||||
|
||||
/**
|
||||
* The passCode of the conference.
|
||||
*/
|
||||
passCode: string,
|
||||
passCode: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for translation.
|
||||
*/
|
||||
t: Function,
|
||||
};
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
dialInDialog: {
|
||||
textAlign: 'center',
|
|
@ -1,15 +1,19 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { Icon, IconClose } from '../../../base/icons';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconClose } from '../../../base/icons/svg/index';
|
||||
// @ts-ignore
|
||||
import { ActionButton } from '../../../base/premeeting';
|
||||
// @ts-ignore
|
||||
import Label from '../Label';
|
||||
// @ts-ignore
|
||||
import CountryPicker from '../country-picker/CountryPicker';
|
||||
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Closes a dialog.
|
||||
|
@ -24,15 +28,10 @@ type Props = {
|
|||
/**
|
||||
* Handler for text button.
|
||||
*/
|
||||
onTextButtonClick: Function,
|
||||
onTextButtonClick: Function
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for translation.
|
||||
*/
|
||||
t: Function,
|
||||
};
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
dialOutDialog: {
|
||||
padding: `${theme.spacing(3)}px`
|
|
@ -1,18 +1,21 @@
|
|||
// @flow
|
||||
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { Icon, IconCheckSolid, IconExclamationTriangle } from '../../../base/icons';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { IState } from '../../../app/types';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconCheckSolid, IconExclamationTriangle } from '../../../base/icons/svg';
|
||||
import { connect } from '../../../base/redux/functions';
|
||||
import {
|
||||
getDeviceStatusType,
|
||||
getDeviceStatusText
|
||||
|
||||
// @ts-ignore
|
||||
} from '../../functions';
|
||||
|
||||
export type Props = {
|
||||
export interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* The text to be displayed in relation to the status of the audio/video devices.
|
||||
|
@ -23,15 +26,10 @@ export type Props = {
|
|||
* The type of status for current devices, controlling the background color of the text.
|
||||
* Can be `ok` or `warning`.
|
||||
*/
|
||||
deviceStatusType: string,
|
||||
deviceStatusType: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for translation.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
deviceStatus: {
|
||||
alignItems: 'center',
|
||||
|
@ -87,7 +85,7 @@ const iconMap = {
|
|||
*/
|
||||
function DeviceStatus({ deviceStatusType, deviceStatusText, t }: Props) {
|
||||
const classes = useStyles();
|
||||
const { src, className } = iconMap[deviceStatusType];
|
||||
const { src, className } = iconMap[deviceStatusType as keyof typeof iconMap];
|
||||
const hasError = deviceStatusType === 'warning';
|
||||
const containerClassName = clsx(classes.deviceStatus, { 'device-status-error': hasError });
|
||||
|
||||
|
@ -113,7 +111,7 @@ function DeviceStatus({ deviceStatusType, deviceStatusText, t }: Props) {
|
|||
* @param {Object} state - The redux state.
|
||||
* @returns {{ deviceStatusText: string, deviceStatusText: string }}
|
||||
*/
|
||||
function mapStateToProps(state) {
|
||||
function mapStateToProps(state: IState) {
|
||||
return {
|
||||
deviceStatusText: getDeviceStatusText(state),
|
||||
deviceStatusType: getDeviceStatusType(state)
|
|
@ -1,21 +1,26 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { withStyles } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
|
||||
// @ts-ignore
|
||||
import { StartRecordingDialog } from '../..';
|
||||
// @ts-ignore
|
||||
import { openDialog } from '../../../../base/dialog';
|
||||
import { translate } from '../../../../base/i18n';
|
||||
import { IconHighlight } from '../../../../base/icons';
|
||||
import { translate } from '../../../../base/i18n/functions';
|
||||
import { IconHighlight } from '../../../../base/icons/svg';
|
||||
// @ts-ignore
|
||||
import { Label } from '../../../../base/label';
|
||||
import { connect } from '../../../../base/redux';
|
||||
import { connect } from '../../../../base/redux/functions';
|
||||
// @ts-ignore
|
||||
import { Tooltip } from '../../../../base/tooltip';
|
||||
import BaseTheme from '../../../../base/ui/components/BaseTheme';
|
||||
import BaseTheme from '../../../../base/ui/components/BaseTheme.web';
|
||||
// @ts-ignore
|
||||
import { maybeShowPremiumFeatureDialog } from '../../../../jaas/actions';
|
||||
import { FEATURES } from '../../../../jaas/constants';
|
||||
import { StartRecordingDialog } from '../../../components';
|
||||
import AbstractHighlightButton, {
|
||||
_abstractMapStateToProps,
|
||||
type Props as AbstractProps
|
||||
// @ts-ignore
|
||||
} from '../AbstractHighlightButton';
|
||||
|
||||
type Props = AbstractProps & {
|
||||
|
@ -35,7 +40,7 @@ type Props = AbstractProps & {
|
|||
/**
|
||||
* The type of the React {@code Component} state of {@link HighlightButton}.
|
||||
*/
|
||||
type State = {
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Whether the notification which prompts for starting recording is open is not.
|
||||
|
@ -50,7 +55,7 @@ type Props = AbstractProps & {
|
|||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
const styles = theme => {
|
||||
const styles = (theme: any) => {
|
||||
return {
|
||||
container: {
|
||||
position: 'relative'
|
||||
|
@ -100,6 +105,7 @@ export class HighlightButton extends AbstractHighlightButton<Props, State> {
|
|||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// @ts-ignore
|
||||
this.state = {
|
||||
isNotificationOpen: false
|
||||
};
|
||||
|
@ -132,6 +138,7 @@ export class HighlightButton extends AbstractHighlightButton<Props, State> {
|
|||
* @returns {void}
|
||||
*/
|
||||
async _onOpenDialog() {
|
||||
// @ts-ignore
|
||||
const { dispatch } = this.props;
|
||||
const dialogShown = await dispatch(maybeShowPremiumFeatureDialog(FEATURES.RECORDING));
|
||||
|
||||
|
@ -147,12 +154,14 @@ export class HighlightButton extends AbstractHighlightButton<Props, State> {
|
|||
* @param {Event} e - The click event.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onClick(e) {
|
||||
_onClick(e: React.MouseEvent) {
|
||||
e.stopPropagation();
|
||||
|
||||
// @ts-ignore
|
||||
const { _disabled } = this.props;
|
||||
|
||||
if (_disabled) {
|
||||
// @ts-ignore
|
||||
this.setState({
|
||||
isNotificationOpen: true
|
||||
});
|
||||
|
@ -167,6 +176,7 @@ export class HighlightButton extends AbstractHighlightButton<Props, State> {
|
|||
* @returns {void}
|
||||
*/
|
||||
_onWindowClickListener() {
|
||||
// @ts-ignore
|
||||
this.setState({
|
||||
isNotificationOpen: false
|
||||
});
|
||||
|
@ -184,6 +194,7 @@ export class HighlightButton extends AbstractHighlightButton<Props, State> {
|
|||
_visible,
|
||||
classes,
|
||||
t
|
||||
// @ts-ignore
|
||||
} = this.props;
|
||||
|
||||
|
||||
|
@ -206,6 +217,7 @@ export class HighlightButton extends AbstractHighlightButton<Props, State> {
|
|||
id = 'highlightMeetingLabel'
|
||||
onClick = { this._onClick } />
|
||||
</Tooltip>
|
||||
{/* @ts-ignore */}
|
||||
{this.state.isNotificationOpen && (
|
||||
<div className = { classes.highlightNotification }>
|
||||
{t('recording.highlightMomentDisabled')}
|
||||
|
@ -221,4 +233,5 @@ export class HighlightButton extends AbstractHighlightButton<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export default withStyles(styles)(translate(connect(_abstractMapStateToProps)(HighlightButton)));
|
|
@ -1,14 +1,15 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import React from 'react';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
// @ts-ignore
|
||||
import { Label } from '../../../base/label';
|
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { connect } from '../../../base/redux/functions';
|
||||
import AbstractRecordingLabel, {
|
||||
_mapStateToProps
|
||||
// @ts-ignore
|
||||
} from '../AbstractRecordingLabel';
|
||||
|
||||
/**
|
||||
|
@ -18,7 +19,7 @@ import AbstractRecordingLabel, {
|
|||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
const styles = theme => {
|
||||
const styles = (theme: any) => {
|
||||
return {
|
||||
[JitsiRecordingConstants.mode.STREAM]: {
|
||||
background: theme.palette.ui03
|
||||
|
@ -42,24 +43,26 @@ class RecordingLabel extends AbstractRecordingLabel {
|
|||
* @inheritdoc
|
||||
*/
|
||||
_renderLabel() {
|
||||
// @ts-ignore
|
||||
if (this.props._status !== JitsiRecordingConstants.status.ON) {
|
||||
// Since there are no expanded labels on web, we only render this
|
||||
// label when the recording status is ON.
|
||||
return null;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const { classes, mode, t } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Label
|
||||
className = { classes && classes[mode] }
|
||||
// @ts-ignore
|
||||
text = { t(this._getLabelKey()) } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
_getLabelKey: () => ?string;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export default withStyles(styles)(translate(connect(_mapStateToProps)(RecordingLabel)));
|
|
@ -1,8 +1,8 @@
|
|||
// @flow
|
||||
import { makeStyles } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
// @ts-ignore
|
||||
import { RECORD_TYPE } from '../../constants';
|
||||
|
||||
/**
|
||||
|
@ -13,25 +13,25 @@ type Props = {
|
|||
/**
|
||||
* The id of the record.
|
||||
*/
|
||||
id: String,
|
||||
id: string,
|
||||
|
||||
/**
|
||||
* The name of the record.
|
||||
*/
|
||||
name: String,
|
||||
|
||||
/**
|
||||
* The type of the record.
|
||||
*/
|
||||
type: String,
|
||||
name: string,
|
||||
|
||||
/**
|
||||
* The handler for the click event.
|
||||
*/
|
||||
onClick: Function
|
||||
onClick: (e?: React.MouseEvent) => void,
|
||||
|
||||
/**
|
||||
* The type of the record.
|
||||
*/
|
||||
type: string
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
recordItem: {
|
||||
display: 'flex',
|
|
@ -1,21 +1,26 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import Spinner from '@atlaskit/spinner';
|
||||
import { makeStyles } from '@material-ui/core';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
// @ts-ignore
|
||||
import { Dialog, hideDialog } from '../../../base/dialog';
|
||||
import { Icon, IconSearch } from '../../../base/icons';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconSearch } from '../../../base/icons/svg/index';
|
||||
// @ts-ignore
|
||||
import { getFieldValue } from '../../../base/react';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.web';
|
||||
// @ts-ignore
|
||||
import { NOTES_MAX_LENGTH } from '../../constants';
|
||||
// @ts-ignore
|
||||
import { useSalesforceLinkDialog } from '../../useSalesforceLinkDialog';
|
||||
|
||||
import { RecordItem } from './RecordItem';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
// @ts-ignore
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
container: {
|
||||
minHeight: '450px',
|
||||
|
@ -136,7 +141,7 @@ function SalesforceLinkDialog() {
|
|||
showSearchResults
|
||||
} = useSalesforceLinkDialog();
|
||||
|
||||
const handleChange = useCallback((event: Event) => {
|
||||
const handleChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = getFieldValue(event);
|
||||
|
||||
setSearchTerm(value);
|
||||
|
@ -150,6 +155,7 @@ function SalesforceLinkDialog() {
|
|||
const renderSpinner = () => (
|
||||
<div className = { classes.spinner }>
|
||||
<Spinner
|
||||
// @ts-ignore
|
||||
isCompleting = { false }
|
||||
size = 'medium' />
|
||||
</div>
|
||||
|
@ -176,7 +182,7 @@ function SalesforceLinkDialog() {
|
|||
/* eslint-disable-next-line react/jsx-no-bind */
|
||||
onChange = { e => setNotes(e.target.value) }
|
||||
placeholder = { t('dialog.addMeetingNote') }
|
||||
row = '4'
|
||||
rows = { 4 }
|
||||
value = { notes } />
|
||||
</div>
|
||||
);
|
||||
|
@ -236,7 +242,7 @@ function SalesforceLinkDialog() {
|
|||
|
||||
return (
|
||||
<ul className = { classes.recordList }>
|
||||
{records.map(item => (
|
||||
{records.map((item: any) => (
|
||||
<RecordItem
|
||||
key = { `record-${item.id}` }
|
||||
/* eslint-disable-next-line react/jsx-no-bind */
|
|
@ -1,38 +1,46 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { withStyles } from '@material-ui/styles';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { IState } from '../../../app/types';
|
||||
// @ts-ignore
|
||||
import { getAvailableDevices } from '../../../base/devices';
|
||||
// @ts-ignore
|
||||
import { DialogWithTabs, hideDialog } from '../../../base/dialog';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { connect } from '../../../base/redux/functions';
|
||||
// @ts-ignore
|
||||
import { isCalendarEnabled } from '../../../calendar-sync';
|
||||
import {
|
||||
DeviceSelection,
|
||||
getDeviceSelectionDialogProps,
|
||||
submitDeviceSelectionTab
|
||||
// @ts-ignore
|
||||
} from '../../../device-selection';
|
||||
import {
|
||||
submitModeratorTab,
|
||||
submitMoreTab,
|
||||
submitProfileTab,
|
||||
submitSoundsTab
|
||||
// @ts-ignore
|
||||
} from '../../actions';
|
||||
// @ts-ignore
|
||||
import { SETTINGS_TABS } from '../../constants';
|
||||
import {
|
||||
getModeratorTabProps,
|
||||
getMoreTabProps,
|
||||
getProfileTabProps,
|
||||
getSoundsTabProps
|
||||
// @ts-ignore
|
||||
} from '../../functions';
|
||||
|
||||
// @ts-ignore
|
||||
import CalendarTab from './CalendarTab';
|
||||
import ModeratorTab from './ModeratorTab';
|
||||
import MoreTab from './MoreTab';
|
||||
import ProfileTab from './ProfileTab';
|
||||
import SoundsTab from './SoundsTab';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
declare let interfaceConfig: any;
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of
|
||||
|
@ -40,6 +48,15 @@ declare var interfaceConfig: Object;
|
|||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Information about the tabs to be rendered.
|
||||
*/
|
||||
_tabs: Array<{
|
||||
name: string;
|
||||
onMount: () => void;
|
||||
submit: () => void;
|
||||
}>,
|
||||
|
||||
/**
|
||||
* An object containing the CSS classes.
|
||||
*/
|
||||
|
@ -51,11 +68,6 @@ type Props = {
|
|||
*/
|
||||
defaultTab: string,
|
||||
|
||||
/**
|
||||
* Information about the tabs to be rendered.
|
||||
*/
|
||||
_tabs: Array<Object>,
|
||||
|
||||
/**
|
||||
* Invoked to save changed settings.
|
||||
*/
|
||||
|
@ -75,7 +87,7 @@ type Props = {
|
|||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
const styles = theme => {
|
||||
const styles = (theme: any) => {
|
||||
return {
|
||||
settingsDialog: {
|
||||
display: 'flex',
|
||||
|
@ -110,6 +122,7 @@ const styles = theme => {
|
|||
color: '#9FB0CC'
|
||||
},
|
||||
|
||||
// @ts-ignore
|
||||
[[ '& .calendar-tab',
|
||||
'& .more-tab',
|
||||
'& .box' ]]: {
|
||||
|
@ -225,9 +238,11 @@ class SettingsDialog extends Component<Props> {
|
|||
return {
|
||||
...tab,
|
||||
onMount: tab.onMount
|
||||
? (...args) => dispatch(tab.onMount(...args))
|
||||
// @ts-ignore
|
||||
? (...args: any) => dispatch(tab.onMount(...args))
|
||||
: undefined,
|
||||
submit: (...args) => tab.submit
|
||||
submit: (...args: any) => tab.submit
|
||||
// @ts-ignore
|
||||
&& dispatch(tab.submit(...args))
|
||||
};
|
||||
});
|
||||
|
@ -245,8 +260,6 @@ class SettingsDialog extends Component<Props> {
|
|||
);
|
||||
}
|
||||
|
||||
_closeDialog: () => void;
|
||||
|
||||
/**
|
||||
* Callback invoked to close the dialog without saving changes.
|
||||
*
|
||||
|
@ -269,7 +282,7 @@ class SettingsDialog extends Component<Props> {
|
|||
* tabs: Array<Object>
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state, ownProps) {
|
||||
function _mapStateToProps(state: IState, ownProps: any) {
|
||||
const { classes, isDisplayedOnWelcomePage } = ownProps;
|
||||
const configuredTabs = interfaceConfig.SETTINGS_SECTIONS || [];
|
||||
|
||||
|
@ -293,7 +306,7 @@ function _mapStateToProps(state, ownProps) {
|
|||
label: 'settings.devices',
|
||||
onMount: getAvailableDevices,
|
||||
props: getDeviceSelectionDialogProps(state, isDisplayedOnWelcomePage),
|
||||
propsUpdateFunction: (tabState, newProps) => {
|
||||
propsUpdateFunction: (tabState: any, newProps: any) => {
|
||||
// Ensure the device selection tab gets updated when new devices
|
||||
// are found by taking the new props and only preserving the
|
||||
// current user selected devices. If this were not done, the
|
||||
|
@ -308,7 +321,7 @@ function _mapStateToProps(state, ownProps) {
|
|||
};
|
||||
},
|
||||
styles: `settings-pane ${classes.settingsDialog} devices-pane`,
|
||||
submit: newState => submitDeviceSelectionTab(newState, isDisplayedOnWelcomePage)
|
||||
submit: (newState: any) => submitDeviceSelectionTab(newState, isDisplayedOnWelcomePage)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -329,7 +342,7 @@ function _mapStateToProps(state, ownProps) {
|
|||
component: ModeratorTab,
|
||||
label: 'settings.moderator',
|
||||
props: moderatorTabProps,
|
||||
propsUpdateFunction: (tabState, newProps) => {
|
||||
propsUpdateFunction: (tabState: any, newProps: any) => {
|
||||
// Updates tab props, keeping users selection
|
||||
|
||||
return {
|
||||
|
@ -371,7 +384,7 @@ function _mapStateToProps(state, ownProps) {
|
|||
component: MoreTab,
|
||||
label: 'settings.more',
|
||||
props: moreTabProps,
|
||||
propsUpdateFunction: (tabState, newProps) => {
|
||||
propsUpdateFunction: (tabState: any, newProps: any) => {
|
||||
// Updates tab props, keeping users selection
|
||||
|
||||
return {
|
|
@ -1,24 +1,30 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
|
||||
import { IState } from '../../../app/types';
|
||||
// @ts-ignore
|
||||
import { Dialog } from '../../../base/dialog';
|
||||
import { escapeRegexp } from '../../../base/util';
|
||||
import { escapeRegexp } from '../../../base/util/helpers';
|
||||
// @ts-ignore
|
||||
import { resetSearchCriteria, toggleFaceExpressions, initSearch } from '../../actions';
|
||||
import {
|
||||
DISPLAY_SWITCH_BREAKPOINT,
|
||||
MOBILE_BREAKPOINT,
|
||||
RESIZE_SEARCH_SWITCH_CONTAINER_BREAKPOINT
|
||||
// @ts-ignore
|
||||
} from '../../constants';
|
||||
|
||||
import FaceExpressionsSwitch from './FaceExpressionsSwitch';
|
||||
// @ts-ignore
|
||||
import SpeakerStatsLabels from './SpeakerStatsLabels';
|
||||
// @ts-ignore
|
||||
import SpeakerStatsList from './SpeakerStatsList';
|
||||
// @ts-ignore
|
||||
import SpeakerStatsSearch from './SpeakerStatsSearch';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
speakerStats: {
|
||||
'& .row': {
|
||||
|
@ -88,9 +94,9 @@ const useStyles = makeStyles(theme => {
|
|||
});
|
||||
|
||||
const SpeakerStats = () => {
|
||||
const { faceLandmarks } = useSelector(state => state['features/base/config']);
|
||||
const { showFaceExpressions } = useSelector(state => state['features/speaker-stats']);
|
||||
const { clientWidth } = useSelector(state => state['features/base/responsive-ui']);
|
||||
const { faceLandmarks } = useSelector((state: IState) => state['features/base/config']);
|
||||
const { showFaceExpressions } = useSelector((state: any) => state['features/speaker-stats']);
|
||||
const { clientWidth } = useSelector((state: IState) => state['features/base/responsive-ui']);
|
||||
const displaySwitch = faceLandmarks?.enableDisplayFaceExpressions && clientWidth > DISPLAY_SWITCH_BREAKPOINT;
|
||||
const displayLabels = clientWidth > MOBILE_BREAKPOINT;
|
||||
const dispatch = useDispatch();
|
|
@ -1,12 +1,12 @@
|
|||
/* @flow */
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
// @ts-ignore
|
||||
import { Tooltip } from '../../../base/tooltip';
|
||||
import { FACE_EXPRESSIONS_EMOJIS } from '../../../face-landmarks/constants';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
labels: {
|
||||
padding: '22px 0 7px 0',
|
||||
|
@ -34,22 +34,6 @@ type Props = {
|
|||
const SpeakerStatsLabels = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const classes = useStyles();
|
||||
const FaceExpressionsLabels = () => Object.keys(FACE_EXPRESSIONS_EMOJIS).map(
|
||||
expression => (
|
||||
<div
|
||||
className = 'expression'
|
||||
key = { expression }>
|
||||
<Tooltip
|
||||
content = { t(`speakerStats.${expression}`) }
|
||||
position = { 'top' } >
|
||||
<div>
|
||||
{ FACE_EXPRESSIONS_EMOJIS[expression] }
|
||||
</div>
|
||||
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
const nameTimeClass = `name-time${
|
||||
props.showFaceExpressions ? ' name-time_expressions-on' : ''
|
||||
}`;
|
||||
|
@ -69,7 +53,22 @@ const SpeakerStatsLabels = (props: Props) => {
|
|||
{
|
||||
props.showFaceExpressions
|
||||
&& <div className = { `expressions ${classes.emojis}` }>
|
||||
<FaceExpressionsLabels />
|
||||
{Object.keys(FACE_EXPRESSIONS_EMOJIS).map(
|
||||
expression => (
|
||||
<div
|
||||
className = 'expression'
|
||||
key = { expression }>
|
||||
<Tooltip
|
||||
content = { t(`speakerStats.${expression}`) }
|
||||
position = { 'top' } >
|
||||
<div>
|
||||
{FACE_EXPRESSIONS_EMOJIS[expression as keyof typeof FACE_EXPRESSIONS_EMOJIS]}
|
||||
</div>
|
||||
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
</div>
|
|
@ -1,14 +1,16 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import React from 'react';
|
||||
|
||||
// @ts-ignore
|
||||
import { MOBILE_BREAKPOINT } from '../../constants';
|
||||
// @ts-ignore
|
||||
import abstractSpeakerStatsList from '../AbstractSpeakerStatsList';
|
||||
|
||||
// @ts-ignore
|
||||
import SpeakerStatsItem from './SpeakerStatsItem';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
list: {
|
||||
marginTop: `${theme.spacing(3)}px`,
|
|
@ -1,17 +1,20 @@
|
|||
/* @flow */
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { IconSearch, Icon } from '../../../base/icons';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconSearch } from '../../../base/icons/svg/index';
|
||||
// @ts-ignore
|
||||
import { getFieldValue } from '../../../base/react';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.web';
|
||||
// @ts-ignore
|
||||
import { MOBILE_BREAKPOINT } from '../../constants';
|
||||
// @ts-ignore
|
||||
import { isSpeakerStatsSearchDisabled } from '../../functions';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
speakerStatsSearchContainer: {
|
||||
position: 'relative'
|
||||
|
@ -83,13 +86,13 @@ function SpeakerStatsSearch({ onSearch }: Props) {
|
|||
* @param {Object} evt - The static event.
|
||||
* @returns {void}
|
||||
*/
|
||||
const onChange = useCallback((evt: Event) => {
|
||||
const onChange = useCallback((evt: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = getFieldValue(evt);
|
||||
|
||||
setSearchValue(value);
|
||||
onSearch && onSearch(value);
|
||||
}, []);
|
||||
const preventDismiss = useCallback((evt: KeyboardEvent) => {
|
||||
const preventDismiss = useCallback((evt: React.KeyboardEvent) => {
|
||||
if (evt.key === 'Enter') {
|
||||
evt.preventDefault();
|
||||
}
|
||||
|
@ -103,7 +106,7 @@ function SpeakerStatsSearch({ onSearch }: Props) {
|
|||
<div className = { classes.speakerStatsSearchContainer }>
|
||||
<Icon
|
||||
className = { classes.searchIcon }
|
||||
color = { BaseTheme.palette.surface07 }
|
||||
color = { BaseTheme.palette.icon03 }
|
||||
src = { IconSearch } />
|
||||
<input
|
||||
autoComplete = 'off'
|
|
@ -1,22 +1,20 @@
|
|||
// @flow
|
||||
|
||||
import { makeStyles } from '@material-ui/core';
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { ReactElement, useCallback } from 'react';
|
||||
|
||||
import { DRAWER_MAX_HEIGHT } from '../../constants';
|
||||
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Class name for custom styles.
|
||||
*/
|
||||
className: string,
|
||||
|
||||
/**
|
||||
* The component(s) to be displayed within the drawer menu.
|
||||
*/
|
||||
children: React$Node,
|
||||
children: ReactElement,
|
||||
|
||||
/**
|
||||
* Class name for custom styles.
|
||||
*/
|
||||
className?: string,
|
||||
|
||||
/**
|
||||
* Whether the drawer should be shown or not.
|
||||
|
@ -29,7 +27,7 @@ type Props = {
|
|||
onClose: Function
|
||||
};
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
drawer: {
|
||||
backgroundColor: theme.palette.ui02,
|
|
@ -1,25 +1,30 @@
|
|||
/* @flow */
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import InlineDialog from '@atlaskit/inline-dialog';
|
||||
import { withStyles } from '@material-ui/styles';
|
||||
import React, { Component } from 'react';
|
||||
import React, { Component, ReactElement } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
// @ts-ignore
|
||||
import { createToolbarEvent, sendAnalytics } from '../../../analytics';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import { connect } from '../../../base/redux/functions';
|
||||
// @ts-ignore
|
||||
import { ReactionEmoji, ReactionsMenu } from '../../../reactions/components';
|
||||
import { type ReactionEmojiProps, REACTIONS_MENU_HEIGHT } from '../../../reactions/constants';
|
||||
import { getReactionsQueue } from '../../../reactions/functions.any';
|
||||
import { DRAWER_MAX_HEIGHT } from '../../constants';
|
||||
|
||||
// @ts-ignore
|
||||
import Drawer from './Drawer';
|
||||
// @ts-ignore
|
||||
import JitsiPortal from './JitsiPortal';
|
||||
// @ts-ignore
|
||||
import OverflowToggleButton from './OverflowToggleButton';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link OverflowMenuButton}.
|
||||
*/
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* ID of the menu that is controlled by this button.
|
||||
|
@ -29,12 +34,12 @@ type Props = {
|
|||
/**
|
||||
* A child React Element to display within {@code InlineDialog}.
|
||||
*/
|
||||
children: React$Node,
|
||||
children: ReactElement,
|
||||
|
||||
/**
|
||||
* An object containing the CSS classes.
|
||||
*/
|
||||
classes: Object,
|
||||
classes: any,
|
||||
|
||||
/**
|
||||
* Whether or not the OverflowMenu popover should display.
|
||||
|
@ -51,11 +56,6 @@ type Props = {
|
|||
*/
|
||||
overflowDrawer: boolean,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function,
|
||||
|
||||
/**
|
||||
* The array of reactions to be displayed.
|
||||
*/
|
||||
|
@ -65,7 +65,7 @@ type Props = {
|
|||
* Whether or not to display the reactions in the mobile menu.
|
||||
*/
|
||||
showMobileReactions: boolean
|
||||
};
|
||||
}
|
||||
|
||||
const styles = () => {
|
||||
return {
|
||||
|
@ -98,15 +98,13 @@ class OverflowMenuButton extends Component<Props> {
|
|||
this._onEscClick = this._onEscClick.bind(this);
|
||||
}
|
||||
|
||||
_onEscClick: (KeyboardEvent) => void;
|
||||
|
||||
/**
|
||||
* Click handler for the more actions entries.
|
||||
*
|
||||
* @param {KeyboardEvent} event - Esc key click to close the popup.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onEscClick(event) {
|
||||
_onEscClick(event: React.KeyboardEvent) {
|
||||
if (event.key === 'Escape' && this.props.isOpen) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
@ -136,10 +134,12 @@ class OverflowMenuButton extends Component<Props> {
|
|||
<Drawer
|
||||
isOpen = { isOpen }
|
||||
onClose = { this._onCloseDialog }>
|
||||
<div className = { classes.overflowMenuDrawer }>
|
||||
{children}
|
||||
</div>
|
||||
{showMobileReactions && <ReactionsMenu overflowMenu = { true } />}
|
||||
<>
|
||||
<div className = { classes.overflowMenuDrawer }>
|
||||
{children}
|
||||
</div>
|
||||
{showMobileReactions && <ReactionsMenu overflowMenu = { true } />}
|
||||
</>
|
||||
</Drawer>
|
||||
{showMobileReactions && <div className = 'reactions-animations-container'>
|
||||
{reactionsQueue.map(({ reaction, uid }, index) => (<ReactionEmoji
|
||||
|
@ -167,8 +167,6 @@ class OverflowMenuButton extends Component<Props> {
|
|||
);
|
||||
}
|
||||
|
||||
_onCloseDialog: () => void;
|
||||
|
||||
/**
|
||||
* Callback invoked when {@code InlineDialog} signals that it should be
|
||||
* close.
|
||||
|
@ -180,8 +178,6 @@ class OverflowMenuButton extends Component<Props> {
|
|||
this.props.onVisibilityChange(false);
|
||||
}
|
||||
|
||||
_toggleDialogVisibility: () => void;
|
||||
|
||||
/**
|
||||
* Callback invoked to signal that an event has occurred that should change
|
||||
* the visibility of the {@code InlineDialog} component.
|
||||
|
@ -203,7 +199,7 @@ class OverflowMenuButton extends Component<Props> {
|
|||
* @param {Object} state - The Redux state.
|
||||
* @returns {Props}
|
||||
*/
|
||||
function mapStateToProps(state) {
|
||||
function mapStateToProps(state: any) {
|
||||
const { overflowDrawer } = state['features/toolbox'];
|
||||
|
||||
return {
|
||||
|
@ -212,4 +208,5 @@ function mapStateToProps(state) {
|
|||
};
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export default withStyles(styles)(translate(connect(mapStateToProps)(OverflowMenuButton)));
|
|
@ -1,76 +1,109 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { batch } from 'react-redux';
|
||||
|
||||
// @ts-ignore
|
||||
import keyboardShortcut from '../../../../../modules/keyboardshortcut/keyboardshortcut';
|
||||
import {
|
||||
ACTION_SHORTCUT_TRIGGERED,
|
||||
createShortcutEvent,
|
||||
createToolbarEvent,
|
||||
sendAnalytics
|
||||
// @ts-ignore
|
||||
} from '../../../analytics';
|
||||
// @ts-ignore
|
||||
import { ContextMenu, ContextMenuItemGroup } from '../../../base/components';
|
||||
// @ts-ignore
|
||||
import { getMultipleVideoSendingSupportFeatureFlag, getToolbarButtons } from '../../../base/config';
|
||||
// @ts-ignore
|
||||
import { isToolbarButtonEnabled } from '../../../base/config/functions.web';
|
||||
// @ts-ignore
|
||||
import { openDialog, toggleDialog } from '../../../base/dialog';
|
||||
import { isIosMobileBrowser, isMobileBrowser } from '../../../base/environment/utils';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import JitsiMeetJS from '../../../base/lib-jitsi-meet';
|
||||
import {
|
||||
getLocalParticipant,
|
||||
hasRaisedHand,
|
||||
raiseHand
|
||||
} from '../../../base/participants';
|
||||
import { connect } from '../../../base/redux';
|
||||
} from '../../../base/participants/actions';
|
||||
import {
|
||||
getLocalParticipant,
|
||||
hasRaisedHand
|
||||
} from '../../../base/participants/functions';
|
||||
import { connect } from '../../../base/redux/functions';
|
||||
// @ts-ignore
|
||||
import { getLocalVideoTrack } from '../../../base/tracks';
|
||||
// @ts-ignore
|
||||
import { toggleChat } from '../../../chat';
|
||||
// @ts-ignore
|
||||
import { ChatButton } from '../../../chat/components';
|
||||
// @ts-ignore
|
||||
import { EmbedMeetingButton } from '../../../embed-meeting';
|
||||
// @ts-ignore
|
||||
import { SharedDocumentButton } from '../../../etherpad';
|
||||
// @ts-ignore
|
||||
import { FeedbackButton } from '../../../feedback';
|
||||
// @ts-ignore
|
||||
import { setGifMenuVisibility } from '../../../gifs/actions';
|
||||
// @ts-ignore
|
||||
import { isGifEnabled } from '../../../gifs/functions';
|
||||
// @ts-ignore
|
||||
import { InviteButton } from '../../../invite/components/add-people-dialog';
|
||||
// @ts-ignore
|
||||
import { isVpaasMeeting } from '../../../jaas/functions';
|
||||
// @ts-ignore
|
||||
import { KeyboardShortcutsButton } from '../../../keyboard-shortcuts';
|
||||
import { NoiseSuppressionButton } from '../../../noise-suppression/components';
|
||||
import {
|
||||
close as closeParticipantsPane,
|
||||
open as openParticipantsPane
|
||||
// @ts-ignore
|
||||
} from '../../../participants-pane/actions';
|
||||
// @ts-ignore
|
||||
import { ParticipantsPaneButton } from '../../../participants-pane/components/web';
|
||||
// @ts-ignore
|
||||
import { getParticipantsPaneOpen } from '../../../participants-pane/functions';
|
||||
import { addReactionToBuffer } from '../../../reactions/actions.any';
|
||||
import { toggleReactionsMenuVisibility } from '../../../reactions/actions.web';
|
||||
import { ReactionsMenuButton } from '../../../reactions/components';
|
||||
import ReactionsMenuButton from '../../../reactions/components/web/ReactionsMenuButton';
|
||||
import { REACTIONS } from '../../../reactions/constants';
|
||||
import { isReactionsEnabled } from '../../../reactions/functions.any';
|
||||
import {
|
||||
LiveStreamButton,
|
||||
RecordButton
|
||||
// @ts-ignore
|
||||
} from '../../../recording';
|
||||
// @ts-ignore
|
||||
import { isSalesforceEnabled } from '../../../salesforce/functions';
|
||||
import {
|
||||
isScreenAudioSupported,
|
||||
isScreenVideoShared,
|
||||
ShareAudioButton,
|
||||
startScreenShareFlow
|
||||
} from '../../../screen-share/';
|
||||
// @ts-ignore
|
||||
} from '../../../screen-share';
|
||||
// @ts-ignore
|
||||
import SecurityDialogButton from '../../../security/components/security-dialog/web/SecurityDialogButton';
|
||||
// @ts-ignore
|
||||
import { SettingsButton } from '../../../settings';
|
||||
// @ts-ignore
|
||||
import { SharedVideoButton } from '../../../shared-video/components';
|
||||
// @ts-ignore
|
||||
import { SpeakerStatsButton } from '../../../speaker-stats/components/web';
|
||||
import {
|
||||
ClosedCaptionButton
|
||||
// @ts-ignore
|
||||
} from '../../../subtitles';
|
||||
import {
|
||||
TileViewButton,
|
||||
shouldDisplayTileView,
|
||||
toggleTileView
|
||||
// @ts-ignore
|
||||
} from '../../../video-layout';
|
||||
// @ts-ignore
|
||||
import { VideoQualityDialog, VideoQualityButton } from '../../../video-quality/components';
|
||||
// @ts-ignore
|
||||
import { VideoBackgroundButton, toggleBackgroundEffect } from '../../../virtual-background';
|
||||
import { VIRTUAL_BACKGROUND_TYPE } from '../../../virtual-background/constants';
|
||||
import {
|
||||
|
@ -78,29 +111,45 @@ import {
|
|||
setOverflowMenuVisible,
|
||||
setToolbarHovered,
|
||||
showToolbox
|
||||
// @ts-ignore
|
||||
} from '../../actions';
|
||||
import { THRESHOLDS, NOT_APPLICABLE, NOTIFY_CLICK_MODE } from '../../constants';
|
||||
// @ts-ignore
|
||||
import { isDesktopShareButtonDisabled, isToolboxVisible } from '../../functions';
|
||||
// @ts-ignore
|
||||
import DownloadButton from '../DownloadButton';
|
||||
// @ts-ignore
|
||||
import HangupButton from '../HangupButton';
|
||||
// @ts-ignore
|
||||
import HelpButton from '../HelpButton';
|
||||
|
||||
// @ts-ignore
|
||||
import AudioSettingsButton from './AudioSettingsButton';
|
||||
// @ts-ignore
|
||||
import DockIframeButton from './DockIframeButton';
|
||||
// @ts-ignore
|
||||
import FullscreenButton from './FullscreenButton';
|
||||
// @ts-ignore
|
||||
import LinkToSalesforceButton from './LinkToSalesforceButton';
|
||||
// @ts-ignore
|
||||
import OverflowMenuButton from './OverflowMenuButton';
|
||||
// @ts-ignore
|
||||
import ProfileButton from './ProfileButton';
|
||||
// @ts-ignore
|
||||
import Separator from './Separator';
|
||||
// @ts-ignore
|
||||
import ShareDesktopButton from './ShareDesktopButton';
|
||||
// @ts-ignore
|
||||
import ToggleCameraButton from './ToggleCameraButton';
|
||||
// @ts-ignore
|
||||
import UndockIframeButton from './UndockIframeButton';
|
||||
// @ts-ignore
|
||||
import VideoSettingsButton from './VideoSettingsButton';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Toolbox}.
|
||||
*/
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* String showing if the virtual background type is desktop-share.
|
||||
|
@ -110,7 +159,10 @@ type Props = {
|
|||
/**
|
||||
* Toolbar buttons which have their click exposed through the API.
|
||||
*/
|
||||
_buttonsWithNotifyClick: Array<string | Object>,
|
||||
_buttonsWithNotifyClick: Array<string | {
|
||||
key: string;
|
||||
preventExecution: boolean;
|
||||
}>,
|
||||
|
||||
/**
|
||||
* Whether or not the chat feature is currently displayed.
|
||||
|
@ -248,39 +300,33 @@ type Props = {
|
|||
*/
|
||||
_toolbarButtons: Array<string>,
|
||||
|
||||
/**
|
||||
* Returns the selected virtual source object.
|
||||
*/
|
||||
_virtualSource: any,
|
||||
|
||||
/**
|
||||
* Flag showing whether toolbar is visible.
|
||||
*/
|
||||
_visible: boolean,
|
||||
|
||||
/**
|
||||
* Returns the selected virtual source object.
|
||||
*/
|
||||
_virtualSource: Object,
|
||||
|
||||
/**
|
||||
* An object containing the CSS classes.
|
||||
*/
|
||||
classes: Object,
|
||||
classes: any,
|
||||
|
||||
/**
|
||||
* Invoked to active other features of the app.
|
||||
*/
|
||||
dispatch: Function,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function,
|
||||
|
||||
/**
|
||||
* Explicitly passed array with the buttons which this Toolbox should display.
|
||||
*/
|
||||
toolbarButtons: Array<string>,
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
declare var APP: Object;
|
||||
declare let APP: any;
|
||||
|
||||
const styles = () => {
|
||||
return {
|
||||
|
@ -435,7 +481,7 @@ class Toolbox extends Component<Props> {
|
|||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
componentDidUpdate(prevProps) {
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
const { _dialog, dispatch } = this.props;
|
||||
|
||||
|
||||
|
@ -488,15 +534,13 @@ class Toolbox extends Component<Props> {
|
|||
);
|
||||
}
|
||||
|
||||
_onEscKey: (KeyboardEvent) => void;
|
||||
|
||||
/**
|
||||
* Key handler for overflow menu.
|
||||
*
|
||||
* @param {KeyboardEvent} e - Esc key click to close the popup.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onEscKey(e) {
|
||||
_onEscKey(e: React.KeyboardEvent) {
|
||||
if (e.key === 'Escape') {
|
||||
e.stopPropagation();
|
||||
this._closeOverflowMenuIfOpen();
|
||||
|
@ -870,9 +914,9 @@ class Toolbox extends Component<Props> {
|
|||
* @param {string} btnName - The toolbar button's name.
|
||||
* @returns {string|undefined} - The button's notify mode.
|
||||
*/
|
||||
_getButtonNotifyMode(btnName) {
|
||||
_getButtonNotifyMode(btnName: string) {
|
||||
const notify = this.props._buttonsWithNotifyClick?.find(
|
||||
(btn: string | Object) =>
|
||||
btn =>
|
||||
(typeof btn === 'string' && btn === btnName)
|
||||
|| (typeof btn === 'object' && btn.key === btnName)
|
||||
);
|
||||
|
@ -890,7 +934,7 @@ class Toolbox extends Component<Props> {
|
|||
* @param {Object} buttons - The list of toolbar buttons.
|
||||
* @returns {void}
|
||||
*/
|
||||
_setButtonsNotifyClickMode(buttons) {
|
||||
_setButtonsNotifyClickMode(buttons: Object) {
|
||||
if (typeof APP === 'undefined' || !this.props._buttonsWithNotifyClick?.length) {
|
||||
return;
|
||||
}
|
||||
|
@ -926,7 +970,7 @@ class Toolbox extends Component<Props> {
|
|||
const keys = Object.keys(buttons);
|
||||
|
||||
const filtered = [
|
||||
...order.map(key => buttons[key]),
|
||||
...order.map(key => buttons[key as keyof typeof buttons]),
|
||||
...Object.values(buttons).filter((button, index) => !order.includes(keys[index]))
|
||||
].filter(Boolean).filter(({ key, alias = NOT_APPLICABLE }) =>
|
||||
isToolbarButtonEnabled(key, _toolbarButtons) || isToolbarButtonEnabled(alias, _toolbarButtons));
|
||||
|
@ -946,8 +990,6 @@ class Toolbox extends Component<Props> {
|
|||
};
|
||||
}
|
||||
|
||||
_onMouseOut: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action signaling the toolbar is not being hovered.
|
||||
*
|
||||
|
@ -960,8 +1002,6 @@ class Toolbox extends Component<Props> {
|
|||
!_overflowMenuVisible && dispatch(setToolbarHovered(false));
|
||||
}
|
||||
|
||||
_onMouseOver: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action signaling the toolbar is being hovered.
|
||||
*
|
||||
|
@ -972,9 +1012,6 @@ class Toolbox extends Component<Props> {
|
|||
this.props.dispatch(setToolbarHovered(true));
|
||||
}
|
||||
|
||||
|
||||
_onSetOverflowVisible: (boolean) => void;
|
||||
|
||||
/**
|
||||
* Sets the visibility of the overflow menu.
|
||||
*
|
||||
|
@ -983,13 +1020,11 @@ class Toolbox extends Component<Props> {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onSetOverflowVisible(visible) {
|
||||
_onSetOverflowVisible(visible: boolean) {
|
||||
this.props.dispatch(setOverflowMenuVisible(visible));
|
||||
this.props.dispatch(setToolbarHovered(visible));
|
||||
}
|
||||
|
||||
_onShortcutToggleChat: () => void;
|
||||
|
||||
/**
|
||||
* Creates an analytics keyboard shortcut event and dispatches an action for
|
||||
* toggling the display of chat.
|
||||
|
@ -1007,15 +1042,13 @@ class Toolbox extends Component<Props> {
|
|||
// Checks if there was any text selected by the user.
|
||||
// Used for when we press simultaneously keys for copying
|
||||
// text messages from the chat board
|
||||
if (window.getSelection().toString() !== '') {
|
||||
if (window.getSelection()?.toString() !== '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._doToggleChat();
|
||||
}
|
||||
|
||||
_onShortcutToggleParticipantsPane: () => void;
|
||||
|
||||
/**
|
||||
* Creates an analytics keyboard shortcut event and dispatches an action for
|
||||
* toggling the display of the participants pane.
|
||||
|
@ -1033,8 +1066,6 @@ class Toolbox extends Component<Props> {
|
|||
this._onToolbarToggleParticipantsPane();
|
||||
}
|
||||
|
||||
_onShortcutToggleVideoQuality: () => void;
|
||||
|
||||
/**
|
||||
* Creates an analytics keyboard shortcut event and dispatches an action for
|
||||
* toggling the display of Video Quality.
|
||||
|
@ -1048,8 +1079,6 @@ class Toolbox extends Component<Props> {
|
|||
this._doToggleVideoQuality();
|
||||
}
|
||||
|
||||
_onShortcutToggleTileView: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action for toggling the tile view.
|
||||
*
|
||||
|
@ -1066,8 +1095,6 @@ class Toolbox extends Component<Props> {
|
|||
this._doToggleTileView();
|
||||
}
|
||||
|
||||
_onShortcutToggleFullScreen: () => void;
|
||||
|
||||
/**
|
||||
* Creates an analytics keyboard shortcut event and dispatches an action for
|
||||
* toggling full screen mode.
|
||||
|
@ -1085,8 +1112,6 @@ class Toolbox extends Component<Props> {
|
|||
this._doToggleFullScreen();
|
||||
}
|
||||
|
||||
_onShortcutToggleRaiseHand: () => void;
|
||||
|
||||
/**
|
||||
* Creates an analytics keyboard shortcut event and dispatches an action for
|
||||
* toggling raise hand.
|
||||
|
@ -1103,8 +1128,6 @@ class Toolbox extends Component<Props> {
|
|||
this._doToggleRaiseHand();
|
||||
}
|
||||
|
||||
_onShortcutToggleScreenshare: () => void;
|
||||
|
||||
/**
|
||||
* Creates an analytics keyboard shortcut event and dispatches an action for
|
||||
* toggling screensharing.
|
||||
|
@ -1127,7 +1150,6 @@ class Toolbox extends Component<Props> {
|
|||
this._doToggleScreenshare();
|
||||
}
|
||||
|
||||
_onTabIn: () => void;
|
||||
|
||||
/**
|
||||
* Toggle the toolbar visibility when tabbing into it.
|
||||
|
@ -1139,7 +1161,6 @@ class Toolbox extends Component<Props> {
|
|||
this.props.dispatch(showToolbox());
|
||||
}
|
||||
}
|
||||
_onToolbarToggleParticipantsPane: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action for toggling the participants pane.
|
||||
|
@ -1157,8 +1178,6 @@ class Toolbox extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
_onToolbarOpenVideoQuality: () => void;
|
||||
|
||||
/**
|
||||
* Creates an analytics toolbar event and dispatches an action for toggling
|
||||
* open the video quality dialog.
|
||||
|
@ -1172,8 +1191,6 @@ class Toolbox extends Component<Props> {
|
|||
this._doOpenVideoQuality();
|
||||
}
|
||||
|
||||
_onToolbarToggleChat: () => void;
|
||||
|
||||
/**
|
||||
* Creates an analytics toolbar event and dispatches an action for toggling
|
||||
* the display of chat.
|
||||
|
@ -1191,8 +1208,6 @@ class Toolbox extends Component<Props> {
|
|||
this._doToggleChat();
|
||||
}
|
||||
|
||||
_onToolbarToggleFullScreen: () => void;
|
||||
|
||||
/**
|
||||
* Creates an analytics toolbar event and dispatches an action for toggling
|
||||
* full screen mode.
|
||||
|
@ -1210,8 +1225,6 @@ class Toolbox extends Component<Props> {
|
|||
this._doToggleFullScreen();
|
||||
}
|
||||
|
||||
_onToolbarToggleRaiseHand: () => void;
|
||||
|
||||
/**
|
||||
* Creates an analytics toolbar event and dispatches an action for toggling
|
||||
* raise hand.
|
||||
|
@ -1227,8 +1240,6 @@ class Toolbox extends Component<Props> {
|
|||
this._doToggleRaiseHand();
|
||||
}
|
||||
|
||||
_onToolbarToggleScreenshare: () => void;
|
||||
|
||||
/**
|
||||
* Creates an analytics toolbar event and dispatches an action for toggling
|
||||
* screensharing.
|
||||
|
@ -1357,9 +1368,9 @@ class Toolbox extends Component<Props> {
|
|||
}
|
||||
|
||||
return acc;
|
||||
}, []).map(buttonGroup => (
|
||||
}, []).map((buttonGroup: any) => (
|
||||
<ContextMenuItemGroup key = { `group-${buttonGroup[0].group}` }>
|
||||
{buttonGroup.map(({ key, Content, ...rest }) => (
|
||||
{buttonGroup.map(({ key, Content, ...rest }: any) => (
|
||||
key !== 'raisehand' || !_reactionsEnabled)
|
||||
&& <Content
|
||||
{ ...rest }
|
||||
|
@ -1394,7 +1405,7 @@ class Toolbox extends Component<Props> {
|
|||
* @private
|
||||
* @returns {{}}
|
||||
*/
|
||||
function _mapStateToProps(state, ownProps) {
|
||||
function _mapStateToProps(state: any, ownProps: Partial<Props>) {
|
||||
const { conference } = state['features/base/conference'];
|
||||
const {
|
||||
buttonsWithNotifyClick,
|
||||
|
@ -1447,4 +1458,5 @@ function _mapStateToProps(state, ownProps) {
|
|||
};
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export default translate(connect(_mapStateToProps)(withStyles(styles)(Toolbox)));
|
|
@ -1,28 +1,44 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { IState } from '../../../app/types';
|
||||
// @ts-ignore
|
||||
import { isSupported as isAvModerationSupported } from '../../../av-moderation/functions';
|
||||
// @ts-ignore
|
||||
import { Avatar } from '../../../base/avatar';
|
||||
// @ts-ignore
|
||||
import ContextMenu from '../../../base/components/context-menu/ContextMenu';
|
||||
// @ts-ignore
|
||||
import ContextMenuItemGroup from '../../../base/components/context-menu/ContextMenuItemGroup';
|
||||
import { isIosMobileBrowser, isMobileBrowser } from '../../../base/environment/utils';
|
||||
import { IconShareVideo } from '../../../base/icons';
|
||||
import { MEDIA_TYPE } from '../../../base/media';
|
||||
import { getLocalParticipant, PARTICIPANT_ROLE } from '../../../base/participants';
|
||||
import { IconShareVideo } from '../../../base/icons/svg/index';
|
||||
import { MEDIA_TYPE } from '../../../base/media/constants';
|
||||
import { PARTICIPANT_ROLE } from '../../../base/participants/constants';
|
||||
import { getLocalParticipant } from '../../../base/participants/functions';
|
||||
import { Participant } from '../../../base/participants/reducer';
|
||||
// @ts-ignore
|
||||
import { isParticipantAudioMuted } from '../../../base/tracks';
|
||||
// @ts-ignore
|
||||
import { getBreakoutRooms, getCurrentRoomId, isInBreakoutRoom } from '../../../breakout-rooms/functions';
|
||||
// @ts-ignore
|
||||
import { setVolume } from '../../../filmstrip/actions.web';
|
||||
// @ts-ignore
|
||||
import { isStageFilmstripAvailable } from '../../../filmstrip/functions.web';
|
||||
// @ts-ignore
|
||||
import { isForceMuted } from '../../../participants-pane/functions';
|
||||
// @ts-ignore
|
||||
import { requestRemoteControl, stopController } from '../../../remote-control';
|
||||
// @ts-ignore
|
||||
import { stopSharedVideo } from '../../../shared-video/actions.any';
|
||||
// @ts-ignore
|
||||
import { showOverflowDrawer } from '../../../toolbox/functions.web';
|
||||
|
||||
// @ts-ignore
|
||||
import { REMOTE_CONTROL_MENU_STATES } from './RemoteControlButton';
|
||||
// @ts-ignore
|
||||
import SendToRoomButton from './SendToRoomButton';
|
||||
|
||||
import {
|
||||
|
@ -38,6 +54,7 @@ import {
|
|||
RemoteControlButton,
|
||||
TogglePinToStageButton,
|
||||
VolumeSlider
|
||||
// @ts-ignore
|
||||
} from './';
|
||||
|
||||
type Props = {
|
||||
|
@ -56,7 +73,10 @@ type Props = {
|
|||
* The participant for which the drawer is open.
|
||||
* It contains the displayName & participantID.
|
||||
*/
|
||||
drawerParticipant?: Object,
|
||||
drawerParticipant?: {
|
||||
displayName: string;
|
||||
participantID: string;
|
||||
},
|
||||
|
||||
/**
|
||||
* Shared video local participant owner.
|
||||
|
@ -86,7 +106,7 @@ type Props = {
|
|||
/**
|
||||
* Participant reference.
|
||||
*/
|
||||
participant: Object,
|
||||
participant: Participant,
|
||||
|
||||
/**
|
||||
* The current state of the participant's remote control session.
|
||||
|
@ -96,10 +116,10 @@ type Props = {
|
|||
/**
|
||||
* Whether or not the menu is displayed in the thumbnail remote video menu.
|
||||
*/
|
||||
thumbnailMenu: ?boolean
|
||||
thumbnailMenu?: boolean
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
text: {
|
||||
color: theme.palette.text02,
|
||||
|
@ -139,9 +159,9 @@ const ParticipantContextMenu = ({
|
|||
const _isAudioMuted = useSelector(state => isParticipantAudioMuted(participant, state));
|
||||
const _overflowDrawer = useSelector(showOverflowDrawer);
|
||||
const { remoteVideoMenu = {}, disableRemoteMute, startSilent }
|
||||
= useSelector(state => state['features/base/config']);
|
||||
= useSelector((state: IState) => state['features/base/config']);
|
||||
const { disableKick, disableGrantModerator, disablePrivateChat } = remoteVideoMenu;
|
||||
const { participantsVolume } = useSelector(state => state['features/filmstrip']);
|
||||
const { participantsVolume } = useSelector((state: any) => state['features/filmstrip']);
|
||||
const _volume = (participant?.local ?? true ? undefined
|
||||
: participant?.id ? participantsVolume[participant?.id] : undefined) ?? 1;
|
||||
const isBreakoutRoom = useSelector(isInBreakoutRoom);
|
||||
|
@ -149,7 +169,7 @@ const ParticipantContextMenu = ({
|
|||
const stageFilmstrip = useSelector(isStageFilmstripAvailable);
|
||||
|
||||
const _currentRoomId = useSelector(getCurrentRoomId);
|
||||
const _rooms = Object.values(useSelector(getBreakoutRooms));
|
||||
const _rooms: Array<{id: string}> = Object.values(useSelector(getBreakoutRooms));
|
||||
|
||||
const _onVolumeChange = useCallback(value => {
|
||||
dispatch(setVolume(participant.id, value));
|
||||
|
@ -273,10 +293,10 @@ const ParticipantContextMenu = ({
|
|||
);
|
||||
}
|
||||
|
||||
const breakoutRoomsButtons = [];
|
||||
const breakoutRoomsButtons: any = [];
|
||||
|
||||
if (!thumbnailMenu && _isModerator) {
|
||||
_rooms.forEach((room: Object) => {
|
||||
_rooms.forEach(room => {
|
||||
if (room.id !== _currentRoomId) {
|
||||
breakoutRoomsButtons.push(
|
||||
<SendToRoomButton
|
|
@ -9,6 +9,7 @@ import { isMobileBrowser } from '../../../base/environment/utils';
|
|||
import { translate } from '../../../base/i18n';
|
||||
import { IconHorizontalPoints } from '../../../base/icons/svg/index';
|
||||
import { getParticipantById } from '../../../base/participants/functions';
|
||||
import { Participant } from '../../../base/participants/reducer';
|
||||
// @ts-ignore
|
||||
import { Popover } from '../../../base/popover';
|
||||
// @ts-ignore
|
||||
|
@ -57,7 +58,7 @@ interface Props extends WithTranslation {
|
|||
/**
|
||||
* Participant reference.
|
||||
*/
|
||||
_participant: Object,
|
||||
_participant: Participant,
|
||||
|
||||
/**
|
||||
* The ID for the participant on which the remote video menu will act.
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
/* @flow */
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { withStyles } from '@material-ui/styles';
|
||||
import clsx from 'clsx';
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { Icon, IconVolume } from '../../../base/icons';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconVolume } from '../../../base/icons/svg/index';
|
||||
// @ts-ignore
|
||||
import { VOLUME_SLIDER_SCALE } from '../../constants';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link VolumeSlider}.
|
||||
*/
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* An object containing the CSS classes.
|
||||
*/
|
||||
classes: Object,
|
||||
classes: any,
|
||||
|
||||
/**
|
||||
* The value of the audio slider should display at when the component first
|
||||
|
@ -28,13 +30,8 @@ type Props = {
|
|||
/**
|
||||
* The callback to invoke when the audio slider value changes.
|
||||
*/
|
||||
onChange: Function,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
onChange: Function
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link VolumeSlider}.
|
||||
|
@ -48,7 +45,7 @@ type State = {
|
|||
volumeLevel: number
|
||||
};
|
||||
|
||||
const styles = theme => {
|
||||
const styles = (theme: any) => {
|
||||
return {
|
||||
container: {
|
||||
minHeight: '40px',
|
||||
|
@ -116,7 +113,7 @@ class VolumeSlider extends Component<Props, State> {
|
|||
* @param {MouseEvent} e - Click event.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onClick(e) {
|
||||
_onClick(e: React.MouseEvent) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
|
@ -156,8 +153,6 @@ class VolumeSlider extends Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
_onVolumeChange: (Object) => void;
|
||||
|
||||
/**
|
||||
* Sets the internal state of the volume level for the volume slider.
|
||||
* Invokes the prop onVolumeChange to notify of volume changes.
|
||||
|
@ -166,12 +161,13 @@ class VolumeSlider extends Component<Props, State> {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onVolumeChange(event) {
|
||||
const volumeLevel = event.currentTarget.value;
|
||||
_onVolumeChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
const volumeLevel = Number(event.currentTarget.value);
|
||||
|
||||
this.props.onChange(volumeLevel / VOLUME_SLIDER_SCALE);
|
||||
this.setState({ volumeLevel });
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export default translate(withStyles(styles)(VolumeSlider));
|
|
@ -1,4 +1,3 @@
|
|||
// @flow
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
|
@ -25,7 +24,7 @@ type Props = {
|
|||
/**
|
||||
* Callback invoked on change.
|
||||
*/
|
||||
onChange: Function,
|
||||
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void,
|
||||
|
||||
/**
|
||||
* The granularity that the value must adhere to.
|
||||
|
@ -38,7 +37,7 @@ type Props = {
|
|||
value: number
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
// keep the same height for all elements:
|
||||
// input, input track & fake track(div)
|
||||
const height = 6;
|
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
|||
|
||||
import { Dialog } from '../../base/dialog';
|
||||
|
||||
import VideoQualitySlider from './VideoQualitySlider';
|
||||
import VideoQualitySlider from './VideoQualitySlider.web';
|
||||
|
||||
/**
|
||||
* Implements a React {@link Component} which displays the component
|
||||
|
|
|
@ -1,17 +1,24 @@
|
|||
// @flow
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import clsx from 'clsx';
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import type { Dispatch } from 'redux';
|
||||
|
||||
// @ts-ignore
|
||||
import { createToolbarEvent, sendAnalytics } from '../../analytics';
|
||||
// @ts-ignore
|
||||
import { setAudioOnly } from '../../base/audio-only';
|
||||
import { translate } from '../../base/i18n';
|
||||
import { translate } from '../../base/i18n/functions';
|
||||
// @ts-ignore
|
||||
import { setLastN, getLastNForQualityLevel } from '../../base/lastn';
|
||||
import { connect } from '../../base/redux';
|
||||
import { connect } from '../../base/redux/functions';
|
||||
import { withPixelLineHeight } from '../../base/styles/functions.web';
|
||||
// @ts-ignore
|
||||
import { setPreferredVideoQuality } from '../actions';
|
||||
// @ts-ignore
|
||||
import { DEFAULT_LAST_N, VIDEO_QUALITY_LEVELS } from '../constants';
|
||||
// @ts-ignore
|
||||
import logger from '../logger';
|
||||
|
||||
import Slider from './Slider';
|
||||
|
@ -31,7 +38,7 @@ const {
|
|||
* @returns {Object} The event in a format suitable for sending via
|
||||
* sendAnalytics.
|
||||
*/
|
||||
const createEvent = function(quality) {
|
||||
const createEvent = function(quality: string) {
|
||||
return createToolbarEvent(
|
||||
'video.quality',
|
||||
{
|
||||
|
@ -42,7 +49,7 @@ const createEvent = function(quality) {
|
|||
/**
|
||||
* The type of the React {@code Component} props of {@link VideoQualitySlider}.
|
||||
*/
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Whether or not the conference is in audio only mode.
|
||||
|
@ -65,22 +72,16 @@ type Props = {
|
|||
*/
|
||||
_sendrecvVideoQuality: Number,
|
||||
|
||||
/**
|
||||
/**
|
||||
* An object containing the CSS classes.
|
||||
*/
|
||||
classes: Object,
|
||||
classes: any,
|
||||
|
||||
/**
|
||||
* Invoked to request toggling of audio only mode.
|
||||
*/
|
||||
dispatch: Dispatch<any>,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
dispatch: Dispatch<any>
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the styles for the component.
|
||||
|
@ -89,7 +90,7 @@ type Props = {
|
|||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
const styles = theme => {
|
||||
const styles = (theme: any) => {
|
||||
return {
|
||||
dialog: {
|
||||
color: theme.palette.text01
|
||||
|
@ -128,7 +129,7 @@ class VideoQualitySlider extends Component<Props> {
|
|||
* @param {Object} props - The read-only React Component props with which
|
||||
* the new instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
|
@ -203,8 +204,6 @@ class VideoQualitySlider extends Component<Props> {
|
|||
);
|
||||
}
|
||||
|
||||
_enableAudioOnly: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action to enable audio only mode.
|
||||
*
|
||||
|
@ -217,8 +216,6 @@ class VideoQualitySlider extends Component<Props> {
|
|||
this.props.dispatch(setAudioOnly(true));
|
||||
}
|
||||
|
||||
_enableHighDefinition: () => void;
|
||||
|
||||
/**
|
||||
* Handles the action of the high definition video being selected.
|
||||
* Dispatches an action to receive high quality video from remote
|
||||
|
@ -233,8 +230,6 @@ class VideoQualitySlider extends Component<Props> {
|
|||
this._setPreferredVideoQuality(HIGH);
|
||||
}
|
||||
|
||||
_enableLowDefinition: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action to receive low quality video from remote
|
||||
* participants.
|
||||
|
@ -248,8 +243,6 @@ class VideoQualitySlider extends Component<Props> {
|
|||
this._setPreferredVideoQuality(LOW);
|
||||
}
|
||||
|
||||
_enableStandardDefinition: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action to receive standard quality video from remote
|
||||
* participants.
|
||||
|
@ -263,8 +256,6 @@ class VideoQualitySlider extends Component<Props> {
|
|||
this._setPreferredVideoQuality(STANDARD);
|
||||
}
|
||||
|
||||
_enableUltraHighDefinition: () => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action to receive ultra HD quality video from remote
|
||||
* participants.
|
||||
|
@ -291,12 +282,14 @@ class VideoQualitySlider extends Component<Props> {
|
|||
|
||||
if (_audioOnly) {
|
||||
const audioOnlyOption = _sliderOptions.find(
|
||||
({ audioOnly }) => audioOnly);
|
||||
({ audioOnly }: any) => audioOnly);
|
||||
|
||||
// @ts-ignore
|
||||
return _sliderOptions.indexOf(audioOnlyOption);
|
||||
}
|
||||
|
||||
for (let i = 0; i < _sliderOptions.length; i++) {
|
||||
// @ts-ignore
|
||||
if (_sliderOptions[i].videoQuality >= _sendrecvVideoQuality) {
|
||||
return i;
|
||||
}
|
||||
|
@ -305,8 +298,6 @@ class VideoQualitySlider extends Component<Props> {
|
|||
return -1;
|
||||
}
|
||||
|
||||
_onSliderChange: () => void;
|
||||
|
||||
/**
|
||||
* Invokes a callback when the selected video quality changes.
|
||||
*
|
||||
|
@ -314,13 +305,16 @@ class VideoQualitySlider extends Component<Props> {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onSliderChange(event) {
|
||||
_onSliderChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
const { _audioOnly, _sendrecvVideoQuality } = this.props;
|
||||
const {
|
||||
// @ts-ignore
|
||||
audioOnly,
|
||||
// @ts-ignore
|
||||
onSelect,
|
||||
// @ts-ignore
|
||||
videoQuality
|
||||
} = this._sliderOptions[event.target.value];
|
||||
} = this._sliderOptions[event.target.value as keyof typeof this._sliderOptions];
|
||||
|
||||
// Take no action if the newly chosen option does not change audio only
|
||||
// or video quality state.
|
||||
|
@ -341,7 +335,7 @@ class VideoQualitySlider extends Component<Props> {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setPreferredVideoQuality(qualityLevel) {
|
||||
_setPreferredVideoQuality(qualityLevel: number) {
|
||||
this.props.dispatch(setPreferredVideoQuality(qualityLevel));
|
||||
if (this.props._audioOnly) {
|
||||
this.props.dispatch(setAudioOnly(false));
|
||||
|
@ -366,7 +360,7 @@ class VideoQualitySlider extends Component<Props> {
|
|||
* @private
|
||||
* @returns {Props}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
function _mapStateToProps(state: any) {
|
||||
const { enabled: audioOnly } = state['features/base/audio-only'];
|
||||
const { p2p } = state['features/base/conference'];
|
||||
const { preferredVideoQuality } = state['features/video-quality'];
|
|
@ -1,16 +1,19 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { Icon, IconPlusCircle } from '../../base/icons';
|
||||
import { translate } from '../../base/i18n/functions';
|
||||
import Icon from '../../base/icons/components/Icon';
|
||||
import { IconPlusCircle } from '../../base/icons/svg/index';
|
||||
import { VIRTUAL_BACKGROUND_TYPE, type Image } from '../constants';
|
||||
// @ts-ignore
|
||||
import { resizeImage } from '../functions';
|
||||
// @ts-ignore
|
||||
import logger from '../logger';
|
||||
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Callback used to set the 'loading' state of the parent component.
|
||||
|
@ -27,23 +30,19 @@ type Props = {
|
|||
*/
|
||||
setStoredImages: Function,
|
||||
|
||||
/**
|
||||
* A list of images locally stored.
|
||||
*/
|
||||
storedImages: Array<Image>,
|
||||
|
||||
/**
|
||||
* If a label should be displayed alongside the button.
|
||||
*/
|
||||
showLabel: boolean,
|
||||
|
||||
/**
|
||||
* Used for translation.
|
||||
* A list of images locally stored.
|
||||
*/
|
||||
t: Function
|
||||
storedImages: Array<Image>
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
// @ts-ignore
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
addBackground: {
|
||||
marginRight: `${theme.spacing(2)}px`
|
||||
|
@ -80,7 +79,7 @@ function UploadImageButton({
|
|||
t
|
||||
}: Props) {
|
||||
const classes = useStyles();
|
||||
const uploadImageButton: Object = useRef(null);
|
||||
const uploadImageButton = useRef<HTMLInputElement>(null);
|
||||
const uploadImageKeyPress = useCallback(e => {
|
||||
if (uploadImageButton.current && (e.key === ' ' || e.key === 'Enter')) {
|
||||
e.preventDefault();
|
|
@ -1,34 +1,49 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import Spinner from '@atlaskit/spinner';
|
||||
// @ts-ignore
|
||||
import Bourne from '@hapi/bourne';
|
||||
// @ts-ignore
|
||||
import { jitsiLocalStorage } from '@jitsi/js-utils/jitsi-local-storage';
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import clsx from 'clsx';
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { IState } from '../../app/types';
|
||||
// @ts-ignore
|
||||
import { getMultipleVideoSendingSupportFeatureFlag } from '../../base/config';
|
||||
// @ts-ignore
|
||||
import { Dialog, hideDialog, openDialog } from '../../base/dialog';
|
||||
import { translate } from '../../base/i18n';
|
||||
import { Icon, IconCloseSmall, IconShareDesktop } from '../../base/icons';
|
||||
import { translate } from '../../base/i18n/functions';
|
||||
import Icon from '../../base/icons/components/Icon';
|
||||
import { IconCloseSmall, IconShareDesktop } from '../../base/icons/svg/index';
|
||||
import { browser, JitsiTrackErrors } from '../../base/lib-jitsi-meet';
|
||||
// @ts-ignore
|
||||
import { createLocalTrack } from '../../base/lib-jitsi-meet/functions';
|
||||
import { VIDEO_TYPE } from '../../base/media';
|
||||
import { connect } from '../../base/redux';
|
||||
import { VIDEO_TYPE } from '../../base/media/constants';
|
||||
import { connect } from '../../base/redux/functions';
|
||||
// @ts-ignore
|
||||
import { updateSettings } from '../../base/settings';
|
||||
// @ts-ignore
|
||||
import { Tooltip } from '../../base/tooltip';
|
||||
// @ts-ignore
|
||||
import { getLocalVideoTrack } from '../../base/tracks';
|
||||
// @ts-ignore
|
||||
import { NOTIFICATION_TIMEOUT_TYPE, showErrorNotification } from '../../notifications';
|
||||
// @ts-ignore
|
||||
import { toggleBackgroundEffect, virtualBackgroundTrackChanged } from '../actions';
|
||||
import { IMAGES, BACKGROUNDS_LIMIT, VIRTUAL_BACKGROUND_TYPE, type Image } from '../constants';
|
||||
// @ts-ignore
|
||||
import { toDataURL } from '../functions';
|
||||
// @ts-ignore
|
||||
import logger from '../logger';
|
||||
|
||||
import UploadImageButton from './UploadImageButton';
|
||||
// @ts-ignore
|
||||
import VirtualBackgroundPreview from './VirtualBackgroundPreview';
|
||||
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* The list of Images to choose from.
|
||||
|
@ -63,7 +78,7 @@ type Props = {
|
|||
/**
|
||||
* Returns the selected virtual background object.
|
||||
*/
|
||||
_virtualBackground: Object,
|
||||
_virtualBackground: any,
|
||||
|
||||
/**
|
||||
* The redux {@code dispatch} function.
|
||||
|
@ -76,15 +91,10 @@ type Props = {
|
|||
* NOTE: currently used only for electron in order to open the dialog in the correct state after desktop sharing
|
||||
* selection.
|
||||
*/
|
||||
initialOptions: Object,
|
||||
initialOptions: Object
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
const onError = event => {
|
||||
const onError = (event: any) => {
|
||||
event.target.style.display = 'none';
|
||||
};
|
||||
|
||||
|
@ -97,7 +107,7 @@ const onError = event => {
|
|||
* @private
|
||||
* @returns {{Props}}
|
||||
*/
|
||||
function _mapStateToProps(state): Object {
|
||||
function _mapStateToProps(state: any): Object {
|
||||
const { localFlipX } = state['features/base/settings'];
|
||||
const dynamicBrandingImages = state['features/dynamic-branding'].virtualBackgrounds;
|
||||
const hasBrandingImages = Boolean(dynamicBrandingImages.length);
|
||||
|
@ -115,7 +125,7 @@ function _mapStateToProps(state): Object {
|
|||
|
||||
const VirtualBackgroundDialog = translate(connect(_mapStateToProps)(VirtualBackground));
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
container: {
|
||||
display: 'flex',
|
||||
|
@ -131,6 +141,7 @@ const useStyles = makeStyles(theme => {
|
|||
gridTemplateColumns: 'auto auto auto auto auto',
|
||||
columnGap: '9px',
|
||||
cursor: 'pointer',
|
||||
// @ts-ignore
|
||||
[[ '& .desktop-share:hover',
|
||||
'& .thumbnail:hover',
|
||||
'& .blur:hover',
|
||||
|
@ -217,6 +228,7 @@ const useStyles = makeStyles(theme => {
|
|||
gridTemplateColumns: 'auto auto auto auto auto',
|
||||
fontSize: '1.5vw',
|
||||
|
||||
// @ts-ignore
|
||||
[[ '& .desktop-share:hover',
|
||||
'& .thumbnail:hover',
|
||||
'& .blur:hover',
|
||||
|
@ -226,6 +238,7 @@ const useStyles = makeStyles(theme => {
|
|||
width: '60px'
|
||||
},
|
||||
|
||||
// @ts-ignore
|
||||
[[ '& .desktop-share',
|
||||
'& .virtual-background-none,',
|
||||
'& .thumbnail,',
|
||||
|
@ -234,6 +247,7 @@ const useStyles = makeStyles(theme => {
|
|||
height: '60px',
|
||||
width: '60px'
|
||||
},
|
||||
// @ts-ignore
|
||||
[[ '& .desktop-share-selected',
|
||||
'& .thumbnail-selected',
|
||||
'& .none-selected',
|
||||
|
@ -282,11 +296,11 @@ function VirtualBackground({
|
|||
}: Props) {
|
||||
const classes = useStyles();
|
||||
const [ previewIsLoaded, setPreviewIsLoaded ] = useState(false);
|
||||
const [ options, setOptions ] = useState({ ...initialOptions });
|
||||
const [ options, setOptions ] = useState<any>({ ...initialOptions });
|
||||
const localImages = jitsiLocalStorage.getItem('virtualBackgrounds');
|
||||
const [ storedImages, setStoredImages ] = useState<Array<Image>>((localImages && Bourne.parse(localImages)) || []);
|
||||
const [ loading, setLoading ] = useState(false);
|
||||
let { disableScreensharingVirtualBackground } = useSelector(state => state['features/base/config']);
|
||||
let { disableScreensharingVirtualBackground } = useSelector((state: IState) => state['features/base/config']);
|
||||
|
||||
// Disable screenshare as virtual background in multi-stream mode.
|
||||
disableScreensharingVirtualBackground = disableScreensharingVirtualBackground || _multiStreamModeEnabled;
|
||||
|
@ -369,7 +383,7 @@ function VirtualBackground({
|
|||
|
||||
try {
|
||||
url = await createLocalTrack('desktop', '');
|
||||
} catch (e) {
|
||||
} catch (e: any) {
|
||||
if (e.name === JitsiTrackErrors.SCREENSHARING_USER_CANCELED) {
|
||||
isCancelled = true;
|
||||
} else {
|
||||
|
@ -526,11 +540,11 @@ function VirtualBackground({
|
|||
blurValue: initialVirtualBackground.blurValue
|
||||
});
|
||||
dispatch(hideDialog());
|
||||
});
|
||||
}, []);
|
||||
|
||||
const loadedPreviewState = useCallback(async loaded => {
|
||||
await setPreviewIsLoaded(loaded);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
|
@ -546,6 +560,7 @@ function VirtualBackground({
|
|||
{loading ? (
|
||||
<div className = { classes.virtualBackgroundLoading }>
|
||||
<Spinner
|
||||
// @ts-ignore
|
||||
isCompleting = { false }
|
||||
size = 'medium' />
|
||||
</div>
|
||||
|
@ -561,7 +576,7 @@ function VirtualBackground({
|
|||
<div
|
||||
className = { clsx(classes.dialog, { [classes.dialogMarginTop]: previewIsLoaded }) }
|
||||
role = 'radiogroup'
|
||||
tabIndex = '-1'>
|
||||
tabIndex = { -1 }>
|
||||
<Tooltip
|
||||
content = { t('virtualBackground.removeBackground') }
|
||||
position = { 'top' }>
|
|
@ -1,21 +1,32 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import Spinner from '@atlaskit/spinner';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { IState } from '../../app/types';
|
||||
// @ts-ignore
|
||||
import { hideDialog } from '../../base/dialog';
|
||||
// @ts-ignore
|
||||
import { translate } from '../../base/i18n';
|
||||
import { VIDEO_TYPE } from '../../base/media';
|
||||
// @ts-ignore
|
||||
import Video from '../../base/media/components/Video';
|
||||
import { connect, equals } from '../../base/redux';
|
||||
import { VIDEO_TYPE } from '../../base/media/constants';
|
||||
import { connect, equals } from '../../base/redux/functions';
|
||||
// @ts-ignore
|
||||
import { getCurrentCameraDeviceId } from '../../base/settings';
|
||||
// @ts-ignore
|
||||
import { createLocalTracksF } from '../../base/tracks/functions';
|
||||
// @ts-ignore
|
||||
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications';
|
||||
// @ts-ignore
|
||||
import { showWarningNotification } from '../../notifications/actions';
|
||||
// @ts-ignore
|
||||
import { toggleBackgroundEffect } from '../actions';
|
||||
import { VIRTUAL_BACKGROUND_TYPE } from '../constants';
|
||||
// @ts-ignore
|
||||
import { localTrackStopped } from '../functions';
|
||||
// @ts-ignore
|
||||
import logger from '../logger';
|
||||
|
||||
const videoClassName = 'video-preview-video';
|
||||
|
@ -23,7 +34,7 @@ const videoClassName = 'video-preview-video';
|
|||
/**
|
||||
* The type of the React {@code PureComponent} props of {@link VirtualBackgroundPreview}.
|
||||
*/
|
||||
export type Props = {
|
||||
export type Props = WithTranslation & {
|
||||
|
||||
/**
|
||||
* The deviceId of the camera device currently being used.
|
||||
|
@ -33,7 +44,7 @@ export type Props = {
|
|||
/**
|
||||
* An object containing the CSS classes.
|
||||
*/
|
||||
classes: Object,
|
||||
classes: any,
|
||||
|
||||
/**
|
||||
* The redux {@code dispatch} function.
|
||||
|
@ -48,12 +59,7 @@ export type Props = {
|
|||
/**
|
||||
* Represents the virtual background set options.
|
||||
*/
|
||||
options: Object,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
options: any
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -61,6 +67,11 @@ export type Props = {
|
|||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Activate the selected device camera only.
|
||||
*/
|
||||
jitsiTrack: Object|null,
|
||||
|
||||
/**
|
||||
* Loader activated on setting virtual background.
|
||||
*/
|
||||
|
@ -69,12 +80,7 @@ type State = {
|
|||
/**
|
||||
* Flag that indicates if the local track was loaded.
|
||||
*/
|
||||
localTrackLoaded: boolean,
|
||||
|
||||
/**
|
||||
* Activate the selected device camera only.
|
||||
*/
|
||||
jitsiTrack: Object
|
||||
localTrackLoaded: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -84,7 +90,7 @@ type State = {
|
|||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
const styles = theme => {
|
||||
const styles = (theme: any) => {
|
||||
return {
|
||||
virtualBackgroundPreview: {
|
||||
'& .video-preview': {
|
||||
|
@ -141,7 +147,7 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
|
|||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
|
@ -157,7 +163,7 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
|
|||
* @param {Object} jitsiTrack - The track that needs to be disposed.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
_stopStream(jitsiTrack) {
|
||||
_stopStream(jitsiTrack: any) {
|
||||
if (jitsiTrack) {
|
||||
jitsiTrack.dispose();
|
||||
}
|
||||
|
@ -231,6 +237,7 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
|
|||
return (
|
||||
<div className = 'video-preview-loader'>
|
||||
<Spinner
|
||||
// @ts-ignore
|
||||
invertColor = { true }
|
||||
isCompleting = { false }
|
||||
size = { 'large' } />
|
||||
|
@ -244,7 +251,7 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
|
|||
* @param {Object} data - The track data.
|
||||
* @returns {React$Node}
|
||||
*/
|
||||
_renderPreviewEntry(data) {
|
||||
_renderPreviewEntry(data: Object) {
|
||||
const { t } = this.props;
|
||||
const className = 'video-background-preview-entry';
|
||||
|
||||
|
@ -298,7 +305,7 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
|
|||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
async componentDidUpdate(prevProps) {
|
||||
async componentDidUpdate(prevProps: Props) {
|
||||
if (!equals(this.props._currentCameraDeviceId, prevProps._currentCameraDeviceId)) {
|
||||
this._setTracks();
|
||||
}
|
||||
|
@ -338,7 +345,7 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
|
|||
* @private
|
||||
* @returns {{Props}}
|
||||
*/
|
||||
function _mapStateToProps(state): Object {
|
||||
function _mapStateToProps(state: IState): Object {
|
||||
return {
|
||||
_currentCameraDeviceId: getCurrentCameraDeviceId(state)
|
||||
};
|
Loading…
Reference in New Issue