feat(prejoin): Add 'skip prejoin' button

This commit is contained in:
Vlad Piersec 2020-07-15 11:06:14 +03:00 committed by Saúl Ibarra Corretgé
parent c8444a9a0d
commit 035f720a50
7 changed files with 168 additions and 23 deletions

View File

@ -36,13 +36,7 @@
} }
&-checkbox-container { &-checkbox-container {
align-items: center; margin-bottom: 14px;
color: #fff;
display: none;
font-size: 13px;
justify-content: center;
line-height: 20px;
margin-top: 16px;
width: 100%; width: 100%;
} }
} }

View File

@ -216,3 +216,66 @@
width: 100%; width: 100%;
} }
} }
@mixin flex-centered() {
align-items: center;
display: flex;
justify-content: center;
}
@mixin icon-container($bg, $fill) {
.toggle-button-icon-container {
background: $bg;
svg {
fill: $fill
}
}
}
.toggle-button {
border-radius: 3px;
cursor: pointer;
color: #fff;
font-size: 13px;
height: 40px;
margin: 0 auto;
width: 320px;
@include flex-centered();
svg {
fill: transparent;
}
&:hover {
background: #1C2025;
@include icon-container(#A4B8D1, #1C2025);
}
&-container {
position: relative;
@include flex-centered();
}
&-icon-container {
border-radius: 50%;
left: -22px;
padding: 2px;
position: absolute;
}
&--toggled {
background: #75757A;
&:hover {
background: #75757A;
@include icon-container(#A4B8D1, #75757A);
}
@include icon-container(#A4B8D1, #75757A);
}
}

View File

@ -39,6 +39,11 @@ type Props = {
*/ */
title: string, title: string,
/**
* The 'Skip prejoin' button to be rendered (if any).
*/
skipPrejoinButton?: React$Node,
/** /**
* True if the preview overlay should be muted, false otherwise. * True if the preview overlay should be muted, false otherwise.
*/ */
@ -97,6 +102,7 @@ export default class PreMeetingScreen extends PureComponent<Props> {
<AudioSettingsButton visible = { true } /> <AudioSettingsButton visible = { true } />
<VideoSettingsButton visible = { true } /> <VideoSettingsButton visible = { true } />
</div> </div>
{ this.props.skipPrejoinButton }
{ this.props.footer } { this.props.footer }
</div> </div>
</div> </div>

View File

@ -0,0 +1,52 @@
// @flow
import React from 'react';
import { Icon, IconCheck } from '../../../icons';
const mainClass = 'toggle-button';
type Props = {
/**
* Text of the button.
*/
children: React$Node,
/**
* If the button is toggled or not.
*/
isToggled?: boolean,
/**
* OnClick button handler.
*/
onClick: Function
}
/**
* Button used as a toggle.
*
* @returns {ReactElement}
*/
function ToggleButton({ children, isToggled, onClick }: Props) {
const className = isToggled ? `${mainClass} ${mainClass}--toggled` : mainClass;
return (
<div
className = { className }
onClick = { onClick }>
<div className = 'toggle-button-container'>
<div className = 'toggle-button-icon-container'>
<Icon
className = 'toggle-button-icon'
size = { 10 }
src = { IconCheck } />
</div>
<span>{children}</span>
</div>
</div>
);
}
export default ToggleButton;

View File

@ -3,3 +3,4 @@
export { default as ActionButton } from './ActionButton'; export { default as ActionButton } from './ActionButton';
export { default as InputField } from './InputField'; export { default as InputField } from './InputField';
export { default as PreMeetingScreen } from './PreMeetingScreen'; export { default as PreMeetingScreen } from './PreMeetingScreen';
export { default as ToggleButton } from './ToggleButton';

View File

@ -7,7 +7,7 @@ import { getRoomName } from '../../base/conference';
import { translate } from '../../base/i18n'; import { translate } from '../../base/i18n';
import { Icon, IconPhone, IconVolumeOff } from '../../base/icons'; import { Icon, IconPhone, IconVolumeOff } from '../../base/icons';
import { isVideoMutedByUser } from '../../base/media'; import { isVideoMutedByUser } from '../../base/media';
import { ActionButton, InputField, PreMeetingScreen } from '../../base/premeeting'; import { ActionButton, InputField, PreMeetingScreen, ToggleButton } from '../../base/premeeting';
import { connect } from '../../base/redux'; import { connect } from '../../base/redux';
import { getDisplayName, updateSettings } from '../../base/settings'; import { getDisplayName, updateSettings } from '../../base/settings';
import { getLocalJitsiVideoTrack } from '../../base/tracks'; import { getLocalJitsiVideoTrack } from '../../base/tracks';
@ -21,7 +21,8 @@ import {
isDeviceStatusVisible, isDeviceStatusVisible,
isDisplayNameRequired, isDisplayNameRequired,
isJoinByPhoneButtonVisible, isJoinByPhoneButtonVisible,
isJoinByPhoneDialogVisible isJoinByPhoneDialogVisible,
isPrejoinSkipped
} from '../functions'; } from '../functions';
import JoinByPhoneDialog from './dialogs/JoinByPhoneDialog'; import JoinByPhoneDialog from './dialogs/JoinByPhoneDialog';
@ -29,6 +30,11 @@ import DeviceStatus from './preview/DeviceStatus';
type Props = { type Props = {
/**
* Flag signaling if the 'skip prejoin' button is toggled or not.
*/
buttonIsToggled: boolean,
/** /**
* Flag signaling if the device status is visible or not. * Flag signaling if the device status is visible or not.
*/ */
@ -145,22 +151,22 @@ class Prejoin extends Component<Props, State> {
this._closeDialog = this._closeDialog.bind(this); this._closeDialog = this._closeDialog.bind(this);
this._showDialog = this._showDialog.bind(this); this._showDialog = this._showDialog.bind(this);
this._onCheckboxChange = this._onCheckboxChange.bind(this); this._onToggleButtonClick = this._onToggleButtonClick.bind(this);
this._onDropdownClose = this._onDropdownClose.bind(this); this._onDropdownClose = this._onDropdownClose.bind(this);
this._onOptionsClick = this._onOptionsClick.bind(this); this._onOptionsClick = this._onOptionsClick.bind(this);
this._setName = this._setName.bind(this); this._setName = this._setName.bind(this);
} }
_onCheckboxChange: () => void; _onToggleButtonClick: () => void;
/** /**
* Handler for the checkbox. * Handler for the toggle button.
* *
* @param {Object} e - The synthetic event. * @param {Object} e - The synthetic event.
* @returns {void} * @returns {void}
*/ */
_onCheckboxChange(e) { _onToggleButtonClick() {
this.props.setSkipPrejoin(e.target.checked); this.props.setSkipPrejoin(!this.props.buttonIsToggled);
} }
_onDropdownClose: () => void; _onDropdownClose: () => void;
@ -250,7 +256,7 @@ class Prejoin extends Component<Props, State> {
videoTrack videoTrack
} = this.props; } = this.props;
const { _closeDialog, _onCheckboxChange, _onDropdownClose, _onOptionsClick, _setName, _showDialog } = this; const { _closeDialog, _onDropdownClose, _onOptionsClick, _setName, _showDialog } = this;
const { showJoinByPhoneButtons } = this.state; const { showJoinByPhoneButtons } = this.state;
return ( return (
@ -259,6 +265,7 @@ class Prejoin extends Component<Props, State> {
name = { name } name = { name }
showAvatar = { showAvatar } showAvatar = { showAvatar }
showConferenceInfo = { showJoinActions } showConferenceInfo = { showJoinActions }
skipPrejoinButton = { this._renderSkipPrejoinButton() }
title = { t('prejoin.joinMeeting') } title = { t('prejoin.joinMeeting') }
videoMuted = { !showCameraPreview } videoMuted = { !showCameraPreview }
videoTrack = { videoTrack }> videoTrack = { videoTrack }>
@ -306,14 +313,6 @@ class Prejoin extends Component<Props, State> {
</InlineDialog> </InlineDialog>
</div> </div>
</div> </div>
<div className = 'prejoin-checkbox-container'>
<input
className = 'prejoin-checkbox'
onChange = { _onCheckboxChange }
type = 'checkbox' />
<span>{t('prejoin.doNotShow')}</span>
</div>
</div> </div>
)} )}
{ showDialog && ( { showDialog && (
@ -333,6 +332,25 @@ class Prejoin extends Component<Props, State> {
_renderFooter() { _renderFooter() {
return this.props.deviceStatusVisible && <DeviceStatus />; return this.props.deviceStatusVisible && <DeviceStatus />;
} }
/**
* Renders the 'skip prejoin' button.
*
* @returns {React$Element}
*/
_renderSkipPrejoinButton() {
const { buttonIsToggled, t } = this.props;
return (
<div className = 'prejoin-checkbox-container'>
<ToggleButton
isToggled = { buttonIsToggled }
onClick = { this._onToggleButtonClick }>
{t('prejoin.doNotShow')}
</ToggleButton>
</div>
);
}
} }
/** /**
@ -346,6 +364,7 @@ function mapStateToProps(state): Object {
const joinButtonDisabled = isDisplayNameRequired(state) && !name; const joinButtonDisabled = isDisplayNameRequired(state) && !name;
return { return {
buttonIsToggled: isPrejoinSkipped(state),
joinButtonDisabled, joinButtonDisabled,
name, name,
deviceStatusVisible: isDeviceStatusVisible(state), deviceStatusVisible: isDeviceStatusVisible(state),

View File

@ -36,6 +36,16 @@ export function isDisplayNameRequired(state: Object): boolean {
|| state['features/base/config'].requireDisplayName; || state['features/base/config'].requireDisplayName;
} }
/**
* Selector for determining if the user has chosen to skip prejoin page.
*
* @param {Object} state - The state of the app.
* @returns {boolean}
*/
export function isPrejoinSkipped(state: Object) {
return state['features/prejoin'].userSelectedSkipPrejoin;
}
/** /**
* Returns the text for the prejoin status bar. * Returns the text for the prejoin status bar.
* *