mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2025-12-30 11:22:31 +00:00
feat(lobby) integrate login in lobby + configs (#16401)
* feat(lobby) integrate login in lobby + configs * fixed toolboxContainer styles, used HangupButton * make hangup button visible by default * use hangup button * feat(prejoin): fixed indent, import extension * squash: Restore back wait for owner dialog. * squash: Drops not used state and functions. --------- Co-authored-by: Calin-Teodor <calin.chitu@8x8.com> Co-authored-by: damencho <damencho@jitsi.org>
This commit is contained in:
@@ -46,6 +46,15 @@ export const SET_TOKEN_AUTH_URL_SUCCESS = 'SET_TOKEN_AUTH_URL_SUCCESS';
|
||||
*/
|
||||
export const STOP_WAIT_FOR_OWNER = 'STOP_WAIT_FOR_OWNER';
|
||||
|
||||
/**
|
||||
* The type of (redux) action which disables moderator login.
|
||||
*
|
||||
* {
|
||||
* type: DISABLE_MODERATOR_LOGIN
|
||||
* }
|
||||
*/
|
||||
export const DISABLE_MODERATOR_LOGIN = 'DISABLE_MODERATOR_LOGIN';
|
||||
|
||||
/**
|
||||
* The type of (redux) action which informs that the authentication and role
|
||||
* upgrade process has finished either with success or with a specific error.
|
||||
@@ -74,6 +83,15 @@ export const UPGRADE_ROLE_FINISHED = 'UPGRADE_ROLE_FINISHED';
|
||||
*/
|
||||
export const UPGRADE_ROLE_STARTED = 'UPGRADE_ROLE_STARTED';
|
||||
|
||||
/**
|
||||
* The type of (redux) action which enables moderator login.
|
||||
*
|
||||
* {
|
||||
* type: ENABLE_MODERATOR_LOGIN
|
||||
* }
|
||||
*/
|
||||
export const ENABLE_MODERATOR_LOGIN = 'ENABLE_MODERATOR_LOGIN';
|
||||
|
||||
/**
|
||||
* The type of (redux) action that sets delayed handler which will check if
|
||||
* the conference has been created and it's now possible to join from anonymous
|
||||
|
||||
@@ -4,12 +4,15 @@ import { IJitsiConference } from '../base/conference/reducer';
|
||||
import { hideDialog, openDialog } from '../base/dialog/actions';
|
||||
|
||||
import {
|
||||
DISABLE_MODERATOR_LOGIN,
|
||||
ENABLE_MODERATOR_LOGIN,
|
||||
LOGIN,
|
||||
LOGOUT,
|
||||
SET_TOKEN_AUTH_URL_SUCCESS,
|
||||
STOP_WAIT_FOR_OWNER,
|
||||
UPGRADE_ROLE_FINISHED,
|
||||
UPGRADE_ROLE_STARTED, WAIT_FOR_OWNER
|
||||
UPGRADE_ROLE_STARTED,
|
||||
WAIT_FOR_OWNER
|
||||
} from './actionTypes';
|
||||
import { LoginDialog, WaitForOwnerDialog } from './components';
|
||||
import logger from './logger';
|
||||
@@ -165,6 +168,30 @@ export function logout() {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables moderator login.
|
||||
*
|
||||
* @returns {{
|
||||
* type: DISABLE_MODERATOR_LOGIN
|
||||
* }}
|
||||
*/
|
||||
export function disableModeratorLogin() {
|
||||
return {
|
||||
type: DISABLE_MODERATOR_LOGIN
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables moderator login.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function enableModeratorLogin() {
|
||||
return {
|
||||
type: ENABLE_MODERATOR_LOGIN
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens {@link WaitForOnwerDialog}.
|
||||
*
|
||||
@@ -175,6 +202,7 @@ export function openWaitForOwnerDialog() {
|
||||
return openDialog(WaitForOwnerDialog);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stops waiting for the conference owner.
|
||||
*
|
||||
|
||||
@@ -67,7 +67,7 @@ class WaitForOwnerDialog extends Component<IProps> {
|
||||
<ConfirmDialog
|
||||
cancelLabel = { this.props._alternativeCancelText ? 'dialog.WaitingForHostButton' : 'dialog.Cancel' }
|
||||
confirmLabel = 'dialog.IamHost'
|
||||
descriptionKey = 'dialog.WaitForHostMsg'
|
||||
descriptionKey = 'lobby.waitForModerator'
|
||||
isConfirmHidden = { _isConfirmHidden }
|
||||
onCancel = { this._onCancel }
|
||||
onSubmit = { this._onLogin } />
|
||||
|
||||
@@ -91,7 +91,7 @@ class WaitForOwnerDialog extends PureComponent<IProps> {
|
||||
onSubmit = { this._onIAmHost }
|
||||
titleKey = { t('dialog.WaitingForHostTitle') }>
|
||||
<span>
|
||||
{ this.props._hideLoginButton ? t('dialog.WaitForHostNoAuthMsg') : t('dialog.WaitForHostMsg') }
|
||||
{ this.props._hideLoginButton ? t('dialog.WaitForHostNoAuthMsg') : t('lobby.waitForModerator') }
|
||||
</span>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -28,6 +28,8 @@ import {
|
||||
WAIT_FOR_OWNER
|
||||
} from './actionTypes';
|
||||
import {
|
||||
disableModeratorLogin,
|
||||
enableModeratorLogin,
|
||||
hideLoginDialog,
|
||||
openLoginDialog,
|
||||
openTokenAuthUrl,
|
||||
@@ -44,7 +46,7 @@ import logger from './logger';
|
||||
|
||||
/**
|
||||
* Middleware that captures connection or conference failed errors and controls
|
||||
* {@link WaitForOwnerDialog} and {@link LoginDialog}.
|
||||
* moderator login availability and {@link LoginDialog}.
|
||||
*
|
||||
* FIXME Some of the complexity was introduced by the lack of dialog stacking.
|
||||
*
|
||||
@@ -105,11 +107,21 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
}
|
||||
recoverable = error.recoverable;
|
||||
}
|
||||
if (recoverable) {
|
||||
store.dispatch(waitForOwner());
|
||||
} else {
|
||||
store.dispatch(stopWaitForOwner());
|
||||
|
||||
if (error.name === JitsiConferenceErrors.MEMBERS_ONLY_ERROR && lobbyWaitingForHost) {
|
||||
if (recoverable) {
|
||||
store.dispatch(enableModeratorLogin());
|
||||
} else {
|
||||
store.dispatch(disableModeratorLogin());
|
||||
}
|
||||
} else if (error.name === JitsiConferenceErrors.AUTHENTICATION_REQUIRED) {
|
||||
if (recoverable) {
|
||||
store.dispatch(waitForOwner());
|
||||
} else {
|
||||
store.dispatch(stopWaitForOwner());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -126,6 +138,9 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
dispatch(setTokenAuthUrlSuccess(true));
|
||||
}
|
||||
|
||||
if (_isWaitingForModerator(store)) {
|
||||
store.dispatch(disableModeratorLogin());
|
||||
}
|
||||
if (_isWaitingForOwner(store)) {
|
||||
store.dispatch(stopWaitForOwner());
|
||||
}
|
||||
@@ -134,6 +149,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
}
|
||||
|
||||
case CONFERENCE_LEFT:
|
||||
store.dispatch(disableModeratorLogin());
|
||||
store.dispatch(stopWaitForOwner());
|
||||
break;
|
||||
|
||||
@@ -236,7 +252,6 @@ function _clearExistingWaitForOwnerTimeout({ getState }: IStore) {
|
||||
waitForOwnerTimeoutID && clearTimeout(waitForOwnerTimeoutID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the cyclic "wait for conference owner" task is currently scheduled.
|
||||
*
|
||||
@@ -247,6 +262,16 @@ function _isWaitingForOwner({ getState }: IStore) {
|
||||
return Boolean(getState()['features/authentication'].waitForOwnerTimeoutID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the cyclic "wait for moderator" task is currently scheduled.
|
||||
*
|
||||
* @param {Object} store - The redux store.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function _isWaitingForModerator({ getState }: IStore) {
|
||||
return getState()['features/authentication'].showModeratorLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles login challenge. Opens login dialog or redirects to token auth URL.
|
||||
*
|
||||
|
||||
@@ -4,6 +4,8 @@ import { assign } from '../base/redux/functions';
|
||||
|
||||
import {
|
||||
CANCEL_LOGIN,
|
||||
DISABLE_MODERATOR_LOGIN,
|
||||
ENABLE_MODERATOR_LOGIN,
|
||||
SET_TOKEN_AUTH_URL_SUCCESS,
|
||||
STOP_WAIT_FOR_OWNER,
|
||||
UPGRADE_ROLE_FINISHED,
|
||||
@@ -14,6 +16,7 @@ import {
|
||||
export interface IAuthenticationState {
|
||||
error?: Object | undefined;
|
||||
progress?: number | undefined;
|
||||
showModeratorLogin?: boolean;
|
||||
thenableWithCancel?: {
|
||||
cancel: Function;
|
||||
};
|
||||
@@ -45,6 +48,11 @@ ReducerRegistry.register<IAuthenticationState>('features/authentication',
|
||||
progress: undefined,
|
||||
thenableWithCancel: undefined
|
||||
});
|
||||
case ENABLE_MODERATOR_LOGIN:
|
||||
return assign(state, {
|
||||
showModeratorLogin: true
|
||||
});
|
||||
|
||||
case SET_TOKEN_AUTH_URL_SUCCESS:
|
||||
return assign(state, {
|
||||
tokenAuthUrlSuccessful: action.value
|
||||
@@ -56,6 +64,12 @@ ReducerRegistry.register<IAuthenticationState>('features/authentication',
|
||||
waitForOwnerTimeoutID: undefined
|
||||
});
|
||||
|
||||
case DISABLE_MODERATOR_LOGIN:
|
||||
return assign(state, {
|
||||
error: undefined,
|
||||
showModeratorLogin: false
|
||||
});
|
||||
|
||||
case UPGRADE_ROLE_FINISHED: {
|
||||
let { thenableWithCancel } = action;
|
||||
|
||||
|
||||
@@ -464,6 +464,7 @@ export interface IConfig {
|
||||
lobby?: {
|
||||
autoKnock?: boolean;
|
||||
enableChat?: boolean;
|
||||
showHangUp?: boolean;
|
||||
};
|
||||
localRecording?: {
|
||||
disable?: boolean;
|
||||
|
||||
@@ -4,6 +4,7 @@ import { connect } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IReduxState } from '../../../../app/types';
|
||||
import { getLobbyConfig } from '../../../../lobby/functions';
|
||||
import DeviceStatus from '../../../../prejoin/components/web/preview/DeviceStatus';
|
||||
import { isRoomNameEnabled } from '../../../../prejoin/functions.web';
|
||||
import Toolbox from '../../../../toolbox/components/web/Toolbox';
|
||||
@@ -121,10 +122,9 @@ const useStyles = makeStyles()(theme => {
|
||||
alignItems: 'center',
|
||||
flexShrink: 0,
|
||||
boxSizing: 'border-box',
|
||||
margin: '0 48px',
|
||||
padding: '24px 0 16px',
|
||||
position: 'relative',
|
||||
width: '300px',
|
||||
width: '400px',
|
||||
height: '100%',
|
||||
zIndex: 252,
|
||||
|
||||
@@ -146,10 +146,21 @@ const useStyles = makeStyles()(theme => {
|
||||
contentControls: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
alignItems: 'stretch',
|
||||
margin: 'auto',
|
||||
width: '100%'
|
||||
},
|
||||
paddedContent: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
padding: '0 50px',
|
||||
|
||||
'& > *': {
|
||||
width: '100%',
|
||||
boxSizing: 'border-box'
|
||||
}
|
||||
},
|
||||
title: {
|
||||
...theme.typography.heading4,
|
||||
color: `${theme.palette.text01}!important`,
|
||||
@@ -220,34 +231,38 @@ const PreMeetingScreen = ({
|
||||
{_isPreCallTestEnabled && <ConnectionStatus />}
|
||||
|
||||
<div className = { classes.contentControls }>
|
||||
<h1 className = { classes.title }>
|
||||
{title}
|
||||
</h1>
|
||||
{_roomName && (
|
||||
<span className = { classes.roomNameContainer }>
|
||||
{isOverflowing ? (
|
||||
<Tooltip content = { _roomName }>
|
||||
<div className = { classes.paddedContent }>
|
||||
<h1 className = { classes.title }>
|
||||
{title}
|
||||
</h1>
|
||||
{_roomName && (
|
||||
<span className = { classes.roomNameContainer }>
|
||||
{isOverflowing ? (
|
||||
<Tooltip content = { _roomName }>
|
||||
<span
|
||||
className = { classes.roomName }
|
||||
ref = { roomNameRef }>
|
||||
{_roomName}
|
||||
</span>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<span
|
||||
className = { classes.roomName }
|
||||
ref = { roomNameRef }>
|
||||
{_roomName}
|
||||
</span>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<span
|
||||
className = { classes.roomName }
|
||||
ref = { roomNameRef }>
|
||||
{_roomName}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
{children}
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
{_buttons.length && <Toolbox toolbarButtons = { _buttons } />}
|
||||
{skipPrejoinButton}
|
||||
{showUnsafeRoomWarning && <UnsafeRoomWarning />}
|
||||
{showDeviceStatus && <DeviceStatus />}
|
||||
{showRecordingWarning && <RecordingWarning />}
|
||||
<div className = { classes.paddedContent }>
|
||||
{skipPrejoinButton}
|
||||
{showUnsafeRoomWarning && <UnsafeRoomWarning />}
|
||||
{showDeviceStatus && <DeviceStatus />}
|
||||
{showRecordingWarning && <RecordingWarning />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -269,10 +284,16 @@ const PreMeetingScreen = ({
|
||||
function mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) {
|
||||
const { hiddenPremeetingButtons } = state['features/base/config'];
|
||||
const { toolbarButtons } = state['features/toolbox'];
|
||||
const { showHangUp = true } = getLobbyConfig(state);
|
||||
const { knocking } = state['features/lobby'];
|
||||
const premeetingButtons = (ownProps.thirdParty
|
||||
? THIRD_PARTY_PREJOIN_BUTTONS
|
||||
: PREMEETING_BUTTONS).filter((b: any) => !(hiddenPremeetingButtons || []).includes(b));
|
||||
|
||||
if (showHangUp && knocking && !premeetingButtons.includes('hangup')) {
|
||||
premeetingButtons.push('hangup');
|
||||
}
|
||||
|
||||
const { premeetingBackground } = state['features/dynamic-branding'];
|
||||
|
||||
return {
|
||||
|
||||
@@ -13,6 +13,7 @@ import { updateSettings } from '../../base/settings/actions';
|
||||
import { IMessage } from '../../chat/types';
|
||||
import { isDeviceStatusVisible } from '../../prejoin/functions';
|
||||
import { cancelKnocking, joinWithPassword, onSendMessage, setPasswordJoinFailed, startKnocking } from '../actions';
|
||||
import { getLobbyConfig } from '../functions';
|
||||
|
||||
export const SCREEN_STATES = {
|
||||
EDIT: 1,
|
||||
@@ -27,6 +28,11 @@ export interface IProps {
|
||||
*/
|
||||
_deviceStatusVisible: boolean;
|
||||
|
||||
/**
|
||||
* Whether to show the hangup button.
|
||||
*/
|
||||
_hangUp?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates whether the message that display name is required is shown.
|
||||
*/
|
||||
@@ -52,6 +58,11 @@ export interface IProps {
|
||||
*/
|
||||
_lobbyMessageRecipient?: string;
|
||||
|
||||
/**
|
||||
* Whether to hide the login button.
|
||||
*/
|
||||
_login?: boolean;
|
||||
|
||||
/**
|
||||
* The name of the meeting we're about to join.
|
||||
*/
|
||||
@@ -445,8 +456,10 @@ export function _mapStateToProps(state: IReduxState) {
|
||||
const { disableLobbyPassword } = getSecurityUiConfig(state);
|
||||
const showCopyUrlButton = inviteEnabledFlag || !disableInviteFunctions;
|
||||
const deviceStatusVisible = isDeviceStatusVisible(state);
|
||||
const { showHangUp = true } = getLobbyConfig(state);
|
||||
const { membersOnly, lobbyWaitingForHost } = state['features/base/conference'];
|
||||
const { isLobbyChatActive, lobbyMessageRecipient, messages } = state['features/chat'];
|
||||
const { showModeratorLogin } = state['features/authentication'];
|
||||
|
||||
return {
|
||||
_deviceStatusVisible: deviceStatusVisible,
|
||||
@@ -454,6 +467,8 @@ export function _mapStateToProps(state: IReduxState) {
|
||||
_knocking: knocking,
|
||||
_lobbyChatMessages: messages,
|
||||
_lobbyMessageRecipient: lobbyMessageRecipient?.name,
|
||||
_login: showModeratorLogin,
|
||||
_hangUp: showHangUp,
|
||||
_isLobbyChatActive: isLobbyChatActive,
|
||||
_meetingName: getConferenceName(state),
|
||||
_membersOnlyConference: membersOnly,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Text, TextStyle, View, ViewStyle } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { login } from '../../../authentication/actions.any';
|
||||
import { getConferenceName } from '../../../base/conference/functions';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import JitsiScreen from '../../../base/modal/components/JitsiScreen';
|
||||
@@ -18,6 +19,7 @@ import { navigate }
|
||||
from '../../../mobile/navigation/components/lobby/LobbyNavigationContainerRef';
|
||||
import { screen } from '../../../mobile/navigation/routes';
|
||||
import { preJoinStyles } from '../../../prejoin/components/native/styles';
|
||||
import HangupButton from '../../../toolbox/components/HangupButton';
|
||||
import AudioMuteButton from '../../../toolbox/components/native/AudioMuteButton';
|
||||
import VideoMuteButton from '../../../toolbox/components/native/VideoMuteButton';
|
||||
import AbstractLobbyScreen, {
|
||||
@@ -43,6 +45,18 @@ interface IProps extends AbstractProps {
|
||||
* Implements a waiting screen that represents the participant being in the lobby.
|
||||
*/
|
||||
class LobbyScreen extends AbstractLobbyScreen<IProps> {
|
||||
/**
|
||||
* Initializes a new LobbyScreen instance.
|
||||
*
|
||||
* @param {IProps} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this._onLogin = this._onLogin.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements {@code PureComponent#render}.
|
||||
*
|
||||
@@ -197,12 +211,19 @@ class LobbyScreen extends AbstractLobbyScreen<IProps> {
|
||||
* @inheritdoc
|
||||
*/
|
||||
_renderToolbarButtons() {
|
||||
const { _hangUp } = this.props;
|
||||
|
||||
return (
|
||||
<View style = { preJoinStyles.toolboxContainer as ViewStyle }>
|
||||
<AudioMuteButton
|
||||
styles = { preJoinStyles.buttonStylesBorderless } />
|
||||
<VideoMuteButton
|
||||
styles = { preJoinStyles.buttonStylesBorderless } />
|
||||
{
|
||||
_hangUp
|
||||
&& <HangupButton
|
||||
styles = { preJoinStyles.buttonStylesBorderless } />
|
||||
}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -213,7 +234,7 @@ class LobbyScreen extends AbstractLobbyScreen<IProps> {
|
||||
* @inheritdoc
|
||||
*/
|
||||
_renderStandardButtons() {
|
||||
const { _knocking, _renderPassword, _isLobbyChatActive } = this.props;
|
||||
const { _knocking, _renderPassword, _isLobbyChatActive, _login } = this.props;
|
||||
const { displayName } = this.state;
|
||||
|
||||
return (
|
||||
@@ -246,9 +267,28 @@ class LobbyScreen extends AbstractLobbyScreen<IProps> {
|
||||
style = { preJoinStyles.joinButton }
|
||||
type = { BUTTON_TYPES.PRIMARY } />
|
||||
}
|
||||
{
|
||||
_login
|
||||
&& <Button
|
||||
accessibilityLabel = 'dialog.IamHost'
|
||||
labelKey = 'dialog.IamHost'
|
||||
onClick = { this._onLogin }
|
||||
style = { preJoinStyles.joinButton }
|
||||
type = { BUTTON_TYPES.PRIMARY } />
|
||||
}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles login button click.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onLogin() {
|
||||
this.props.dispatch(login());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { login } from '../../../authentication/actions.any';
|
||||
import { leaveConference } from '../../../base/conference/actions';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconCloseLarge } from '../../../base/icons/svg';
|
||||
@@ -8,6 +10,7 @@ import PreMeetingScreen from '../../../base/premeeting/components/web/PreMeeting
|
||||
import LoadingIndicator from '../../../base/react/components/web/LoadingIndicator';
|
||||
import Button from '../../../base/ui/components/web/Button';
|
||||
import Input from '../../../base/ui/components/web/Input';
|
||||
import { BUTTON_TYPES } from '../../../base/ui/constants.any';
|
||||
import ChatInput from '../../../chat/components/web/ChatInput';
|
||||
import MessageContainer from '../../../chat/components/web/MessageContainer';
|
||||
import AbstractLobbyScreen, {
|
||||
@@ -35,6 +38,10 @@ class LobbyScreen extends AbstractLobbyScreen<IProps> {
|
||||
super(props);
|
||||
|
||||
this._messageContainerRef = React.createRef<MessageContainer>();
|
||||
|
||||
// Bind authentication methods
|
||||
this._onLogin = this._onLogin.bind(this);
|
||||
this._onHangup = this._onHangup.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,7 +91,7 @@ class LobbyScreen extends AbstractLobbyScreen<IProps> {
|
||||
* @inheritdoc
|
||||
*/
|
||||
override _renderJoining() {
|
||||
const { _isLobbyChatActive } = this.props;
|
||||
const { _login, _isLobbyChatActive } = this.props;
|
||||
|
||||
return (
|
||||
<div className = 'lobby-screen-content'>
|
||||
@@ -96,7 +103,7 @@ class LobbyScreen extends AbstractLobbyScreen<IProps> {
|
||||
<LoadingIndicator size = 'large' />
|
||||
</div>
|
||||
<span className = 'joining-message'>
|
||||
{ this.props.t('lobby.joiningMessage') }
|
||||
{ this.props.t(_login ? 'lobby.waitForModerator' : 'lobby.joiningMessage') }
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
@@ -215,14 +222,14 @@ class LobbyScreen extends AbstractLobbyScreen<IProps> {
|
||||
labelKey = 'prejoin.joinMeeting'
|
||||
onClick = { this._onJoinWithPassword }
|
||||
testId = 'lobby.passwordJoinButton'
|
||||
type = 'primary' />
|
||||
type = { BUTTON_TYPES.PRIMARY } />
|
||||
<Button
|
||||
className = 'lobby-button-margin'
|
||||
fullWidth = { true }
|
||||
labelKey = 'lobby.backToKnockModeButton'
|
||||
onClick = { this._onSwitchToKnockMode }
|
||||
testId = 'lobby.backToKnockModeButton'
|
||||
type = 'secondary' />
|
||||
type = { BUTTON_TYPES.SECONDARY } />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -233,7 +240,7 @@ class LobbyScreen extends AbstractLobbyScreen<IProps> {
|
||||
* @inheritdoc
|
||||
*/
|
||||
override _renderStandardButtons() {
|
||||
const { _knocking, _isLobbyChatActive, _renderPassword } = this.props;
|
||||
const { _knocking, _login, _isLobbyChatActive, _renderPassword } = this.props;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -260,7 +267,15 @@ class LobbyScreen extends AbstractLobbyScreen<IProps> {
|
||||
labelKey = 'lobby.enterPasswordButton'
|
||||
onClick = { this._onSwitchToPasswordMode }
|
||||
testId = 'lobby.enterPasswordButton'
|
||||
type = 'secondary' />
|
||||
type = { BUTTON_TYPES.SECONDARY } />
|
||||
}
|
||||
{_login && <Button
|
||||
className = 'lobby-button-margin'
|
||||
fullWidth = { true }
|
||||
labelKey = 'dialog.IamHost'
|
||||
onClick = { this._onLogin }
|
||||
testId = 'lobby.loginButton'
|
||||
type = { BUTTON_TYPES.PRIMARY } />
|
||||
}
|
||||
</>
|
||||
);
|
||||
@@ -279,6 +294,26 @@ class LobbyScreen extends AbstractLobbyScreen<IProps> {
|
||||
this._messageContainerRef.current.scrollToElement(withAnimation, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles login button click.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onLogin() {
|
||||
this.props.dispatch(login());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles hangup button click.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onHangup() {
|
||||
this.props.dispatch(leaveConference());
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(connect(_mapStateToProps)(LobbyScreen));
|
||||
|
||||
@@ -33,12 +33,14 @@ import { BUTTON_TYPES } from '../../../base/ui/constants.native';
|
||||
import { openDisplayNamePrompt } from '../../../display-name/actions';
|
||||
import BrandingImageBackground from '../../../dynamic-branding/components/native/BrandingImageBackground';
|
||||
import LargeVideo from '../../../large-video/components/LargeVideo.native';
|
||||
import { getLobbyConfig } from '../../../lobby/functions';
|
||||
import HeaderNavigationButton from '../../../mobile/navigation/components/HeaderNavigationButton';
|
||||
import { navigateRoot } from '../../../mobile/navigation/rootNavigationContainerRef';
|
||||
import { screen } from '../../../mobile/navigation/routes';
|
||||
import HangupButton from '../../../toolbox/components/HangupButton';
|
||||
import AudioMuteButton from '../../../toolbox/components/native/AudioMuteButton';
|
||||
import VideoMuteButton from '../../../toolbox/components/native/VideoMuteButton';
|
||||
import { isDisplayNameRequired, isRoomNameEnabled } from '../../functions';
|
||||
import { isDisplayNameRequired, isRoomNameEnabled } from '../../functions.native';
|
||||
import { IPrejoinProps } from '../../types';
|
||||
import { hasDisplayName } from '../../utils';
|
||||
|
||||
@@ -59,6 +61,8 @@ const Prejoin: React.FC<IPrejoinProps> = ({ navigation }: IPrejoinProps) => {
|
||||
const isDisplayNameReadonly = useSelector(isNameReadOnly);
|
||||
const roomName = useSelector((state: IReduxState) => getConferenceName(state));
|
||||
const roomNameEnabled = useSelector((state: IReduxState) => isRoomNameEnabled(state));
|
||||
const { showHangUp = true } = useSelector((state: IReduxState) => getLobbyConfig(state));
|
||||
const { knocking } = useSelector((state: IReduxState) => state['features/lobby']);
|
||||
const participantName = localParticipant?.name;
|
||||
const [ displayName, setDisplayName ]
|
||||
= useState(participantName || '');
|
||||
@@ -185,6 +189,11 @@ const Prejoin: React.FC<IPrejoinProps> = ({ navigation }: IPrejoinProps) => {
|
||||
styles = { styles.buttonStylesBorderless } />
|
||||
<VideoMuteButton
|
||||
styles = { styles.buttonStylesBorderless } />
|
||||
{
|
||||
showHangUp && knocking
|
||||
&& <HangupButton
|
||||
styles = { styles.buttonStylesBorderless } />
|
||||
}
|
||||
</View>
|
||||
{
|
||||
showDisplayNameInput && <Input
|
||||
|
||||
@@ -74,8 +74,8 @@ export const preJoinStyles = {
|
||||
height: 60,
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: BaseTheme.spacing[3],
|
||||
paddingHorizontal: BaseTheme.spacing[2],
|
||||
width: 148
|
||||
padding: BaseTheme.spacing[2],
|
||||
width: 'auto'
|
||||
},
|
||||
|
||||
customInput: {
|
||||
|
||||
@@ -228,7 +228,7 @@ class Whiteboard extends PureComponent<IProps> {
|
||||
|
||||
/**
|
||||
* Maps (parts of) the redux state to the associated
|
||||
* {@code WaitForOwnerDialog}'s props.
|
||||
* {@code Whiteboard}'s props.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @private
|
||||
|
||||
Reference in New Issue
Block a user