feat(config): Add config option for making display name read only

This commit is contained in:
Vlad Piersec 2021-09-06 13:01:13 +03:00 committed by vp8x8
parent 8fd7b10f06
commit fc6e8fd4b9
8 changed files with 51 additions and 10 deletions

View File

@ -476,6 +476,10 @@ var config = {
// When 'true', it shows an intermediate page before joining, where the user can configure their devices.
// prejoinPageEnabled: false,
// When 'true', the user cannot edit the display name.
// (Mainly useful when used in conjuction with the JWT so the JWT name becomes read only.)
// readOnlyName: false,
// If etherpad integration is enabled, setting this to true will
// automatically open the etherpad when a participant joins. This
// does not affect the mobile app since opening an etherpad

View File

@ -175,6 +175,7 @@ export default [
'requireDisplayName',
'remoteVideoMenu',
'roomPasswordNumberOfDigits',
'readOnlyName',
'replaceParticipant',
'resolution',
'startAudioMuted',

View File

@ -152,6 +152,18 @@ export function getWhitelistedJSON(configName: string, configJSON: Object): Obje
return configJSON;
}
/**
* Selector for determining if the display name is read only.
*
* @param {Object} state - The state of the app.
* @returns {boolean}
*/
export function isNameReadOnly(state: Object): boolean {
return state['features/base/config'].disableProfile
|| state['features/base/config'].readOnlyName;
}
/**
* Restores a Jitsi Meet config.js from {@code localStorage} if it was
* previously downloaded from a specific {@code baseURL} and stored with

View File

@ -36,6 +36,11 @@ type Props = {
*/
placeHolder: string,
/**
* Whether the input is read only or not.
*/
readOnly?: boolean,
/**
* The field type (e.g. text, password...etc).
*/
@ -126,6 +131,7 @@ export default class InputField extends PureComponent<Props, State> {
onFocus = { this._onFocus }
onKeyDown = { this._onKeyDown }
placeholder = { this.props.placeHolder }
readOnly = { this.props.readOnly }
type = { this.props.type }
value = { this.state.value } />
);

View File

@ -5,6 +5,7 @@ import React, { Component } from 'react';
import { createScreenSharingIssueEvent, sendAnalytics } from '../../../analytics';
import { AudioLevelIndicator } from '../../../audio-level-indicator';
import { Avatar } from '../../../base/avatar';
import { isNameReadOnly } from '../../../base/config';
import { isMobileBrowser } from '../../../base/environment/utils';
import JitsiMeetJS from '../../../base/lib-jitsi-meet/_';
import { MEDIA_TYPE, VideoTrack } from '../../../base/media';
@ -73,6 +74,11 @@ export type State = {|
*/
export type Props = {|
/**
* If the display name is editable or not.
*/
_allowEditing: boolean,
/**
* The audio track related to the participant.
*/
@ -103,11 +109,6 @@ export type Props = {|
*/
_disableLocalVideoFlip: boolean,
/**
* Indicates whether the profile functionality is disabled.
*/
_disableProfile: boolean,
/**
* The display mode of the thumbnail.
*/
@ -763,13 +764,13 @@ class Thumbnail extends Component<Props, State> {
*/
_renderLocalParticipant() {
const {
_allowEditing,
_defaultLocalDisplayName,
_disableLocalVideoFlip,
_isMobile,
_isMobilePortrait,
_isScreenSharing,
_localFlipX,
_disableProfile,
_participant,
_videoTrack
} = this.props;
@ -820,7 +821,7 @@ class Thumbnail extends Component<Props, State> {
className = 'displayNameContainer'
onClick = { onClick }>
<DisplayName
allowEditing = { !_disableProfile }
allowEditing = { _allowEditing }
displayNameSuffix = { _defaultLocalDisplayName }
elementID = 'localDisplayName'
participantID = { id } />
@ -1053,7 +1054,6 @@ function _mapStateToProps(state, ownProps): Object {
const {
startSilent,
disableLocalVideoFlip,
disableProfile,
iAmRecorder,
iAmSipGateway
} = state['features/base/config'];
@ -1102,6 +1102,7 @@ function _mapStateToProps(state, ownProps): Object {
}
return {
_allowEditing: !isNameReadOnly(state),
_audioTrack,
_connectionIndicatorAutoHideEnabled:
Boolean(state['features/base/config'].connectionIndicators?.autoHide ?? true),
@ -1110,7 +1111,6 @@ function _mapStateToProps(state, ownProps): Object {
_currentLayout,
_defaultLocalDisplayName: interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME,
_disableLocalVideoFlip: Boolean(disableLocalVideoFlip),
_disableProfile: disableProfile,
_isHidden: isLocal && iAmRecorder && !iAmSipGateway,
_isAudioOnly: Boolean(state['features/base/audio-only'].enabled),
_isCurrentlyOnLargeVideo: state['features/large-video']?.participantId === id,

View File

@ -4,6 +4,7 @@ import InlineDialog from '@atlaskit/inline-dialog';
import React, { Component } from 'react';
import { getRoomName } from '../../base/conference';
import { isNameReadOnly } from '../../base/config';
import { translate } from '../../base/i18n';
import { Icon, IconArrowDown, IconArrowUp, IconPhone, IconVolumeOff } from '../../base/icons';
import { isVideoMutedByUser } from '../../base/media';
@ -57,6 +58,11 @@ type Props = {
*/
updateSettings: Function,
/**
* Whether the name input should be read only or not.
*/
readOnlyName: boolean,
/**
* The name of the meeting that is about to be joined.
*/
@ -283,6 +289,7 @@ class Prejoin extends Component<Props, State> {
joinConference,
joinConferenceWithoutAudio,
name,
readOnlyName,
showCameraPreview,
showDialog,
t,
@ -310,6 +317,7 @@ class Prejoin extends Component<Props, State> {
onChange = { _setName }
onSubmit = { joinConference }
placeHolder = { t('dialog.enterDisplayName') }
readOnly = { readOnlyName }
value = { name } />
{showError && <div
@ -393,6 +401,7 @@ function mapStateToProps(state): Object {
showDialog: isJoinByPhoneDialogVisible(state),
showErrorOnJoin,
hasJoinByPhoneButton: isJoinByPhoneButtonVisible(state),
readOnlyName: isNameReadOnly(state),
showCameraPreview: !isVideoMutedByUser(state),
videoTrack: getLocalJitsiVideoTrack(state)
};

View File

@ -42,6 +42,11 @@ export type Props = {
*/
email: string,
/**
* If the display name is read only.
*/
readOnlyName: boolean,
/**
* Invoked to obtain translated strings.
*/
@ -111,6 +116,7 @@ class ProfileTab extends AbstractDialogTab<Props> {
authEnabled,
displayName,
email,
readOnlyName,
t
} = this.props;
@ -122,6 +128,7 @@ class ProfileTab extends AbstractDialogTab<Props> {
autoComplete = 'name'
compact = { true }
id = 'setDisplayName'
isReadOnly = { readOnlyName }
label = { t('profile.setDisplayNameLabel') }
onChange = { this._onDisplayNameChange }
placeholder = { t('settings.name') }

View File

@ -1,5 +1,6 @@
// @flow
import { isNameReadOnly } from '../base/config';
import { SERVER_URL_CHANGE_ENABLED, getFeatureFlag } from '../base/flags';
import { i18next, DEFAULT_LANGUAGE, LANGUAGES } from '../base/i18n';
import { createLocalTrack } from '../base/lib-jitsi-meet/functions';
@ -153,7 +154,8 @@ export function getProfileTabProps(stateful: Object | Function) {
authEnabled: Boolean(conference && authEnabled),
authLogin,
displayName: localParticipant.name,
email: localParticipant.email
email: localParticipant.email,
readOnlyName: isNameReadOnly(state)
};
}