feat(prejoin_page): Rework prejoin page

* Add a checkbox for skipping the prejoin page on next use. (This is hidden for
now, until we also have a settings entry for it).
* Rework 'Join by Phone' buttons and add new overlay.
* Update the device status accordingly if there were errors while adding
devices.
* The input is filled with the display name if there was one previously used.
* Join the meeting on 'Enter' press.
This commit is contained in:
Vlad Piersec 2020-05-07 10:42:55 +03:00 committed by Saúl Ibarra Corretgé
parent a41bda73ff
commit 908712b96f
17 changed files with 355 additions and 117 deletions

View File

@ -9,9 +9,9 @@
&-input-area-container {
position: absolute;
bottom: 128px;
bottom: 48px;
width: 100%;
z-index: 1;
z-index: 2;
}
&-input-area {
@ -34,8 +34,8 @@
display: inline-block;
font-size: 15px;
line-height: 24px;
margin-bottom: 16px;
padding: 7px 16px;
position: relative;
text-align: center;
width: 286px;
@ -51,11 +51,24 @@
&--text {
width: auto;
font-size: 13px;
margin: 0;
padding: 0;
}
}
&-btn-options {
align-items: center;
border-left: 1px solid #fff;
display: flex;
height: 100%;
justify-content: center;
position: absolute;
right: 0;
top: 0;
width: 40px;
}
&-text-btns {
display: flex;
justify-content: space-between;
@ -69,6 +82,25 @@
text-align: center;
width: 100%;
}
&-checkbox {
border: 0;
height: 16px;
margin-right: 8px;
padding: 0;
width: 16px;
}
&-checkbox-container {
align-items: center;
color: #fff;
display: none;
font-size: 13px;
justify-content: center;
line-height: 20px;
margin-top: 16px;
width: 100%;
}
}
@mixin name-placeholder {
@ -128,10 +160,8 @@
&-btn-container {
display: flex;
justify-content: center;
position: absolute;
bottom: 50px;
margin-top: 32px;
width: 100%;
z-index: 1;
&> div {
margin: 0 12px;
@ -151,7 +181,16 @@
position: absolute;
width: 100%;
z-index: 1;
background: linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3)), linear-gradient(360deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0) 54.25%);
background: linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3));
}
&-bottom-overlay {
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.9) 100%);
bottom: 0;
height: 50%;
position: absolute;
width: 100%;
z-index: 1;
}
&-status {
@ -192,6 +231,43 @@
width: 49px;
margin: 0 8px;
}
&-dropdown-btns {
width: 320px;
padding: 8px 0;
}
&-dropdown-btn {
align-items: center;
color: #1C2025;
cursor: pointer;
display: flex;
height: 40px;
font-size: 15px;
line-height: 24px;
padding: 0 16px;
&:hover {
background-color: #DAEBFA;
}
}
&-dropdown-icon {
display: inline-block;
margin-right: 16px;
& > svg {
fill: #1C2025;
}
}
&-dropdown-container {
& > div > div:nth-child(2) > div > div {
background: #fff;
padding: 0;
}
}
}
.prejoin-copy {

View File

@ -488,13 +488,14 @@
"dialInMeeting": "Dial into the meeting",
"dialInPin": "Dial into the meeting and enter PIN code:",
"dialing": "Dialing",
"doNotShow": "Don't show this again",
"iWantToDialIn": "I want to dial in",
"joinAudioByPhone": "Join with phone audio",
"joinMeeting": "Join meeting",
"joinWithoutAudio": "Join without audio",
"initiated": "Call initiated",
"linkCopied": "Link copied to clipboard",
"lookGood": "Speaker and microphone look good",
"lookGood": "It sounds like your microphone is working properly",
"or": "or",
"calling": "Calling",
"startWithPhone": "Start with phone audio",

View File

@ -18,7 +18,7 @@ import {
SET_AUDIO_INPUT_DEVICE,
SET_VIDEO_INPUT_DEVICE
} from './actionTypes';
import { replaceAudioTrackById, replaceVideoTrackById } from '../../prejoin/actions';
import { replaceAudioTrackById, replaceVideoTrackById, setDeviceStatusWarning } from '../../prejoin/actions';
import { isPrejoinPageVisible } from '../../prejoin/functions';
import { showNotification, showWarningNotification } from '../../notifications';
import { updateSettings } from '../settings';
@ -65,14 +65,19 @@ MiddlewareRegistry.register(store => next => action => {
|| JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP
.camera[JitsiTrackErrors.GENERAL];
const additionalCameraErrorMsg = cameraJitsiTrackErrorMsg ? null : message;
const titleKey = name === JitsiTrackErrors.PERMISSION_DENIED
? 'deviceError.cameraPermission' : 'deviceError.cameraError';
store.dispatch(showWarningNotification({
description: additionalCameraErrorMsg,
descriptionKey: cameraErrorMsg,
titleKey: name === JitsiTrackErrors.PERMISSION_DENIED
? 'deviceError.cameraPermission' : 'deviceError.cameraError'
titleKey
}));
if (isPrejoinPageVisible(store.getState())) {
store.dispatch(setDeviceStatusWarning(titleKey));
}
break;
}
case NOTIFY_MIC_ERROR: {
@ -88,15 +93,20 @@ MiddlewareRegistry.register(store => next => action => {
|| JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP
.microphone[JitsiTrackErrors.GENERAL];
const additionalMicErrorMsg = micJitsiTrackErrorMsg ? null : message;
const titleKey = name === JitsiTrackErrors.PERMISSION_DENIED
? 'deviceError.microphonePermission'
: 'deviceError.microphoneError';
store.dispatch(showWarningNotification({
description: additionalMicErrorMsg,
descriptionKey: micErrorMsg,
titleKey: name === JitsiTrackErrors.PERMISSION_DENIED
? 'deviceError.microphonePermission'
: 'deviceError.microphoneError'
titleKey
}));
if (isPrejoinPageVisible(store.getState())) {
store.dispatch(setDeviceStatusWarning(titleKey));
}
break;
}
case SET_AUDIO_INPUT_DEVICE:

View File

@ -85,3 +85,4 @@ export { default as IconVideoQualityLD } from './LD.svg';
export { default as IconVideoQualitySD } from './SD.svg';
export { default as IconVolume } from './volume.svg';
export { default as IconVolumeEmpty } from './volume-empty.svg';
export { default as IconVolumeOff } from './volume-off.svg';

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.8887 6.42609L7.87494 6.43755L3.73524 2.29786C3.33819 1.9008 2.69455 1.9007 2.29763 2.29763C1.9007 2.69455 1.9008 3.33819 2.29786 3.73524L6.30688 7.74427L6 8H3C2.44772 8 2 8.44772 2 9V15C2 15.5523 2.44772 16 3 16H6L11.1799 20.3166C11.2698 20.3915 11.383 20.4325 11.5 20.4325C11.7761 20.4325 12 20.2086 12 19.9325V13.4374L14 15.4374V16C14.179 16 14.3553 15.9882 14.5281 15.9655L16.1615 17.5989C15.4909 17.8579 14.762 18 14 18V20C15.3237 20 16.5723 19.6785 17.672 19.1094L20.2648 21.7021C20.6618 22.0992 21.3055 22.0993 21.7024 21.7024C22.0993 21.3055 22.0992 20.6618 21.7021 20.2648L19.3686 17.9312C19.373 17.9272 19.3774 17.9232 19.3818 17.9192L17.9655 16.5029C17.961 16.5068 17.9565 16.5107 17.9521 16.5147L16.5332 15.0958C16.5378 15.092 16.5424 15.0882 16.547 15.0844L15.1203 13.6577C15.1153 13.6611 15.1103 13.6645 15.1052 13.6678L12 10.5626V10.5374L10 8.53739V8.56261L9.29498 7.8576L9.30874 7.84613L7.8887 6.42609ZM14 9.66261L17.7452 13.4078C17.9099 12.9699 18 12.4955 18 12C18 9.79086 16.2091 8 14 8V9.66261ZM19.248 14.9106L20.7042 16.3668C21.5237 15.1112 22 13.6112 22 12C22 7.58172 18.4183 4 14 4V6C17.3137 6 20 8.68629 20 12C20 13.0562 19.7271 14.0486 19.248 14.9106ZM12 7.66261L9.45676 5.11937L11.1799 3.68341C11.392 3.50663 11.7073 3.53529 11.8841 3.74743C11.959 3.83729 12 3.95055 12 4.06752V7.66261ZM6.7241 10L7.72692 9.16431L10 11.4374V16.7299L6.7241 14H4V10H6.7241Z" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -32,6 +32,17 @@ export function getCurrentOutputDeviceId(state: Object) {
return state['features/base/settings'].audioOutputDeviceId;
}
/**
* Returns the saved display name.
*
* @param {Object} state - The state of the application.
* @returns {string}
*/
export function getDisplayName(state: Object): string {
return state['features/base/settings'].displayName || '';
}
/**
* Handles changes to the `disableCallIntegration` setting.
* Noop on web.

View File

@ -39,7 +39,8 @@ const DEFAULT_STATE = {
userSelectedMicDeviceId: undefined,
userSelectedAudioOutputDeviceLabel: undefined,
userSelectedCameraDeviceLabel: undefined,
userSelectedMicDeviceLabel: undefined
userSelectedMicDeviceLabel: undefined,
userSelectedSkipPrejoin: undefined
};
const STORE_NAME = 'features/base/settings';

View File

@ -24,6 +24,11 @@ export const PREJOIN_START_CONFERENCE = 'PREJOIN_START_CONFERENCE';
*/
export const SET_DEVICE_STATUS = 'SET_DEVICE_STATUS';
/**
* Action type to set the visiblity of the prejoin page for the future.
*/
export const SET_SKIP_PREJOIN = 'SET_SKIP_PREJOIN';
/**
* Action type to set the visiblity of the 'JoinByPhone' dialog.
*/
@ -44,11 +49,6 @@ export const SET_PREJOIN_AUDIO_MUTED = 'SET_PREJOIN_AUDIO_MUTED';
*/
export const SET_PREJOIN_DEVICE_ERRORS = 'SET_PREJOIN_DEVICE_ERRORS';
/**
* Action type to set the name of the user.
*/
export const SET_PREJOIN_NAME = 'SET_PREJOIN_NAME';
/**
* Action type to set the visibility of the prejoin page.
*/

View File

@ -6,11 +6,11 @@ import {
ADD_PREJOIN_VIDEO_TRACK,
PREJOIN_START_CONFERENCE,
SET_DEVICE_STATUS,
SET_SKIP_PREJOIN,
SET_JOIN_BY_PHONE_DIALOG_VISIBLITY,
SET_PREJOIN_AUDIO_DISABLED,
SET_PREJOIN_AUDIO_MUTED,
SET_PREJOIN_DEVICE_ERRORS,
SET_PREJOIN_NAME,
SET_PREJOIN_PAGE_VISIBILITY,
SET_PREJOIN_VIDEO_DISABLED,
SET_PREJOIN_VIDEO_MUTED
@ -273,6 +273,18 @@ export function setDeviceStatusWarning(deviceStatusText: string) {
};
}
/**
* Sets the visibility of the prejoin page for future uses.
*
* @param {boolean} value - The visibility value.
* @returns {Object}
*/
export function setSkipPrejoin(value: boolean) {
return {
type: SET_SKIP_PREJOIN,
value
};
}
/**
* Action used to set the visiblitiy of the 'JoinByPhoneDialog'.
@ -300,19 +312,6 @@ export function setPrejoinDeviceErrors(value: Object) {
};
}
/**
* Action used to set the name of the guest user.
*
* @param {string} value - The name.
* @returns {Object}
*/
export function setPrejoinName(value: string) {
return {
type: SET_PREJOIN_NAME,
value
};
}
/**
* Action used to set the visiblity of the prejoin page.
*

View File

@ -1,19 +1,21 @@
// @flow
import React, { Component } from 'react';
import InlineDialog from '@atlaskit/inline-dialog';
import {
joinConference as joinConferenceAction,
joinConferenceWithoutAudio as joinConferenceWithoutAudioAction,
setJoinByPhoneDialogVisiblity as setJoinByPhoneDialogVisiblityAction,
setPrejoinName
setSkipPrejoin as setSkipPrejoinAction,
setJoinByPhoneDialogVisiblity as setJoinByPhoneDialogVisiblityAction
} from '../actions';
import { getRoomName } from '../../base/conference';
import { Icon, IconPhone, IconVolumeOff } from '../../base/icons';
import { translate } from '../../base/i18n';
import { connect } from '../../base/redux';
import { getDisplayName, updateSettings } from '../../base/settings';
import ActionButton from './buttons/ActionButton';
import {
areJoinByPhoneButtonsVisible,
getPrejoinName,
isDeviceStatusVisible,
isJoinByPhoneDialogVisible
} from '../functions';
@ -52,9 +54,9 @@ type Props = {
name: string,
/**
* Sets the name for the joining user.
* Updates settings.
*/
setName: Function,
updateSettings: Function,
/**
* The name of the meeting that is about to be joined.
@ -62,7 +64,12 @@ type Props = {
roomName: string,
/**
* Sets visibilit of the 'JoinByPhoneDialog'.
* Sets visibility of the prejoin page for the next sessions.
*/
setSkipPrejoin: Function,
/**
* Sets visibility of the 'JoinByPhoneDialog'.
*/
setJoinByPhoneDialogVisiblity: Function,
@ -74,7 +81,7 @@ type Props = {
/**
* If join by phone buttons should be visible.
*/
showJoinByPhoneButtons: boolean,
hasJoinByPhoneButtons: boolean,
/**
* Used for translation.
@ -82,10 +89,18 @@ type Props = {
t: Function,
};
type State = {
/**
* Flag controlling the visibility of the 'join by phone' buttons.
*/
showJoinByPhoneButtons: boolean
}
/**
* This component is displayed before joining a meeting.
*/
class Prejoin extends Component<Props> {
class Prejoin extends Component<Props, State> {
/**
* Initializes a new {@code Prejoin} instance.
*
@ -94,7 +109,69 @@ class Prejoin extends Component<Props> {
constructor(props) {
super(props);
this.state = {
showJoinByPhoneButtons: false
};
this._showDialog = this._showDialog.bind(this);
this._onCheckboxChange = this._onCheckboxChange.bind(this);
this._onDropdownClose = this._onDropdownClose.bind(this);
this._onOptionsClick = this._onOptionsClick.bind(this);
this._setName = this._setName.bind(this);
}
_onCheckboxChange: () => void;
/**
* Handler for the checkbox.
*
* @param {Object} e - The synthetic event.
* @returns {void}
*/
_onCheckboxChange(e) {
this.props.setSkipPrejoin(e.target.checked);
}
_onDropdownClose: () => void;
/**
* Closes the dropdown.
*
* @returns {void}
*/
_onDropdownClose() {
this.setState({
showJoinByPhoneButtons: false
});
}
_onOptionsClick: () => void;
/**
* Displays the join by phone buttons dropdown.
*
* @param {Object} e - The synthetic event.
* @returns {void}
*/
_onOptionsClick(e) {
e.stopPropagation();
this.setState({
showJoinByPhoneButtons: !this.state.showJoinByPhoneButtons
});
}
_setName: () => void;
/**
* Sets the guest participant name.
*
* @param {string} displayName - Participant name.
* @returns {void}
*/
_setName(displayName) {
this.props.updateSettings({
displayName
});
}
_showDialog: () => void;
@ -121,49 +198,78 @@ class Prejoin extends Component<Props> {
joinConference,
joinConferenceWithoutAudio,
name,
setName,
showJoinByPhoneButtons,
hasJoinByPhoneButtons,
t
} = this.props;
const { _showDialog } = this;
const { _onCheckboxChange, _onDropdownClose, _onOptionsClick, _setName, _showDialog } = this;
const { showJoinByPhoneButtons } = this.state;
return (
<div className = 'prejoin-full-page'>
<Preview />
<Preview name = { name } />
<div className = 'prejoin-input-area-container'>
<div className = 'prejoin-input-area'>
<div className = 'prejoin-title'>
{t('prejoin.joinMeeting')}
</div>
<CopyMeetingUrl />
<ParticipantName
isEditable = { isAnonymousUser }
setName = { setName }
joinConference = { joinConference }
setName = { _setName }
value = { name } />
<ActionButton
onClick = { joinConference }
type = 'primary'>
{ t('calendarSync.join') }
</ActionButton>
{showJoinByPhoneButtons
&& <div className = 'prejoin-text-btns'>
<ActionButton
onClick = { joinConferenceWithoutAudio }
type = 'text'>
<div className = 'prejoin-preview-dropdown-container'>
<InlineDialog
content = { <div className = 'prejoin-preview-dropdown-btns'>
<div
className = 'prejoin-preview-dropdown-btn'
onClick = { joinConferenceWithoutAudio }>
<Icon
className = 'prejoin-preview-dropdown-icon'
size = { 24 }
src = { IconVolumeOff } />
{ t('prejoin.joinWithoutAudio') }
</ActionButton>
<ActionButton
onClick = { _showDialog }
type = 'text'>
</div>
<div
className = 'prejoin-preview-dropdown-btn'
onClick = { _showDialog }>
<Icon
className = 'prejoin-preview-dropdown-icon'
size = { 24 }
src = { IconPhone } />
{ t('prejoin.joinAudioByPhone') }
</ActionButton>
</div>
</div> }
isOpen = { showJoinByPhoneButtons }
onClose = { _onDropdownClose }>
<ActionButton
hasOptions = { hasJoinByPhoneButtons }
onClick = { joinConference }
onOptionsClick = { _onOptionsClick }
type = 'primary'>
{ t('prejoin.joinMeeting') }
</ActionButton>
</InlineDialog>
</div>
</div>
<div className = 'prejoin-preview-btn-container'>
<AudioSettingsButton visible = { true } />
<VideoSettingsButton visible = { true } />
</div>
</div>
<div className = 'prejoin-checkbox-container'>
<input
className = 'prejoin-checkbox'
onChange = { _onCheckboxChange }
type = 'checkbox' />
<span>{t('prejoin.doNotShow')}</span>
</div>
</div>
{ deviceStatusVisible && <DeviceStatus /> }
</div>
);
@ -180,10 +286,10 @@ function mapStateToProps(state): Object {
return {
isAnonymousUser: isGuest(state),
deviceStatusVisible: isDeviceStatusVisible(state),
name: getPrejoinName(state),
name: getDisplayName(state),
roomName: getRoomName(state),
showDialog: isJoinByPhoneDialogVisible(state),
showJoinByPhoneButtons: areJoinByPhoneButtonsVisible(state)
hasJoinByPhoneButtons: areJoinByPhoneButtonsVisible(state)
};
}
@ -191,7 +297,8 @@ const mapDispatchToProps = {
joinConferenceWithoutAudio: joinConferenceWithoutAudioAction,
joinConference: joinConferenceAction,
setJoinByPhoneDialogVisiblity: setJoinByPhoneDialogVisiblityAction,
setName: setPrejoinName
setSkipPrejoin: setSkipPrejoinAction,
updateSettings
};
export default connect(mapStateToProps, mapDispatchToProps)(translate(Prejoin));

View File

@ -1,6 +1,8 @@
// @flow
import React from 'react';
import { Icon, IconArrowDown } from '../../../base/icons';
const classNameByType = {
primary: 'prejoin-btn--primary',
secondary: 'prejoin-btn--secondary',
@ -19,6 +21,11 @@ type Props = {
*/
className?: string,
/**
* If the button has options.
*/
hasOptions?: boolean,
/**
* The type of th button: primary, secondary, text.
*/
@ -28,6 +35,11 @@ type Props = {
* OnClick button handler.
*/
onClick: Function,
/**
* Click handler for options.
*/
onOptionsClick?: Function
};
/**
@ -35,7 +47,7 @@ type Props = {
*
* @returns {ReactElement}
*/
function ActionButton({ children, className, type, onClick }: Props) {
function ActionButton({ children, className, hasOptions, type, onClick, onOptionsClick }: Props) {
const ownClassName = `prejoin-btn ${classNameByType[type]}`;
const cls = className ? `${className} ${ownClassName}` : ownClassName;
@ -44,6 +56,15 @@ function ActionButton({ children, className, type, onClick }: Props) {
className = { cls }
onClick = { onClick }>
{children}
{hasOptions && <div
className = 'prejoin-btn-options'
onClick = { onOptionsClick }>
<Icon
className = 'prejoin-btn-icon'
size = { 14 }
src = { IconArrowDown } />
</div>
}
</div>
);
}

View File

@ -170,6 +170,7 @@ class CopyMeetingUrl extends Component<Props, State> {
</div>}
<Icon
className = { `prejoin-copy-icon ${iconCls}` }
onClick = { _copyUrl }
size = { 24 }
src = { src } />
<textarea

View File

@ -10,6 +10,11 @@ type Props = {
*/
isEditable: boolean,
/**
* Joins the current meeting.
*/
joinConference: Function,
/**
* Sets the name for the joining user.
*/
@ -32,6 +37,7 @@ type Props = {
* @returns {ReactElement}
*/
class ParticipantName extends Component<Props> {
/**
* Initializes a new {@code ParticipantName} instance.
*
@ -41,9 +47,24 @@ class ParticipantName extends Component<Props> {
constructor(props) {
super(props);
this._onKeyDown = this._onKeyDown.bind(this);
this._onNameChange = this._onNameChange.bind(this);
}
_onKeyDown: () => void;
/**
* Joins the conference on 'Enter'.
*
* @param {Event} event - Key down event object.
* @returns {void}
*/
_onKeyDown(event) {
if (event.key === 'Enter') {
this.props.joinConference();
}
}
_onNameChange: () => void;
/**
@ -63,15 +84,23 @@ class ParticipantName extends Component<Props> {
*/
render() {
const { value, isEditable, t } = this.props;
const { _onKeyDown, _onNameChange } = this;
return isEditable ? (
<input
autoFocus = { true }
className = 'prejoin-preview-name prejoin-preview-name--editable'
onChange = { this._onNameChange }
onChange = { _onNameChange }
onKeyDown = { _onKeyDown }
placeholder = { t('dialog.enterDisplayName') }
value = { value } />
)
: <div className = 'prejoin-preview-name'>{value}</div>
: <div
className = 'prejoin-preview-name'
onKeyDown = { _onKeyDown }
tabIndex = '0' >
{value}
</div>
;
}
}

View File

@ -4,7 +4,7 @@ import React from 'react';
import { Avatar } from '../../../base/avatar';
import { Video } from '../../../base/media';
import { connect } from '../../../base/redux';
import { getActiveVideoTrack, getPrejoinName, isPrejoinVideoMuted } from '../../functions';
import { getActiveVideoTrack, isPrejoinVideoMuted } from '../../functions';
export type Props = {
@ -41,6 +41,7 @@ function Preview(props: Props) {
return (
<div className = 'prejoin-preview'>
<div className = 'prejoin-preview-overlay' />
<div className = 'prejoin-preview-bottom-overlay' />
<Video
className = 'flipVideoX prejoin-preview-video'
videoTrack = {{ jitsiTrack: videoTrack }} />
@ -66,7 +67,6 @@ function Preview(props: Props) {
*/
function mapStateToProps(state) {
return {
name: getPrejoinName(state),
videoTrack: getActiveVideoTrack(state),
showCameraPreview: !isPrejoinVideoMuted(state)
};

View File

@ -146,16 +146,6 @@ export function isPrejoinAudioMuted(state: Object): boolean {
return state['features/prejoin'].audioMuted;
}
/**
* Selector for getting the name that the user filled while configuring.
*
* @param {Object} state - The state of the app.
* @returns {boolean}
*/
export function getPrejoinName(state: Object): string {
return state['features/prejoin'].name;
}
/**
* Selector for getting the mute status of the prejoin video.
*
@ -214,7 +204,8 @@ export function isJoinByPhoneDialogVisible(state: Object): boolean {
* @returns {boolean}
*/
export function isPrejoinPageEnabled(state: Object): boolean {
return state['features/base/config'].prejoinPageEnabled;
return state['features/base/config'].prejoinPageEnabled
&& !state['features/base/settings'].userSelectedSkipPrejoin;
}
/**

View File

@ -6,11 +6,10 @@ import {
PREJOIN_START_CONFERENCE
} from './actionTypes';
import { setPrejoinAudioMuted, setPrejoinVideoMuted } from './actions';
import { SET_AUDIO_MUTED, SET_VIDEO_MUTED } from '../base/media';
import { participantUpdated, getLocalParticipant } from '../base/participants';
import { MiddlewareRegistry } from '../base/redux';
import { updateSettings } from '../base/settings';
import { getAllPrejoinConfiguredTracks, getPrejoinName } from './functions';
import { SET_AUDIO_MUTED, SET_VIDEO_MUTED } from '../base/media';
import { MiddlewareRegistry } from '../base/redux';
import { getAllPrejoinConfiguredTracks } from './functions';
declare var APP: Object;
@ -51,10 +50,16 @@ MiddlewareRegistry.register(store => next => async action => {
}
case PREJOIN_START_CONFERENCE: {
const { dispatch, getState } = store;
const { getState, dispatch } = store;
const state = getState();
const { userSelectedSkipPrejoin } = state['features/prejoin'];
_syncParticipantName(dispatch, getState);
const tracks = await getAllPrejoinConfiguredTracks(getState());
userSelectedSkipPrejoin && dispatch(updateSettings({
userSelectedSkipPrejoin
}));
const tracks = await getAllPrejoinConfiguredTracks(state);
APP.conference.prejoinStart(tracks);
@ -70,26 +75,8 @@ MiddlewareRegistry.register(store => next => async action => {
store.dispatch(setPrejoinVideoMuted(Boolean(action.muted)));
break;
}
}
return next(action);
});
/**
* Sets the local participant name if one is present.
*
* @param {Function} dispatch - The redux dispatch function.
* @param {Function} getState - Gets the current state.
* @returns {undefined}
*/
function _syncParticipantName(dispatch, getState) {
const state = getState();
const name = getPrejoinName(state);
name && dispatch(
participantUpdated({
...getLocalParticipant(state),
name
}),
);
}

View File

@ -6,10 +6,10 @@ import {
ADD_PREJOIN_VIDEO_TRACK,
SET_DEVICE_STATUS,
SET_JOIN_BY_PHONE_DIALOG_VISIBLITY,
SET_SKIP_PREJOIN,
SET_PREJOIN_AUDIO_DISABLED,
SET_PREJOIN_AUDIO_MUTED,
SET_PREJOIN_DEVICE_ERRORS,
SET_PREJOIN_NAME,
SET_PREJOIN_PAGE_VISIBILITY,
SET_PREJOIN_VIDEO_DISABLED,
SET_PREJOIN_VIDEO_MUTED
@ -24,11 +24,11 @@ const DEFAULT_STATE = {
deviceStatusType: 'ok',
showPrejoin: true,
showJoinByPhoneDialog: false,
userSelectedSkipPrejoin: false,
videoTrack: null,
audioTrack: null,
contentSharingTrack: null,
rawError: '',
name: ''
rawError: ''
};
/**
@ -58,10 +58,10 @@ ReducerRegistry.register(
};
}
case SET_PREJOIN_NAME: {
case SET_SKIP_PREJOIN: {
return {
...state,
name: action.value
userSelectedSkipPrejoin: action.value
};
}