feat(ui-components) Add toggle component (#11933)
This commit is contained in:
parent
3e66e0009d
commit
db54c45b13
|
@ -0,0 +1,117 @@
|
||||||
|
import { makeStyles } from '@material-ui/core';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
|
import { isMobileBrowser } from '../../../environment/utils';
|
||||||
|
|
||||||
|
interface SwitchProps {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the toggle is on.
|
||||||
|
*/
|
||||||
|
checked: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the toggle is disabled.
|
||||||
|
*/
|
||||||
|
disabled?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id of the toggle.
|
||||||
|
*/
|
||||||
|
id?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle change callback.
|
||||||
|
*/
|
||||||
|
onChange: (on?: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme: any) => {
|
||||||
|
return {
|
||||||
|
container: {
|
||||||
|
position: 'relative',
|
||||||
|
backgroundColor: theme.palette.ui05,
|
||||||
|
borderRadius: '12px',
|
||||||
|
width: '40px',
|
||||||
|
height: '24px',
|
||||||
|
border: 0,
|
||||||
|
outline: 0,
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: '.3s',
|
||||||
|
display: 'inline-block',
|
||||||
|
|
||||||
|
'&.disabled': {
|
||||||
|
backgroundColor: theme.palette.ui05,
|
||||||
|
cursor: 'default',
|
||||||
|
|
||||||
|
'& .toggle': {
|
||||||
|
backgroundColor: theme.palette.ui03
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'&.is-mobile': {
|
||||||
|
height: '32px',
|
||||||
|
width: '50px',
|
||||||
|
borderRadius: '32px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
containerOn: {
|
||||||
|
backgroundColor: theme.palette.action01
|
||||||
|
},
|
||||||
|
|
||||||
|
toggle: {
|
||||||
|
width: '16px',
|
||||||
|
height: '16px',
|
||||||
|
position: 'absolute',
|
||||||
|
top: '4px',
|
||||||
|
left: '4px',
|
||||||
|
backgroundColor: theme.palette.ui10,
|
||||||
|
borderRadius: '100%',
|
||||||
|
transition: '.3s',
|
||||||
|
|
||||||
|
'&.is-mobile': {
|
||||||
|
width: '24px',
|
||||||
|
height: '24px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleOn: {
|
||||||
|
left: '20px',
|
||||||
|
|
||||||
|
'&.is-mobile': {
|
||||||
|
left: '22px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
checkbox: {
|
||||||
|
height: 0,
|
||||||
|
width: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const Switch = ({ id, checked, disabled, onChange }: SwitchProps) => {
|
||||||
|
const styles = useStyles();
|
||||||
|
const isMobile = isMobileBrowser();
|
||||||
|
|
||||||
|
const change = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
onChange(e.target.checked);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (<label
|
||||||
|
className = { clsx('toggle-container', styles.container, checked && styles.containerOn,
|
||||||
|
isMobile && 'is-mobile', disabled && 'disabled') }>
|
||||||
|
<input
|
||||||
|
type = 'checkbox'
|
||||||
|
{ ...(id ? { id } : {}) }
|
||||||
|
checked = { checked }
|
||||||
|
className = { styles.checkbox }
|
||||||
|
disabled = { disabled }
|
||||||
|
onChange = { change } />
|
||||||
|
<div className = { clsx('toggle', styles.toggle, checked && styles.toggleOn, isMobile && 'is-mobile') } />
|
||||||
|
</label>);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Switch;
|
|
@ -1,14 +1,18 @@
|
||||||
/* @flow */
|
/* eslint-disable lines-around-comment */
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import type { Dispatch } from 'redux';
|
import type { Dispatch } from 'redux';
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
import { createE2EEEvent, sendAnalytics } from '../../analytics';
|
import { createE2EEEvent, sendAnalytics } from '../../analytics';
|
||||||
|
// @ts-ignore
|
||||||
import { translate } from '../../base/i18n';
|
import { translate } from '../../base/i18n';
|
||||||
import { Switch } from '../../base/react';
|
import { connect } from '../../base/redux/functions';
|
||||||
import { connect } from '../../base/redux';
|
import Switch from '../../base/ui/components/web/Switch';
|
||||||
|
// @ts-ignore
|
||||||
import { toggleE2EE } from '../actions';
|
import { toggleE2EE } from '../actions';
|
||||||
|
// @ts-ignore
|
||||||
import { MAX_MODE } from '../constants';
|
import { MAX_MODE } from '../constants';
|
||||||
|
// @ts-ignore
|
||||||
import { doesEveryoneSupportE2EE } from '../functions';
|
import { doesEveryoneSupportE2EE } from '../functions';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -21,7 +25,7 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* Custom e2ee labels.
|
* Custom e2ee labels.
|
||||||
*/
|
*/
|
||||||
_e2eeLabels: Object,
|
_e2eeLabels: any,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the switch is currently enabled or not.
|
* Whether the switch is currently enabled or not.
|
||||||
|
@ -69,7 +73,7 @@ class E2EESection extends Component<Props, State> {
|
||||||
*
|
*
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
static getDerivedStateFromProps(props: Props, state: Object) {
|
static getDerivedStateFromProps(props: Props, state: State) {
|
||||||
if (props._toggled !== state.toggled) {
|
if (props._toggled !== state.toggled) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -124,17 +128,15 @@ class E2EESection extends Component<Props, State> {
|
||||||
{ label }
|
{ label }
|
||||||
</label>
|
</label>
|
||||||
<Switch
|
<Switch
|
||||||
|
checked = { toggled }
|
||||||
disabled = { !_enabled }
|
disabled = { !_enabled }
|
||||||
id = 'e2ee-section-switch'
|
id = 'e2ee-section-switch'
|
||||||
onValueChange = { this._onToggle }
|
onChange = { this._onToggle } />
|
||||||
value = { toggled } />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onToggle: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to be invoked when the user toggles E2EE on or off.
|
* Callback to be invoked when the user toggles E2EE on or off.
|
||||||
*
|
*
|
||||||
|
@ -160,11 +162,11 @@ class E2EESection extends Component<Props, State> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {Props}
|
* @returns {Props}
|
||||||
*/
|
*/
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state: any) {
|
||||||
const { enabled: e2eeEnabled, maxMode } = state['features/e2ee'];
|
const { enabled: e2eeEnabled, maxMode } = state['features/e2ee'];
|
||||||
const { e2eeLabels } = state['features/base/config'];
|
const { e2eeLabels } = state['features/base/config'];
|
||||||
|
|
||||||
let descriptionResource = '';
|
let descriptionResource: string|undefined = '';
|
||||||
|
|
||||||
if (e2eeLabels) {
|
if (e2eeLabels) {
|
||||||
// When e2eeLabels are present, the descriptionResouse is ignored.
|
// When e2eeLabels are present, the descriptionResouse is ignored.
|
|
@ -1,12 +1,15 @@
|
||||||
// @flow
|
/* eslint-disable lines-around-comment */
|
||||||
|
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
import { translate } from '../../../base/i18n';
|
import { translate } from '../../../base/i18n';
|
||||||
|
// @ts-ignore
|
||||||
import { isLocalParticipantModerator } from '../../../base/participants';
|
import { isLocalParticipantModerator } from '../../../base/participants';
|
||||||
import { Switch } from '../../../base/react';
|
import { connect } from '../../../base/redux/functions';
|
||||||
import { connect } from '../../../base/redux';
|
import Switch from '../../../base/ui/components/web/Switch';
|
||||||
|
// @ts-ignore
|
||||||
import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
|
import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
|
||||||
|
// @ts-ignore
|
||||||
import { toggleLobbyMode } from '../../actions';
|
import { toggleLobbyMode } from '../../actions';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -64,7 +67,7 @@ class LobbySection extends PureComponent<Props, State> {
|
||||||
*
|
*
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
static getDerivedStateFromProps(props: Props, state: Object) {
|
static getDerivedStateFromProps(props: Props, state: State) {
|
||||||
if (props._lobbyEnabled !== state.lobbyEnabled) {
|
if (props._lobbyEnabled !== state.lobbyEnabled) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -100,9 +103,9 @@ class LobbySection extends PureComponent<Props, State> {
|
||||||
{ t('lobby.toggleLabel') }
|
{ t('lobby.toggleLabel') }
|
||||||
</label>
|
</label>
|
||||||
<Switch
|
<Switch
|
||||||
|
checked = { this.state.lobbyEnabled }
|
||||||
id = 'lobby-section-switch'
|
id = 'lobby-section-switch'
|
||||||
onValueChange = { this._onToggleLobby }
|
onChange = { this._onToggleLobby } />
|
||||||
value = { this.state.lobbyEnabled } />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className = 'separator-line' />
|
<div className = 'separator-line' />
|
||||||
|
@ -110,8 +113,6 @@ class LobbySection extends PureComponent<Props, State> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onToggleLobby: () => void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to be invoked when the user toggles the lobby feature on or off.
|
* Callback to be invoked when the user toggles the lobby feature on or off.
|
||||||
*
|
*
|
||||||
|
@ -134,14 +135,12 @@ class LobbySection extends PureComponent<Props, State> {
|
||||||
* @param {Object} state - The Redux state.
|
* @param {Object} state - The Redux state.
|
||||||
* @returns {Props}
|
* @returns {Props}
|
||||||
*/
|
*/
|
||||||
function mapStateToProps(state: Object): $Shape<Props> {
|
function mapStateToProps(state: any): Partial<Props> {
|
||||||
const { conference } = state['features/base/conference'];
|
const { conference } = state['features/base/conference'];
|
||||||
const { hideLobbyButton } = state['features/base/config'];
|
const { hideLobbyButton } = state['features/base/config'];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_lobbyEnabled: state['features/lobby'].lobbyEnabled,
|
_lobbyEnabled: state['features/lobby'].lobbyEnabled,
|
||||||
|
|
||||||
// $FlowExpectedError
|
|
||||||
_visible: conference?.isLobbySupported() && isLocalParticipantModerator(state)
|
_visible: conference?.isLobbySupported() && isLocalParticipantModerator(state)
|
||||||
&& !hideLobbyButton && !isInBreakoutRoom(state)
|
&& !hideLobbyButton && !isInBreakoutRoom(state)
|
||||||
};
|
};
|
Loading…
Reference in New Issue