Move display name handling into redux
This commit is contained in:
parent
8c9ba325ca
commit
82f714b608
|
@ -2660,7 +2660,6 @@ export default {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (room) {
|
if (room) {
|
||||||
room.setDisplayName(formattedNickname);
|
|
||||||
APP.UI.changeDisplayName(id, formattedNickname);
|
APP.UI.changeDisplayName(id, formattedNickname);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
getLocalParticipant,
|
getLocalParticipant,
|
||||||
getParticipantById,
|
getParticipantById,
|
||||||
getPinnedParticipant,
|
getPinnedParticipant,
|
||||||
|
PARTICIPANT_UPDATED,
|
||||||
PIN_PARTICIPANT
|
PIN_PARTICIPANT
|
||||||
} from '../participants';
|
} from '../participants';
|
||||||
import { MiddlewareRegistry, StateListenerRegistry } from '../redux';
|
import { MiddlewareRegistry, StateListenerRegistry } from '../redux';
|
||||||
|
@ -80,6 +81,9 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
case DATA_CHANNEL_OPENED:
|
case DATA_CHANNEL_OPENED:
|
||||||
return _syncReceiveVideoQuality(store, next, action);
|
return _syncReceiveVideoQuality(store, next, action);
|
||||||
|
|
||||||
|
case PARTICIPANT_UPDATED:
|
||||||
|
return _updateLocalParticipantInConference(store, next, action);
|
||||||
|
|
||||||
case PIN_PARTICIPANT:
|
case PIN_PARTICIPANT:
|
||||||
return _pinParticipant(store, next, action);
|
return _pinParticipant(store, next, action);
|
||||||
|
|
||||||
|
@ -651,3 +655,27 @@ function _trackAddedOrRemoved(store, next, action) {
|
||||||
|
|
||||||
return next(action);
|
return next(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the conference object when the local participant is updated.
|
||||||
|
*
|
||||||
|
* @param {Store} store - The redux store in which the specified {@code action}
|
||||||
|
* is being dispatched.
|
||||||
|
* @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
|
||||||
|
* specified {@code action} to the specified {@code store}.
|
||||||
|
* @param {Action} action - The redux action which is being dispatched in the
|
||||||
|
* specified {@code store}.
|
||||||
|
* @private
|
||||||
|
* @returns {Object} The value returned by {@code next(action)}.
|
||||||
|
*/
|
||||||
|
function _updateLocalParticipantInConference({ getState }, next, action) {
|
||||||
|
const { conference } = getState()['features/base/conference'];
|
||||||
|
const { participant } = action;
|
||||||
|
const result = next(action);
|
||||||
|
|
||||||
|
if (conference && participant.local) {
|
||||||
|
conference.setDisplayName(participant.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import {
|
||||||
HIDDEN_PARTICIPANT_LEFT,
|
HIDDEN_PARTICIPANT_LEFT,
|
||||||
KICK_PARTICIPANT,
|
KICK_PARTICIPANT,
|
||||||
MUTE_REMOTE_PARTICIPANT,
|
MUTE_REMOTE_PARTICIPANT,
|
||||||
PARTICIPANT_DISPLAY_NAME_CHANGED,
|
|
||||||
PARTICIPANT_ID_CHANGED,
|
PARTICIPANT_ID_CHANGED,
|
||||||
PARTICIPANT_JOINED,
|
PARTICIPANT_JOINED,
|
||||||
PARTICIPANT_LEFT,
|
PARTICIPANT_LEFT,
|
||||||
|
@ -208,29 +207,6 @@ export function participantConnectionStatusChanged(id, connectionStatus) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Action to signal that a participant's display name has changed.
|
|
||||||
*
|
|
||||||
* @param {string} id - The id of the participant being changed.
|
|
||||||
* @param {string} displayName - The new display name.
|
|
||||||
* @returns {{
|
|
||||||
* type: PARTICIPANT_DISPLAY_NAME_CHANGED,
|
|
||||||
* id: string,
|
|
||||||
* name: string
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
export function participantDisplayNameChanged(id, displayName = '') {
|
|
||||||
// FIXME Do not use this action over participantUpdated. This action exists
|
|
||||||
// as a a bridge for local name updates. Once other components responsible
|
|
||||||
// for updating the local user's display name are in react/redux, this
|
|
||||||
// action should be replaceable with the participantUpdated action.
|
|
||||||
return {
|
|
||||||
type: PARTICIPANT_DISPLAY_NAME_CHANGED,
|
|
||||||
id,
|
|
||||||
name: displayName.substr(0, MAX_DISPLAY_NAME_LENGTH)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action to signal that a participant has joined.
|
* Action to signal that a participant has joined.
|
||||||
*
|
*
|
||||||
|
@ -393,6 +369,10 @@ export function participantRoleChanged(id, role) {
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
export function participantUpdated(participant = {}) {
|
export function participantUpdated(participant = {}) {
|
||||||
|
if (participant.name) {
|
||||||
|
participant.name = participant.name.substr(0, MAX_DISPLAY_NAME_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: PARTICIPANT_UPDATED,
|
type: PARTICIPANT_UPDATED,
|
||||||
participant
|
participant
|
||||||
|
|
|
@ -5,21 +5,13 @@ import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { translate } from '../../base/i18n';
|
import { translate } from '../../base/i18n';
|
||||||
import {
|
import { updateSettings } from '../../base/settings';
|
||||||
getLocalParticipant,
|
|
||||||
participantDisplayNameChanged
|
|
||||||
} from '../../base/participants';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} props of {@DisplayNameForm}.
|
* The type of the React {@code Component} props of {@DisplayNameForm}.
|
||||||
*/
|
*/
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
||||||
/**
|
|
||||||
* The ID of the local participant.
|
|
||||||
*/
|
|
||||||
_localParticipantId: string,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked to set the local participant display name.
|
* Invoked to set the local participant display name.
|
||||||
*/
|
*/
|
||||||
|
@ -117,26 +109,11 @@ class DisplayNameForm extends Component<Props, State> {
|
||||||
_onSubmit(event: Object) {
|
_onSubmit(event: Object) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
this.props.dispatch(participantDisplayNameChanged(
|
// Store display name in settings
|
||||||
this.props._localParticipantId,
|
this.props.dispatch(updateSettings({
|
||||||
this.state.displayName));
|
displayName: this.state.displayName
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export default translate(connect()(DisplayNameForm));
|
||||||
* Maps (parts of) the Redux state to the associated props for the
|
|
||||||
* {@code DisplayNameForm} component.
|
|
||||||
*
|
|
||||||
* @param {Object} state - The Redux state.
|
|
||||||
* @private
|
|
||||||
* @returns {{
|
|
||||||
* _localParticipantId: string
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
function _mapStateToProps(state) {
|
|
||||||
return {
|
|
||||||
_localParticipantId: getLocalParticipant(state).id
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default translate(connect(_mapStateToProps)(DisplayNameForm));
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import { openDialog } from '../../features/base/dialog';
|
import { openDialog } from '../../features/base/dialog';
|
||||||
|
|
||||||
import { DisplayNamePrompt } from './components';
|
import { DisplayNamePrompt } from './components';
|
||||||
|
@ -5,8 +7,12 @@ import { DisplayNamePrompt } from './components';
|
||||||
/**
|
/**
|
||||||
* Signals to open a dialog with the {@code DisplayNamePrompt} component.
|
* Signals to open a dialog with the {@code DisplayNamePrompt} component.
|
||||||
*
|
*
|
||||||
|
* @param {?Function} onPostSubmit - The function to invoke after a successful
|
||||||
|
* submit of the dialog.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
export function openDisplayNamePrompt() {
|
export function openDisplayNamePrompt(onPostSubmit: ?Function = undefined) {
|
||||||
return openDialog(DisplayNamePrompt);
|
return openDialog(DisplayNamePrompt, {
|
||||||
|
onPostSubmit
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { Component } from 'react';
|
||||||
|
|
||||||
|
import { updateSettings } from '../../base/settings';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the React {@code Component} props of
|
||||||
|
* {@link AbstractDisplayNamePrompt}.
|
||||||
|
*/
|
||||||
|
export type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked to update the local participant's display name.
|
||||||
|
*/
|
||||||
|
dispatch: Dispatch<*>,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to be invoked after a successful display name change.
|
||||||
|
*/
|
||||||
|
onPostSubmit: ?Function,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked to obtain translated strings.
|
||||||
|
*/
|
||||||
|
t: Function
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements an abstract class for {@code DisplayNamePrompt}.
|
||||||
|
*/
|
||||||
|
export default class AbstractDisplayNamePrompt<S: *>
|
||||||
|
extends Component<Props, S> {
|
||||||
|
/**
|
||||||
|
* Instantiates a new component.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this._onSetDisplayName = this._onSetDisplayName.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onSetDisplayName: string => boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches an action to update the local participant's display name. A
|
||||||
|
* name must be entered for the action to dispatch.
|
||||||
|
*
|
||||||
|
* It returns a boolean to comply the Dialog behaviour:
|
||||||
|
* {@code true} - the dialog should be closed.
|
||||||
|
* {@code false} - the dialog should be left open.
|
||||||
|
*
|
||||||
|
* @param {string} displayName - The display name to save.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
_onSetDisplayName(displayName) {
|
||||||
|
if (!displayName || !displayName.trim()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { dispatch, onPostSubmit } = this.props;
|
||||||
|
|
||||||
|
// Store display name in settings
|
||||||
|
dispatch(updateSettings({
|
||||||
|
displayName
|
||||||
|
}));
|
||||||
|
|
||||||
|
onPostSubmit && onPostSubmit();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,13 +6,21 @@ import { connect } from 'react-redux';
|
||||||
import { appendSuffix } from '../functions';
|
import { appendSuffix } from '../functions';
|
||||||
|
|
||||||
import { translate } from '../../base/i18n';
|
import { translate } from '../../base/i18n';
|
||||||
import { participantDisplayNameChanged } from '../../base/participants';
|
import {
|
||||||
|
getParticipantDisplayName
|
||||||
|
} from '../../base/participants';
|
||||||
|
import { updateSettings } from '../../base/settings';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} props of {@link DisplayName}.
|
* The type of the React {@code Component} props of {@link DisplayName}.
|
||||||
*/
|
*/
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The participant's current display name.
|
||||||
|
*/
|
||||||
|
_displayName: string,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the display name should be editable on click.
|
* Whether or not the display name should be editable on click.
|
||||||
*/
|
*/
|
||||||
|
@ -23,11 +31,6 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
dispatch: Dispatch<*>,
|
dispatch: Dispatch<*>,
|
||||||
|
|
||||||
/**
|
|
||||||
* The participant's current display name.
|
|
||||||
*/
|
|
||||||
displayName: string,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A string to append to the displayName, if provided.
|
* A string to append to the displayName, if provided.
|
||||||
*/
|
*/
|
||||||
|
@ -130,8 +133,8 @@ class DisplayName extends Component<Props, State> {
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
_displayName,
|
||||||
allowEditing,
|
allowEditing,
|
||||||
displayName,
|
|
||||||
displayNameSuffix,
|
displayNameSuffix,
|
||||||
elementID,
|
elementID,
|
||||||
t
|
t
|
||||||
|
@ -159,7 +162,7 @@ class DisplayName extends Component<Props, State> {
|
||||||
className = 'displayname'
|
className = 'displayname'
|
||||||
id = { elementID }
|
id = { elementID }
|
||||||
onClick = { this._onStartEditing }>
|
onClick = { this._onStartEditing }>
|
||||||
{ appendSuffix(displayName, displayNameSuffix) }
|
{ appendSuffix(_displayName, displayNameSuffix) }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -208,7 +211,7 @@ class DisplayName extends Component<Props, State> {
|
||||||
if (this.props.allowEditing) {
|
if (this.props.allowEditing) {
|
||||||
this.setState({
|
this.setState({
|
||||||
isEditing: true,
|
isEditing: true,
|
||||||
editDisplayNameValue: this.props.displayName || ''
|
editDisplayNameValue: this.props._displayName || ''
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,10 +229,12 @@ class DisplayName extends Component<Props, State> {
|
||||||
*/
|
*/
|
||||||
_onSubmit() {
|
_onSubmit() {
|
||||||
const { editDisplayNameValue } = this.state;
|
const { editDisplayNameValue } = this.state;
|
||||||
const { dispatch, participantID } = this.props;
|
const { dispatch } = this.props;
|
||||||
|
|
||||||
dispatch(participantDisplayNameChanged(
|
// Store display name in settings
|
||||||
participantID, editDisplayNameValue));
|
dispatch(updateSettings({
|
||||||
|
displayName: editDisplayNameValue
|
||||||
|
}));
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
isEditing: false,
|
isEditing: false,
|
||||||
|
@ -255,4 +260,23 @@ class DisplayName extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default translate(connect()(DisplayName));
|
/**
|
||||||
|
* Maps (parts of) the redux state to the props of this component.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The redux store/state.
|
||||||
|
* @param {Props} ownProps - The own props of the component.
|
||||||
|
* @private
|
||||||
|
* @returns {{
|
||||||
|
* _displayName: string
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
function _mapStateToProps(state, ownProps) {
|
||||||
|
const { participantID } = ownProps;
|
||||||
|
|
||||||
|
return {
|
||||||
|
_displayName: getParticipantDisplayName(
|
||||||
|
state, participantID)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translate(connect(_mapStateToProps)(DisplayName));
|
||||||
|
|
|
@ -1,37 +1,15 @@
|
||||||
/* @flow */
|
/* @flow */
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { FieldTextStateless as TextField } from '@atlaskit/field-text';
|
import { FieldTextStateless as TextField } from '@atlaskit/field-text';
|
||||||
|
|
||||||
import { Dialog } from '../../base/dialog';
|
import { Dialog } from '../../base/dialog';
|
||||||
import { translate } from '../../base/i18n';
|
import { translate } from '../../base/i18n';
|
||||||
import {
|
|
||||||
getLocalParticipant,
|
|
||||||
participantDisplayNameChanged
|
|
||||||
} from '../../base/participants';
|
|
||||||
|
|
||||||
/**
|
import AbstractDisplayNamePrompt, {
|
||||||
* The type of the React {@code Component} props of {@link DisplayNamePrompt}.
|
type Props
|
||||||
*/
|
} from './AbstractDisplayNamePrompt';
|
||||||
type Props = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current ID for the local participant. Used for setting the display
|
|
||||||
* name on the associated participant.
|
|
||||||
*/
|
|
||||||
_localParticipantID: string,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked to update the local participant's display name.
|
|
||||||
*/
|
|
||||||
dispatch: Dispatch<*>,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked to obtain translated strings.
|
|
||||||
*/
|
|
||||||
t: Function
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} props of {@link DisplayNamePrompt}.
|
* The type of the React {@code Component} props of {@link DisplayNamePrompt}.
|
||||||
|
@ -50,7 +28,7 @@ type State = {
|
||||||
*
|
*
|
||||||
* @extends Component
|
* @extends Component
|
||||||
*/
|
*/
|
||||||
class DisplayNamePrompt extends Component<Props, State> {
|
class DisplayNamePrompt extends AbstractDisplayNamePrompt<State> {
|
||||||
/**
|
/**
|
||||||
* Initializes a new {@code DisplayNamePrompt} instance.
|
* Initializes a new {@code DisplayNamePrompt} instance.
|
||||||
*
|
*
|
||||||
|
@ -110,6 +88,8 @@ class DisplayNamePrompt extends Component<Props, State> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onSetDisplayName: string => boolean;
|
||||||
|
|
||||||
_onSubmit: () => boolean;
|
_onSubmit: () => boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -120,42 +100,8 @@ class DisplayNamePrompt extends Component<Props, State> {
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
_onSubmit() {
|
_onSubmit() {
|
||||||
const { displayName } = this.state;
|
return this._onSetDisplayName(this.state.displayName);
|
||||||
|
|
||||||
if (!displayName.trim()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { dispatch, _localParticipantID } = this.props;
|
|
||||||
|
|
||||||
dispatch(
|
|
||||||
participantDisplayNameChanged(_localParticipantID, displayName));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export default translate(connect()(DisplayNamePrompt));
|
||||||
* Maps (parts of) the Redux state to the associated {@code DisplayNamePrompt}'s
|
|
||||||
* props.
|
|
||||||
*
|
|
||||||
* @param {Object} state - The Redux state.
|
|
||||||
* @private
|
|
||||||
* @returns {{
|
|
||||||
* _localParticipantID: string
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
function _mapStateToProps(state) {
|
|
||||||
const { id } = getLocalParticipant(state);
|
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* The current ID for the local participant.
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
_localParticipantID: id
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default translate(connect(_mapStateToProps)(DisplayNamePrompt));
|
|
||||||
|
|
|
@ -7,5 +7,5 @@
|
||||||
*/
|
*/
|
||||||
export function appendSuffix(displayName, suffix) {
|
export function appendSuffix(displayName, suffix) {
|
||||||
return `${displayName || suffix || ''}${
|
return `${displayName || suffix || ''}${
|
||||||
displayName && suffix ? ` (${suffix})` : ''}`;
|
displayName && suffix && displayName !== suffix ? ` (${suffix})` : ''}`;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue