123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- /* @flow */
-
- import React, { Component } from 'react';
- import { connect } from '../../base/redux';
- import type { Dispatch } from 'redux';
-
- import { appendSuffix } from '../functions';
-
- import { translate } from '../../base/i18n';
- 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.
- */
- allowEditing: boolean,
-
- /**
- * Invoked to update the participant's display name.
- */
- dispatch: Dispatch<any>,
-
- /**
- * A string to append to the displayName, if provided.
- */
- displayNameSuffix: string,
-
- /**
- * The ID attribute to add to the component. Useful for global querying for
- * the component by legacy components and torture tests.
- */
- elementID: string,
-
- /**
- * The ID of the participant whose name is being displayed.
- */
- participantID: string,
-
- /**
- * Invoked to obtain translated strings.
- */
- t: Function
- };
-
- /**
- * The type of the React {@code Component} state of {@link DisplayName}.
- */
- type State = {
-
- /**
- * The current value of the display name in the edit field.
- */
- editDisplayNameValue: string,
-
- /**
- * Whether or not the component should be displaying an editable input.
- */
- isEditing: boolean
- };
-
- /**
- * React {@code Component} for displaying and editing a participant's name.
- *
- * @extends Component
- */
- class DisplayName extends Component<Props, State> {
- _nameInput: ?HTMLInputElement;
-
- /**
- * Initializes a new {@code DisplayName} instance.
- *
- * @param {Object} props - The read-only properties with which the new
- * instance is to be initialized.
- */
- constructor(props: Props) {
- super(props);
-
- this.state = {
- editDisplayNameValue: '',
- 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) {
- this._nameInput.select();
- }
- }
-
- /**
- * Implements React's {@link Component#render()}.
- *
- * @inheritdoc
- * @returns {ReactElement}
- */
- render() {
- const {
- _displayName,
- allowEditing,
- 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 }
- spellCheck = { 'false' }
- type = 'text'
- value = { this.state.editDisplayNameValue } />
- );
- }
-
- return (
- <span
- className = 'displayname'
- id = { elementID }
- onClick = { this._onStartEditing }>
- { appendSuffix(_displayName, displayNameSuffix) }
- </span>
- );
- }
-
- _onChange: () => void;
-
- /**
- * 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
- });
- }
-
- _onKeyDown: () => void;
-
- /**
- * 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();
- }
- }
-
- _onStartEditing: () => void;
-
- /**
- * 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 || ''
- });
- }
- }
-
- _onSubmit: () => void;
-
- /**
- * 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 } = this.props;
-
- // Store display name in settings
- dispatch(updateSettings({
- displayName: editDisplayNameValue
- }));
-
- this.setState({
- isEditing: false,
- editDisplayNameValue: ''
- });
-
- this._nameInput = null;
- }
-
- _setNameInputRef: (HTMLInputElement | null) => void;
-
- /**
- * 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;
- }
- }
-
- /**
- * 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));
|