feat(config): Add config option for making display name read only
This commit is contained in:
parent
8fd7b10f06
commit
fc6e8fd4b9
|
@ -476,6 +476,10 @@ var config = {
|
||||||
// When 'true', it shows an intermediate page before joining, where the user can configure their devices.
|
// When 'true', it shows an intermediate page before joining, where the user can configure their devices.
|
||||||
// prejoinPageEnabled: false,
|
// 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
|
// If etherpad integration is enabled, setting this to true will
|
||||||
// automatically open the etherpad when a participant joins. This
|
// automatically open the etherpad when a participant joins. This
|
||||||
// does not affect the mobile app since opening an etherpad
|
// does not affect the mobile app since opening an etherpad
|
||||||
|
|
|
@ -175,6 +175,7 @@ export default [
|
||||||
'requireDisplayName',
|
'requireDisplayName',
|
||||||
'remoteVideoMenu',
|
'remoteVideoMenu',
|
||||||
'roomPasswordNumberOfDigits',
|
'roomPasswordNumberOfDigits',
|
||||||
|
'readOnlyName',
|
||||||
'replaceParticipant',
|
'replaceParticipant',
|
||||||
'resolution',
|
'resolution',
|
||||||
'startAudioMuted',
|
'startAudioMuted',
|
||||||
|
|
|
@ -152,6 +152,18 @@ export function getWhitelistedJSON(configName: string, configJSON: Object): Obje
|
||||||
return configJSON;
|
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
|
* Restores a Jitsi Meet config.js from {@code localStorage} if it was
|
||||||
* previously downloaded from a specific {@code baseURL} and stored with
|
* previously downloaded from a specific {@code baseURL} and stored with
|
||||||
|
|
|
@ -36,6 +36,11 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
placeHolder: string,
|
placeHolder: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the input is read only or not.
|
||||||
|
*/
|
||||||
|
readOnly?: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The field type (e.g. text, password...etc).
|
* The field type (e.g. text, password...etc).
|
||||||
*/
|
*/
|
||||||
|
@ -126,6 +131,7 @@ export default class InputField extends PureComponent<Props, State> {
|
||||||
onFocus = { this._onFocus }
|
onFocus = { this._onFocus }
|
||||||
onKeyDown = { this._onKeyDown }
|
onKeyDown = { this._onKeyDown }
|
||||||
placeholder = { this.props.placeHolder }
|
placeholder = { this.props.placeHolder }
|
||||||
|
readOnly = { this.props.readOnly }
|
||||||
type = { this.props.type }
|
type = { this.props.type }
|
||||||
value = { this.state.value } />
|
value = { this.state.value } />
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import React, { Component } from 'react';
|
||||||
import { createScreenSharingIssueEvent, sendAnalytics } from '../../../analytics';
|
import { createScreenSharingIssueEvent, sendAnalytics } from '../../../analytics';
|
||||||
import { AudioLevelIndicator } from '../../../audio-level-indicator';
|
import { AudioLevelIndicator } from '../../../audio-level-indicator';
|
||||||
import { Avatar } from '../../../base/avatar';
|
import { Avatar } from '../../../base/avatar';
|
||||||
|
import { isNameReadOnly } from '../../../base/config';
|
||||||
import { isMobileBrowser } from '../../../base/environment/utils';
|
import { isMobileBrowser } from '../../../base/environment/utils';
|
||||||
import JitsiMeetJS from '../../../base/lib-jitsi-meet/_';
|
import JitsiMeetJS from '../../../base/lib-jitsi-meet/_';
|
||||||
import { MEDIA_TYPE, VideoTrack } from '../../../base/media';
|
import { MEDIA_TYPE, VideoTrack } from '../../../base/media';
|
||||||
|
@ -73,6 +74,11 @@ export type State = {|
|
||||||
*/
|
*/
|
||||||
export type Props = {|
|
export type Props = {|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the display name is editable or not.
|
||||||
|
*/
|
||||||
|
_allowEditing: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The audio track related to the participant.
|
* The audio track related to the participant.
|
||||||
*/
|
*/
|
||||||
|
@ -103,11 +109,6 @@ export type Props = {|
|
||||||
*/
|
*/
|
||||||
_disableLocalVideoFlip: boolean,
|
_disableLocalVideoFlip: boolean,
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates whether the profile functionality is disabled.
|
|
||||||
*/
|
|
||||||
_disableProfile: boolean,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The display mode of the thumbnail.
|
* The display mode of the thumbnail.
|
||||||
*/
|
*/
|
||||||
|
@ -763,13 +764,13 @@ class Thumbnail extends Component<Props, State> {
|
||||||
*/
|
*/
|
||||||
_renderLocalParticipant() {
|
_renderLocalParticipant() {
|
||||||
const {
|
const {
|
||||||
|
_allowEditing,
|
||||||
_defaultLocalDisplayName,
|
_defaultLocalDisplayName,
|
||||||
_disableLocalVideoFlip,
|
_disableLocalVideoFlip,
|
||||||
_isMobile,
|
_isMobile,
|
||||||
_isMobilePortrait,
|
_isMobilePortrait,
|
||||||
_isScreenSharing,
|
_isScreenSharing,
|
||||||
_localFlipX,
|
_localFlipX,
|
||||||
_disableProfile,
|
|
||||||
_participant,
|
_participant,
|
||||||
_videoTrack
|
_videoTrack
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
@ -820,7 +821,7 @@ class Thumbnail extends Component<Props, State> {
|
||||||
className = 'displayNameContainer'
|
className = 'displayNameContainer'
|
||||||
onClick = { onClick }>
|
onClick = { onClick }>
|
||||||
<DisplayName
|
<DisplayName
|
||||||
allowEditing = { !_disableProfile }
|
allowEditing = { _allowEditing }
|
||||||
displayNameSuffix = { _defaultLocalDisplayName }
|
displayNameSuffix = { _defaultLocalDisplayName }
|
||||||
elementID = 'localDisplayName'
|
elementID = 'localDisplayName'
|
||||||
participantID = { id } />
|
participantID = { id } />
|
||||||
|
@ -1053,7 +1054,6 @@ function _mapStateToProps(state, ownProps): Object {
|
||||||
const {
|
const {
|
||||||
startSilent,
|
startSilent,
|
||||||
disableLocalVideoFlip,
|
disableLocalVideoFlip,
|
||||||
disableProfile,
|
|
||||||
iAmRecorder,
|
iAmRecorder,
|
||||||
iAmSipGateway
|
iAmSipGateway
|
||||||
} = state['features/base/config'];
|
} = state['features/base/config'];
|
||||||
|
@ -1102,6 +1102,7 @@ function _mapStateToProps(state, ownProps): Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
_allowEditing: !isNameReadOnly(state),
|
||||||
_audioTrack,
|
_audioTrack,
|
||||||
_connectionIndicatorAutoHideEnabled:
|
_connectionIndicatorAutoHideEnabled:
|
||||||
Boolean(state['features/base/config'].connectionIndicators?.autoHide ?? true),
|
Boolean(state['features/base/config'].connectionIndicators?.autoHide ?? true),
|
||||||
|
@ -1110,7 +1111,6 @@ function _mapStateToProps(state, ownProps): Object {
|
||||||
_currentLayout,
|
_currentLayout,
|
||||||
_defaultLocalDisplayName: interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME,
|
_defaultLocalDisplayName: interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME,
|
||||||
_disableLocalVideoFlip: Boolean(disableLocalVideoFlip),
|
_disableLocalVideoFlip: Boolean(disableLocalVideoFlip),
|
||||||
_disableProfile: disableProfile,
|
|
||||||
_isHidden: isLocal && iAmRecorder && !iAmSipGateway,
|
_isHidden: isLocal && iAmRecorder && !iAmSipGateway,
|
||||||
_isAudioOnly: Boolean(state['features/base/audio-only'].enabled),
|
_isAudioOnly: Boolean(state['features/base/audio-only'].enabled),
|
||||||
_isCurrentlyOnLargeVideo: state['features/large-video']?.participantId === id,
|
_isCurrentlyOnLargeVideo: state['features/large-video']?.participantId === id,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import InlineDialog from '@atlaskit/inline-dialog';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
import { getRoomName } from '../../base/conference';
|
import { getRoomName } from '../../base/conference';
|
||||||
|
import { isNameReadOnly } from '../../base/config';
|
||||||
import { translate } from '../../base/i18n';
|
import { translate } from '../../base/i18n';
|
||||||
import { Icon, IconArrowDown, IconArrowUp, IconPhone, IconVolumeOff } from '../../base/icons';
|
import { Icon, IconArrowDown, IconArrowUp, IconPhone, IconVolumeOff } from '../../base/icons';
|
||||||
import { isVideoMutedByUser } from '../../base/media';
|
import { isVideoMutedByUser } from '../../base/media';
|
||||||
|
@ -57,6 +58,11 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
updateSettings: Function,
|
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.
|
* The name of the meeting that is about to be joined.
|
||||||
*/
|
*/
|
||||||
|
@ -283,6 +289,7 @@ class Prejoin extends Component<Props, State> {
|
||||||
joinConference,
|
joinConference,
|
||||||
joinConferenceWithoutAudio,
|
joinConferenceWithoutAudio,
|
||||||
name,
|
name,
|
||||||
|
readOnlyName,
|
||||||
showCameraPreview,
|
showCameraPreview,
|
||||||
showDialog,
|
showDialog,
|
||||||
t,
|
t,
|
||||||
|
@ -310,6 +317,7 @@ class Prejoin extends Component<Props, State> {
|
||||||
onChange = { _setName }
|
onChange = { _setName }
|
||||||
onSubmit = { joinConference }
|
onSubmit = { joinConference }
|
||||||
placeHolder = { t('dialog.enterDisplayName') }
|
placeHolder = { t('dialog.enterDisplayName') }
|
||||||
|
readOnly = { readOnlyName }
|
||||||
value = { name } />
|
value = { name } />
|
||||||
|
|
||||||
{showError && <div
|
{showError && <div
|
||||||
|
@ -393,6 +401,7 @@ function mapStateToProps(state): Object {
|
||||||
showDialog: isJoinByPhoneDialogVisible(state),
|
showDialog: isJoinByPhoneDialogVisible(state),
|
||||||
showErrorOnJoin,
|
showErrorOnJoin,
|
||||||
hasJoinByPhoneButton: isJoinByPhoneButtonVisible(state),
|
hasJoinByPhoneButton: isJoinByPhoneButtonVisible(state),
|
||||||
|
readOnlyName: isNameReadOnly(state),
|
||||||
showCameraPreview: !isVideoMutedByUser(state),
|
showCameraPreview: !isVideoMutedByUser(state),
|
||||||
videoTrack: getLocalJitsiVideoTrack(state)
|
videoTrack: getLocalJitsiVideoTrack(state)
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,6 +42,11 @@ export type Props = {
|
||||||
*/
|
*/
|
||||||
email: string,
|
email: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the display name is read only.
|
||||||
|
*/
|
||||||
|
readOnlyName: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked to obtain translated strings.
|
* Invoked to obtain translated strings.
|
||||||
*/
|
*/
|
||||||
|
@ -111,6 +116,7 @@ class ProfileTab extends AbstractDialogTab<Props> {
|
||||||
authEnabled,
|
authEnabled,
|
||||||
displayName,
|
displayName,
|
||||||
email,
|
email,
|
||||||
|
readOnlyName,
|
||||||
t
|
t
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -122,6 +128,7 @@ class ProfileTab extends AbstractDialogTab<Props> {
|
||||||
autoComplete = 'name'
|
autoComplete = 'name'
|
||||||
compact = { true }
|
compact = { true }
|
||||||
id = 'setDisplayName'
|
id = 'setDisplayName'
|
||||||
|
isReadOnly = { readOnlyName }
|
||||||
label = { t('profile.setDisplayNameLabel') }
|
label = { t('profile.setDisplayNameLabel') }
|
||||||
onChange = { this._onDisplayNameChange }
|
onChange = { this._onDisplayNameChange }
|
||||||
placeholder = { t('settings.name') }
|
placeholder = { t('settings.name') }
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
|
import { isNameReadOnly } from '../base/config';
|
||||||
import { SERVER_URL_CHANGE_ENABLED, getFeatureFlag } from '../base/flags';
|
import { SERVER_URL_CHANGE_ENABLED, getFeatureFlag } from '../base/flags';
|
||||||
import { i18next, DEFAULT_LANGUAGE, LANGUAGES } from '../base/i18n';
|
import { i18next, DEFAULT_LANGUAGE, LANGUAGES } from '../base/i18n';
|
||||||
import { createLocalTrack } from '../base/lib-jitsi-meet/functions';
|
import { createLocalTrack } from '../base/lib-jitsi-meet/functions';
|
||||||
|
@ -153,7 +154,8 @@ export function getProfileTabProps(stateful: Object | Function) {
|
||||||
authEnabled: Boolean(conference && authEnabled),
|
authEnabled: Boolean(conference && authEnabled),
|
||||||
authLogin,
|
authLogin,
|
||||||
displayName: localParticipant.name,
|
displayName: localParticipant.name,
|
||||||
email: localParticipant.email
|
email: localParticipant.email,
|
||||||
|
readOnlyName: isNameReadOnly(state)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue