Move display name handling into redux

This commit is contained in:
Bettenbuk Zoltan 2019-01-13 20:33:28 +01:00 committed by Saúl Ibarra Corretgé
parent 8c9ba325ca
commit 82f714b608
9 changed files with 167 additions and 133 deletions

View File

@ -2660,7 +2660,6 @@ export default {
});
if (room) {
room.setDisplayName(formattedNickname);
APP.UI.changeDisplayName(id, formattedNickname);
}
},

View File

@ -15,6 +15,7 @@ import {
getLocalParticipant,
getParticipantById,
getPinnedParticipant,
PARTICIPANT_UPDATED,
PIN_PARTICIPANT
} from '../participants';
import { MiddlewareRegistry, StateListenerRegistry } from '../redux';
@ -80,6 +81,9 @@ MiddlewareRegistry.register(store => next => action => {
case DATA_CHANNEL_OPENED:
return _syncReceiveVideoQuality(store, next, action);
case PARTICIPANT_UPDATED:
return _updateLocalParticipantInConference(store, next, action);
case PIN_PARTICIPANT:
return _pinParticipant(store, next, action);
@ -651,3 +655,27 @@ function _trackAddedOrRemoved(store, 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;
}

View File

@ -11,7 +11,6 @@ import {
HIDDEN_PARTICIPANT_LEFT,
KICK_PARTICIPANT,
MUTE_REMOTE_PARTICIPANT,
PARTICIPANT_DISPLAY_NAME_CHANGED,
PARTICIPANT_ID_CHANGED,
PARTICIPANT_JOINED,
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.
*
@ -393,6 +369,10 @@ export function participantRoleChanged(id, role) {
* }}
*/
export function participantUpdated(participant = {}) {
if (participant.name) {
participant.name = participant.name.substr(0, MAX_DISPLAY_NAME_LENGTH);
}
return {
type: PARTICIPANT_UPDATED,
participant

View File

@ -5,21 +5,13 @@ import React, { Component } from 'react';
import { connect } from 'react-redux';
import { translate } from '../../base/i18n';
import {
getLocalParticipant,
participantDisplayNameChanged
} from '../../base/participants';
import { updateSettings } from '../../base/settings';
/**
* The type of the React {@code Component} props of {@DisplayNameForm}.
*/
type Props = {
/**
* The ID of the local participant.
*/
_localParticipantId: string,
/**
* Invoked to set the local participant display name.
*/
@ -117,26 +109,11 @@ class DisplayNameForm extends Component<Props, State> {
_onSubmit(event: Object) {
event.preventDefault();
this.props.dispatch(participantDisplayNameChanged(
this.props._localParticipantId,
this.state.displayName));
// Store display name in settings
this.props.dispatch(updateSettings({
displayName: this.state.displayName
}));
}
}
/**
* 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));
export default translate(connect()(DisplayNameForm));

View File

@ -1,3 +1,5 @@
// @flow
import { openDialog } from '../../features/base/dialog';
import { DisplayNamePrompt } from './components';
@ -5,8 +7,12 @@ import { DisplayNamePrompt } from './components';
/**
* 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}
*/
export function openDisplayNamePrompt() {
return openDialog(DisplayNamePrompt);
export function openDisplayNamePrompt(onPostSubmit: ?Function = undefined) {
return openDialog(DisplayNamePrompt, {
onPostSubmit
});
}

View File

@ -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;
}
}

View File

@ -6,13 +6,21 @@ import { connect } from 'react-redux';
import { appendSuffix } from '../functions';
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}.
*/
type Props = {
/**
* The participant's current display name.
*/
_displayName: string,
/**
* Whether or not the display name should be editable on click.
*/
@ -23,11 +31,6 @@ type Props = {
*/
dispatch: Dispatch<*>,
/**
* The participant's current display name.
*/
displayName: string,
/**
* A string to append to the displayName, if provided.
*/
@ -130,8 +133,8 @@ class DisplayName extends Component<Props, State> {
*/
render() {
const {
_displayName,
allowEditing,
displayName,
displayNameSuffix,
elementID,
t
@ -159,7 +162,7 @@ class DisplayName extends Component<Props, State> {
className = 'displayname'
id = { elementID }
onClick = { this._onStartEditing }>
{ appendSuffix(displayName, displayNameSuffix) }
{ appendSuffix(_displayName, displayNameSuffix) }
</span>
);
}
@ -208,7 +211,7 @@ class DisplayName extends Component<Props, State> {
if (this.props.allowEditing) {
this.setState({
isEditing: true,
editDisplayNameValue: this.props.displayName || ''
editDisplayNameValue: this.props._displayName || ''
});
}
}
@ -226,10 +229,12 @@ class DisplayName extends Component<Props, State> {
*/
_onSubmit() {
const { editDisplayNameValue } = this.state;
const { dispatch, participantID } = this.props;
const { dispatch } = this.props;
dispatch(participantDisplayNameChanged(
participantID, editDisplayNameValue));
// Store display name in settings
dispatch(updateSettings({
displayName: editDisplayNameValue
}));
this.setState({
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));

View File

@ -1,37 +1,15 @@
/* @flow */
import React, { Component } from 'react';
import React from 'react';
import { connect } from 'react-redux';
import { FieldTextStateless as TextField } from '@atlaskit/field-text';
import { Dialog } from '../../base/dialog';
import { translate } from '../../base/i18n';
import {
getLocalParticipant,
participantDisplayNameChanged
} from '../../base/participants';
/**
* The type of the React {@code Component} props of {@link DisplayNamePrompt}.
*/
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
};
import AbstractDisplayNamePrompt, {
type Props
} from './AbstractDisplayNamePrompt';
/**
* The type of the React {@code Component} props of {@link DisplayNamePrompt}.
@ -50,7 +28,7 @@ type State = {
*
* @extends Component
*/
class DisplayNamePrompt extends Component<Props, State> {
class DisplayNamePrompt extends AbstractDisplayNamePrompt<State> {
/**
* Initializes a new {@code DisplayNamePrompt} instance.
*
@ -110,6 +88,8 @@ class DisplayNamePrompt extends Component<Props, State> {
});
}
_onSetDisplayName: string => boolean;
_onSubmit: () => boolean;
/**
@ -120,42 +100,8 @@ class DisplayNamePrompt extends Component<Props, State> {
* @returns {boolean}
*/
_onSubmit() {
const { displayName } = this.state;
if (!displayName.trim()) {
return false;
}
const { dispatch, _localParticipantID } = this.props;
dispatch(
participantDisplayNameChanged(_localParticipantID, displayName));
return true;
return this._onSetDisplayName(this.state.displayName);
}
}
/**
* 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));
export default translate(connect()(DisplayNamePrompt));

View File

@ -7,5 +7,5 @@
*/
export function appendSuffix(displayName, suffix) {
return `${displayName || suffix || ''}${
displayName && suffix ? ` (${suffix})` : ''}`;
displayName && suffix && displayName !== suffix ? ` (${suffix})` : ''}`;
}