From 5c67e8b4cec35b6132b61bf13ed8cf2107852bfd Mon Sep 17 00:00:00 2001 From: Calin Chitu Date: Fri, 26 Nov 2021 17:39:34 +0200 Subject: [PATCH] feat(config) defaultLocalDisplayName and defaultRemoteDisplayName --- conference.js | 49 ++----------------- config.js | 6 +++ interface_config.js | 8 ++- modules/UI/videolayout/LargeVideoManager.js | 9 +++- react/features/base/config/configWhitelist.js | 2 + react/features/base/config/reducer.js | 18 +++++++ react/features/base/participants/functions.js | 16 +++--- react/features/base/participants/reducer.js | 20 +++++--- react/features/external-api/middleware.js | 8 +-- react/features/external-api/subscriber.js | 5 +- .../filmstrip/components/web/Thumbnail.js | 3 +- .../toolbox/components/web/ProfileButton.js | 17 +++++-- 12 files changed, 86 insertions(+), 75 deletions(-) diff --git a/conference.js b/conference.js index d6fd9872a7..11d1b575f4 100644 --- a/conference.js +++ b/conference.js @@ -86,7 +86,6 @@ import { dominantSpeakerChanged, getLocalParticipant, getNormalizedDisplayName, - getParticipantById, localParticipantConnectionStatusChanged, localParticipantRoleChanged, participantConnectionStatusChanged, @@ -235,17 +234,6 @@ function sendData(command, value) { room.sendCommand(command, { value }); } -/** - * Get user nickname by user id. - * @param {string} id user id - * @returns {string?} user nickname or undefined if user is unknown. - */ -function getDisplayName(id) { - const participant = getParticipantById(APP.store.getState(), id); - - return participant && participant.name; -} - /** * Mute or unmute local audio stream if it exists. * @param {boolean} muted - if audio stream should be muted or unmuted. @@ -1218,14 +1206,6 @@ export default { return room.isConnectionInterrupted(); }, - /** - * Obtains the local display name. - * @returns {string|undefined} - */ - getLocalDisplayName() { - return getDisplayName(this.getMyUserId()); - }, - /** * Finds JitsiParticipant for given id. * @@ -1238,29 +1218,6 @@ export default { return room ? room.getParticipantById(id) : null; }, - /** - * Gets the display name foe the JitsiParticipant identified by - * the given id. - * - * @param id {string} the participant's id(MUC nickname/JVB endpoint id) - * - * @return {string} the participant's display name or the default string if - * absent. - */ - getParticipantDisplayName(id) { - const displayName = getDisplayName(id); - - if (displayName) { - return displayName; - } - if (APP.conference.isLocalId(id)) { - return APP.translation.generateTranslationHTML( - interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME); - } - - return interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME; - }, - getMyUserId() { return room && room.myUserId(); }, @@ -2222,6 +2179,10 @@ export default { (id, displayName) => { const formattedDisplayName = getNormalizedDisplayName(displayName); + const state = APP.store.getState(); + const { + defaultRemoteDisplayName + } = state['features/base/config']; APP.store.dispatch(participantUpdated({ conference: room, @@ -2233,7 +2194,7 @@ export default { formattedDisplayName: appendSuffix( formattedDisplayName - || interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME) + || defaultRemoteDisplayName) }); } ); diff --git a/config.js b/config.js index 12602b125f..f39f135fb3 100644 --- a/config.js +++ b/config.js @@ -466,6 +466,12 @@ var config = { // when the toolbar is shown on mouse movements // disable1On1Mode: null | false | true, + // Default local name to be displayed + // defaultLocalDisplayName: 'me', + + // Default remote name to be displayed + // defaultRemoteDisplayName: 'Fellow Jitster', + // Default language for the user interface. // defaultLanguage: 'en', diff --git a/interface_config.js b/interface_config.js index 15491df9e2..c3a76afb90 100644 --- a/interface_config.js +++ b/interface_config.js @@ -27,9 +27,7 @@ var interfaceConfig = { CLOSE_PAGE_GUEST_HINT: false, // A html text to be shown to guests on the close page, false disables it DEFAULT_BACKGROUND: '#474747', - DEFAULT_LOCAL_DISPLAY_NAME: 'me', DEFAULT_LOGO_URL: 'images/watermark.svg', - DEFAULT_REMOTE_DISPLAY_NAME: 'Fellow Jitster', DEFAULT_WELCOME_PAGE_LOGO_URL: 'images/watermark.svg', DISABLE_DOMINANT_SPEAKER_INDICATOR: false, @@ -241,6 +239,12 @@ var interfaceConfig = { // Please use disableModeratorIndicator from config.js // DISABLE_FOCUS_INDICATOR: false, + // Please use defaultLocalDisplayName from config.js + // DEFAULT_LOCAL_DISPLAY_NAME: 'me', + + // Please use defaultRemoteDisplayName from config.js + // DEFAULT_REMOTE_DISPLAY_NAME: 'Fellow Jitster', + // Moved to config.js as `toolbarConfig.initialTimeout`. // INITIAL_TOOLBAR_TIMEOUT: 20000, diff --git a/modules/UI/videolayout/LargeVideoManager.js b/modules/UI/videolayout/LargeVideoManager.js index f3f176ecff..8d384413e0 100644 --- a/modules/UI/videolayout/LargeVideoManager.js +++ b/modules/UI/videolayout/LargeVideoManager.js @@ -14,7 +14,10 @@ import { JitsiParticipantConnectionStatus } from '../../../react/features/base/lib-jitsi-meet'; import { MEDIA_TYPE, VIDEO_TYPE } from '../../../react/features/base/media'; -import { getParticipantById } from '../../../react/features/base/participants'; +import { + getParticipantById, + getParticipantDisplayName +} from '../../../react/features/base/participants'; import { getTrackByMediaTypeAndParticipant } from '../../../react/features/base/tracks'; import { CHAT_SIZE } from '../../../react/features/chat'; import { @@ -314,10 +317,12 @@ export default class LargeVideoManager { * @private */ updateParticipantConnStatusIndication(id, messageKey) { + const state = APP.store.getState(); + if (messageKey) { // Get user's display name const displayName - = APP.conference.getParticipantDisplayName(id); + = getParticipantDisplayName(state, id); this._setRemoteConnectionMessage( messageKey, diff --git a/react/features/base/config/configWhitelist.js b/react/features/base/config/configWhitelist.js index e76fb4873d..45c671f007 100644 --- a/react/features/base/config/configWhitelist.js +++ b/react/features/base/config/configWhitelist.js @@ -81,6 +81,8 @@ export default [ 'debug', 'debugAudioLevels', 'defaultLanguage', + 'defaultLocalDisplayName', + 'defaultRemoteDisplayName', 'desktopSharingFrameRate', 'desktopSharingSources', 'disable1On1Mode', diff --git a/react/features/base/config/reducer.js b/react/features/base/config/reducer.js index a0a52295ce..ead2adc6c8 100644 --- a/react/features/base/config/reducer.js +++ b/react/features/base/config/reducer.js @@ -320,6 +320,24 @@ function _translateLegacyConfig(oldValue: Object) { newValue.e2ee.e2eeLabels = oldValue.e2eeLabels; } + if (oldValue.defaultLocalDisplayName === undefined + && typeof interfaceConfig === 'object' + && interfaceConfig.hasOwnProperty('DEFAULT_LOCAL_DISPLAY_NAME')) { + newValue.defaultLocalDisplayName = interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME; + } + + newValue.defaultLocalDisplayName + = newValue.defaultLocalDisplayName || 'me'; + + if (oldValue.defaultRemoteDisplayName === undefined + && typeof interfaceConfig === 'object' + && interfaceConfig.hasOwnProperty('DEFAULT_REMOTE_DISPLAY_NAME')) { + newValue.defaultRemoteDisplayName = interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME; + } + + newValue.defaultRemoteDisplayName + = newValue.defaultRemoteDisplayName || 'Fellow Jitster'; + return newValue; } diff --git a/react/features/base/participants/functions.js b/react/features/base/participants/functions.js index b0c8e740fa..bbe271c00f 100644 --- a/react/features/base/participants/functions.js +++ b/react/features/base/participants/functions.js @@ -16,7 +16,6 @@ import { } from './constants'; import { preloadImage } from './preloadImage'; -declare var interfaceConfig: Object; /** * Temp structures for avatar urls to be checked/preloaded. @@ -198,9 +197,6 @@ export function getParticipantCountWithFake(stateful: Object | Function) { /** * Returns participant's display name. * - * FIXME: Remove the hardcoded strings once interfaceConfig is stored in redux - * and merge with a similarly named method in {@code conference.js}. - * * @param {(Function|Object)} stateful - The (whole) redux state, or redux's * {@code getState} function to be used to retrieve the state. * @param {string} id - The ID of the participant's display name to retrieve. @@ -210,6 +206,10 @@ export function getParticipantDisplayName( stateful: Object | Function, id: string) { const participant = getParticipantById(stateful, id); + const { + defaultLocalDisplayName, + defaultRemoteDisplayName + } = toState(stateful)['features/base/config']; if (participant) { if (participant.name) { @@ -217,15 +217,11 @@ export function getParticipantDisplayName( } if (participant.local) { - return typeof interfaceConfig === 'object' - ? interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME - : 'me'; + return defaultLocalDisplayName; } } - return typeof interfaceConfig === 'object' - ? interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME - : 'Fellow Jitster'; + return defaultRemoteDisplayName; } /** diff --git a/react/features/base/participants/reducer.js b/react/features/base/participants/reducer.js index d3c76f4935..8a3c6f3eb2 100644 --- a/react/features/base/participants/reducer.js +++ b/react/features/base/participants/reducer.js @@ -16,8 +16,6 @@ import { import { LOCAL_PARTICIPANT_DEFAULT_ID, PARTICIPANT_ROLE } from './constants'; import { isParticipantModerator } from './functions'; -declare var interfaceConfig: Object; - /** * Participant object. * @@ -109,7 +107,10 @@ ReducerRegistry.register('features/base/participants', (state = DEFAULT_STATE, a if (speaker !== local?.id) { const remoteParticipant = state.remote.get(speaker); - remoteParticipant && sortedSpeakersList.push([ speaker, _getDisplayName(remoteParticipant.name) ]); + remoteParticipant + && sortedSpeakersList.push( + [ speaker, _getDisplayName(state, remoteParticipant.name) ] + ); } } @@ -240,7 +241,7 @@ ReducerRegistry.register('features/base/participants', (state = DEFAULT_STATE, a state.remote.set(id, participant); // Insert the new participant. - const displayName = _getDisplayName(name); + const displayName = _getDisplayName(state, name); const sortedRemoteParticipants = Array.from(state.sortedRemoteParticipants); sortedRemoteParticipants.push([ id, displayName ]); @@ -336,7 +337,8 @@ ReducerRegistry.register('features/base/participants', (state = DEFAULT_STATE, a const remoteParticipant = state.remote.get(participant); if (remoteParticipant) { - const displayName = _getDisplayName(remoteParticipant.name); + const displayName + = _getDisplayName(state, remoteParticipant.name); sortedSharesList.push([ participant, displayName ]); } @@ -356,12 +358,14 @@ ReducerRegistry.register('features/base/participants', (state = DEFAULT_STATE, a /** * Returns the participant's display name, default string if display name is not set on the participant. * + * @param {Object} state - The local participant redux state. * @param {string} name - The display name of the participant. * @returns {string} */ -function _getDisplayName(name) { - return name - ?? (typeof interfaceConfig === 'object' ? interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME : 'Fellow Jitser'); +function _getDisplayName(state: Object, name: string): string { + const config = state['features/base/config']; + + return name ?? (config?.defaultRemoteDisplayName || 'Fellow Jitster'); } /** diff --git a/react/features/external-api/middleware.js b/react/features/external-api/middleware.js index 8560b35df6..aeb78d6288 100644 --- a/react/features/external-api/middleware.js +++ b/react/features/external-api/middleware.js @@ -27,7 +27,6 @@ import { SET_FILMSTRIP_VISIBLE } from '../filmstrip'; import './subscriber'; declare var APP: Object; -declare var interfaceConfig: Object; /** * The middleware of the feature {@code external-api}. @@ -86,6 +85,7 @@ MiddlewareRegistry.register(store => next => action => { case CONFERENCE_JOINED: { const state = store.getState(); + const { defaultLocalDisplayName } = state['features/base/config']; const { room } = state['features/base/conference']; const { loadableAvatarUrl, name, id } = getLocalParticipant(state); @@ -96,7 +96,7 @@ MiddlewareRegistry.register(store => next => action => { displayName: name, formattedDisplayName: appendSuffix( name, - interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME + defaultLocalDisplayName ), avatarURL: loadableAvatarUrl } @@ -149,6 +149,8 @@ MiddlewareRegistry.register(store => next => action => { break; case PARTICIPANT_JOINED: { + const state = store.getState(); + const { defaultRemoteDisplayName } = state['features/base/config']; const { participant } = action; const { id, local, name } = participant; @@ -158,7 +160,7 @@ MiddlewareRegistry.register(store => next => action => { APP.API.notifyUserJoined(id, { displayName: name, formattedDisplayName: appendSuffix( - name || interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME) + name || defaultRemoteDisplayName) }); } diff --git a/react/features/external-api/subscriber.js b/react/features/external-api/subscriber.js index 65dce2a227..14b8c8d8d2 100644 --- a/react/features/external-api/subscriber.js +++ b/react/features/external-api/subscriber.js @@ -6,7 +6,6 @@ import { appendSuffix } from '../display-name'; import { shouldDisplayTileView } from '../video-layout'; declare var APP: Object; -declare var interfaceConfig: Object; /** * StateListenerRegistry provides a reliable way of detecting changes to @@ -22,6 +21,7 @@ StateListenerRegistry.register( /* selector */ state => state['features/base/settings'].displayName, /* listener */ (displayName, store) => { const localParticipant = getLocalParticipant(store.getState()); + const { defaultLocalDisplayName } = store.getState()['features/base/config']; // Initial setting of the display name occurs happens on app // initialization, before the local participant is ready. The initial @@ -33,7 +33,8 @@ StateListenerRegistry.register( displayName, formattedDisplayName: appendSuffix( displayName, - interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME) + defaultLocalDisplayName + ) }); } }); diff --git a/react/features/filmstrip/components/web/Thumbnail.js b/react/features/filmstrip/components/web/Thumbnail.js index b42517411a..6104f071cf 100644 --- a/react/features/filmstrip/components/web/Thumbnail.js +++ b/react/features/filmstrip/components/web/Thumbnail.js @@ -1122,6 +1122,7 @@ function _mapStateToProps(state, ownProps): Object { let _isMobilePortrait = false; const { startSilent, + defaultLocalDisplayName, disableLocalVideoFlip, iAmRecorder, iAmSipGateway @@ -1178,7 +1179,7 @@ function _mapStateToProps(state, ownProps): Object { _connectionIndicatorDisabled: _isMobile || Boolean(state['features/base/config'].connectionIndicators?.disabled), _currentLayout, - _defaultLocalDisplayName: interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME, + _defaultLocalDisplayName: defaultLocalDisplayName, _disableLocalVideoFlip: Boolean(disableLocalVideoFlip), _isHidden: isLocal && iAmRecorder && !iAmSipGateway, _isAudioOnly: Boolean(state['features/base/audio-only'].enabled), diff --git a/react/features/toolbox/components/web/ProfileButton.js b/react/features/toolbox/components/web/ProfileButton.js index ae256c802f..e24006c02c 100644 --- a/react/features/toolbox/components/web/ProfileButton.js +++ b/react/features/toolbox/components/web/ProfileButton.js @@ -14,6 +14,11 @@ import ProfileButtonAvatar from './ProfileButtonAvatar'; */ type Props = AbstractButtonProps & { + /** + * Default displayed name for local participant. + */ + _defaultLocalDisplayName: string, + /** * The redux representation of the local participant. */ @@ -43,13 +48,16 @@ class ProfileButton extends AbstractButton { * Retrieves the label. */ get label() { - const { _localParticipant } = this.props; + const { + _defaultLocalDisplayName, + _localParticipant + } = this.props; let displayName; - if (_localParticipant && _localParticipant.name) { + if (_localParticipant?.name) { displayName = _localParticipant.name; } else { - displayName = interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME; + displayName = _defaultLocalDisplayName; } return displayName; @@ -119,7 +127,10 @@ class ProfileButton extends AbstractButton { * @returns {Object} */ const mapStateToProps = state => { + const { defaultLocalDisplayName } = state['features/base/config']; + return { + _defaultLocalDisplayName: defaultLocalDisplayName, _localParticipant: getLocalParticipant(state), _unclickable: !interfaceConfig.SETTINGS_SECTIONS.includes('profile'), customClass: 'profile-button-avatar'