mirror of https://github.com/jitsi/jitsi-meet
feat(display-name): convert to React (#1672)
* feat(display-name): convert to React - Create a new React Component for displaying and updating display names on small videos - The updating of the Component is defined in the parent class SmallVideo, which children will get access to through prototype copying - Create a new actionType and middleware so name changes that occur in DisplayName can be propogated to outside redux - Update the local video's DisplayName when a conference is joined or else the component may keep an undefined user id * squash: query for the container, not the el owned by reactpull/1713/head jitsi-meet_2197
parent
e7a4318e8c
commit
928181cd7a
@ -0,0 +1,239 @@ |
||||
import React, { Component } from 'react'; |
||||
import { connect } from 'react-redux'; |
||||
|
||||
import { translate } from '../../base/i18n'; |
||||
import { participantDisplayNameChanged } from '../../base/participants'; |
||||
|
||||
/** |
||||
* React {@code Component} for displaying and editing a participant's name. |
||||
* |
||||
* @extends Component |
||||
*/ |
||||
class DisplayName extends Component { |
||||
/** |
||||
* {@code DisplayName}'s property types. |
||||
* |
||||
* @static |
||||
*/ |
||||
static propTypes = { |
||||
/** |
||||
* Whether or not the display name should be editable on click. |
||||
*/ |
||||
allowEditing: React.PropTypes.bool, |
||||
|
||||
/** |
||||
* Invoked to update the participant's display name. |
||||
*/ |
||||
dispatch: React.PropTypes.func, |
||||
|
||||
/** |
||||
* The participant's current display name. |
||||
*/ |
||||
displayName: React.PropTypes.string, |
||||
|
||||
/** |
||||
* A string to append to the displayName, if provided. |
||||
*/ |
||||
displayNameSuffix: React.PropTypes.string, |
||||
|
||||
/** |
||||
* The ID attribute to add to the component. Useful for global querying |
||||
* for the component by legacy components and torture tests. |
||||
*/ |
||||
elementID: React.PropTypes.string, |
||||
|
||||
/** |
||||
* The ID of the participant whose name is being displayed. |
||||
*/ |
||||
participantID: React.PropTypes.string, |
||||
|
||||
/** |
||||
* Invoked to obtain translated strings. |
||||
*/ |
||||
t: React.PropTypes.func |
||||
}; |
||||
|
||||
/** |
||||
* Initializes a new {@code DisplayName} instance. |
||||
* |
||||
* @param {Object} props - The read-only properties with which the new |
||||
* instance is to be initialized. |
||||
*/ |
||||
constructor(props) { |
||||
super(props); |
||||
|
||||
this.state = { |
||||
/** |
||||
* The current value of the display name in the edit field. |
||||
* |
||||
* @type {string} |
||||
*/ |
||||
editDisplayNameValue: '', |
||||
|
||||
/** |
||||
* Whether or not the component should be displaying an editable |
||||
* input. |
||||
* |
||||
* @type {boolean} |
||||
*/ |
||||
isEditing: false |
||||
}; |
||||
|
||||
/** |
||||
* The internal reference to the HTML element backing the React |
||||
* {@code Component} input with id {@code editDisplayName}. It is |
||||
* necessary for automatically selecting the display name input field |
||||
* when starting to edit the display name. |
||||
* |
||||
* @private |
||||
* @type {HTMLInputElement} |
||||
*/ |
||||
this._nameInput = null; |
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
this._onChange = this._onChange.bind(this); |
||||
this._onKeyDown = this._onKeyDown.bind(this); |
||||
this._onStartEditing = this._onStartEditing.bind(this); |
||||
this._onSubmit = this._onSubmit.bind(this); |
||||
this._setNameInputRef = this._setNameInputRef.bind(this); |
||||
} |
||||
|
||||
/** |
||||
* Automatically selects the input field's value after starting to edit the |
||||
* display name. |
||||
* |
||||
* @inheritdoc |
||||
* @returns {void} |
||||
*/ |
||||
componentDidUpdate(previousProps, previousState) { |
||||
if (!previousState.isEditing && this.state.isEditing) { |
||||
this._nameInput.select(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Implements React's {@link Component#render()}. |
||||
* |
||||
* @inheritdoc |
||||
* @returns {ReactElement} |
||||
*/ |
||||
render() { |
||||
const { |
||||
allowEditing, |
||||
displayName, |
||||
displayNameSuffix, |
||||
elementID, |
||||
t |
||||
} = this.props; |
||||
|
||||
if (allowEditing && this.state.isEditing) { |
||||
return ( |
||||
<input |
||||
autoFocus = { true } |
||||
className = 'editdisplayname' |
||||
id = 'editDisplayName' |
||||
onBlur = { this._onSubmit } |
||||
onChange = { this._onChange } |
||||
onKeyDown = { this._onKeyDown } |
||||
placeholder = { t('defaultNickname') } |
||||
ref = { this._setNameInputRef } |
||||
type = 'text' |
||||
value = { this.state.editDisplayNameValue } /> |
||||
); |
||||
} |
||||
|
||||
const suffix |
||||
= displayName && displayNameSuffix ? ` (${displayNameSuffix})` : ''; |
||||
|
||||
return ( |
||||
<span |
||||
className = 'displayname' |
||||
id = { elementID } |
||||
onClick = { this._onStartEditing }> |
||||
{ `${displayName || displayNameSuffix || ''}${suffix}` } |
||||
</span> |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Updates the internal state of the display name entered into the edit |
||||
* field. |
||||
* |
||||
* @param {Object} event - DOM Event for value change. |
||||
* @private |
||||
* @returns {void} |
||||
*/ |
||||
_onChange(event) { |
||||
this.setState({ |
||||
editDisplayNameValue: event.target.value |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Submits the editted display name update if the enter key is pressed. |
||||
* |
||||
* @param {Event} event - Key down event object. |
||||
* @private |
||||
* @returns {void} |
||||
*/ |
||||
_onKeyDown(event) { |
||||
if (event.key === 'Enter') { |
||||
this._onSubmit(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Updates the component to display an editable input field and sets the |
||||
* initial value to the current display name. |
||||
* |
||||
* @private |
||||
* @returns {void} |
||||
*/ |
||||
_onStartEditing() { |
||||
if (this.props.allowEditing) { |
||||
this.setState({ |
||||
isEditing: true, |
||||
editDisplayNameValue: this.props.displayName || '' |
||||
}); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Dispatches an action to update the display name if any change has |
||||
* occurred after editing. Clears any temporary state used to keep track |
||||
* of pending display name changes and exits editing mode. |
||||
* |
||||
* @param {Event} event - Key down event object. |
||||
* @private |
||||
* @returns {void} |
||||
*/ |
||||
_onSubmit() { |
||||
const { editDisplayNameValue } = this.state; |
||||
const { dispatch, participantID } = this.props; |
||||
|
||||
dispatch(participantDisplayNameChanged( |
||||
participantID, editDisplayNameValue)); |
||||
|
||||
this.setState({ |
||||
isEditing: false, |
||||
editDisplayNameValue: '' |
||||
}); |
||||
|
||||
this._nameInput = null; |
||||
} |
||||
|
||||
/** |
||||
* Sets the internal reference to the HTML element backing the React |
||||
* {@code Component} input with id {@code editDisplayName}. |
||||
* |
||||
* @param {HTMLInputElement} element - The DOM/HTML element for this |
||||
* {@code Component}'s input. |
||||
* @private |
||||
* @returns {void} |
||||
*/ |
||||
_setNameInputRef(element) { |
||||
this._nameInput = element; |
||||
} |
||||
} |
||||
|
||||
export default translate(connect()(DisplayName)); |
@ -0,0 +1 @@ |
||||
export { default as DisplayName } from './DisplayName'; |
@ -0,0 +1 @@ |
||||
export * from './components'; |
Loading…
Reference in new issue