From 002e48b88679db89a0c7cfbc7601c9e94c74540d Mon Sep 17 00:00:00 2001 From: Leonard Kim Date: Fri, 28 Jul 2017 10:58:04 -0700 Subject: [PATCH] feat(display-name): convert prompt to react Create a new component that uses Dialog. Reuse existing actions for updating a participant's display name. --- modules/UI/UI.js | 49 +----- react/features/display-name/actions.js | 12 ++ .../components/DisplayName.native.js | 0 .../{DisplayName.js => DisplayName.web.js} | 0 .../components/DisplayNamePrompt.native.js | 0 .../components/DisplayNamePrompt.web.js | 150 ++++++++++++++++++ .../features/display-name/components/index.js | 1 + react/features/display-name/index.js | 1 + 8 files changed, 166 insertions(+), 47 deletions(-) create mode 100644 react/features/display-name/actions.js create mode 100644 react/features/display-name/components/DisplayName.native.js rename react/features/display-name/components/{DisplayName.js => DisplayName.web.js} (100%) create mode 100644 react/features/display-name/components/DisplayNamePrompt.native.js create mode 100644 react/features/display-name/components/DisplayNamePrompt.web.js diff --git a/modules/UI/UI.js b/modules/UI/UI.js index 1aa3f4648..f0a4deaa6 100644 --- a/modules/UI/UI.js +++ b/modules/UI/UI.js @@ -29,6 +29,7 @@ import { setAudioMuted, setVideoMuted } from '../../react/features/base/media'; import { openDeviceSelectionDialog } from '../../react/features/device-selection'; +import { openDisplayNamePrompt } from '../../react/features/display-name'; import { checkAutoEnableDesktopSharing, dockToolbox, @@ -867,53 +868,7 @@ UI.participantConnectionStatusChanged = function (id) { * Prompt user for nickname. */ UI.promptDisplayName = () => { - const labelKey = 'dialog.enterDisplayName'; - const message = ( - `
- - -
` - ); - - // Don't use a translation string, because we're too early in the call and - // the translation may not be initialised. - const buttons = { Ok: true }; - - const dialog = messageHandler.openDialog( - 'dialog.displayNameRequired', - message, - true, - buttons, - (e, v, m, f) => { - e.preventDefault(); - if (v) { - const displayName = f.displayName; - - if (displayName) { - UI.inputDisplayNameHandler(displayName); - dialog.close(); - return; - } - } - }, - () => { - const form = $.prompt.getPrompt(); - const input = form.find("input[name='displayName']"); - const button = form.find("button"); - - input.focus(); - button.attr("disabled", "disabled"); - input.keyup(() => { - if (input.val()) { - button.removeAttr("disabled"); - } else { - button.attr("disabled", "disabled"); - } - }); - } - ); + APP.store.dispatch(openDisplayNamePrompt()); }; /** diff --git a/react/features/display-name/actions.js b/react/features/display-name/actions.js new file mode 100644 index 000000000..39dbc4c3b --- /dev/null +++ b/react/features/display-name/actions.js @@ -0,0 +1,12 @@ +import { openDialog } from '../../features/base/dialog'; + +import { DisplayNamePrompt } from './components'; + +/** + * Signals to open a dialog with the {@code DisplayNamePrompt} component. + * + * @returns {Object} + */ +export function openDisplayNamePrompt() { + return openDialog(DisplayNamePrompt); +} diff --git a/react/features/display-name/components/DisplayName.native.js b/react/features/display-name/components/DisplayName.native.js new file mode 100644 index 000000000..e69de29bb diff --git a/react/features/display-name/components/DisplayName.js b/react/features/display-name/components/DisplayName.web.js similarity index 100% rename from react/features/display-name/components/DisplayName.js rename to react/features/display-name/components/DisplayName.web.js diff --git a/react/features/display-name/components/DisplayNamePrompt.native.js b/react/features/display-name/components/DisplayNamePrompt.native.js new file mode 100644 index 000000000..e69de29bb diff --git a/react/features/display-name/components/DisplayNamePrompt.web.js b/react/features/display-name/components/DisplayNamePrompt.web.js new file mode 100644 index 000000000..c4a20db98 --- /dev/null +++ b/react/features/display-name/components/DisplayNamePrompt.web.js @@ -0,0 +1,150 @@ +import AKFieldText from '@atlaskit/field-text'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; + +import { Dialog } from '../../base/dialog'; +import { translate } from '../../base/i18n'; +import { + getLocalParticipant, + participantDisplayNameChanged +} from '../../base/participants'; + +/** + * Implements a React {@code Component} for displaying a dialog with an field + * for setting the local participant's display name. + * + * @extends Component + */ +class DisplayNamePrompt extends Component { + /** + * {@code DisplayNamePrompt} component's property types. + * + * @static + */ + static propTypes = { + /** + * The current ID for the local participant. Used for setting the + * display name on the associated participant. + */ + _localParticipantID: React.PropTypes.string, + + /** + * Invoked to update the local participant's display name. + */ + dispatch: React.PropTypes.func, + + /** + * Invoked to obtain translated strings. + */ + t: React.PropTypes.func + }; + + /** + * Initializes a new {@code DisplayNamePrompt} instance. + * + * @param {Object} props - The read-only properties with which the new + * instance is to be initialized. + */ + constructor(props) { + super(props); + + this.state = { + /** + * The name to show in the display name text field. + * + * @type {string} + */ + displayName: '' + }; + + // Bind event handlers so they are only bound once for every instance. + this._onDisplayNameChange = this._onDisplayNameChange.bind(this); + this._onSubmit = this._onSubmit.bind(this); + } + + /** + * Implements React's {@link Component#render()}. + * + * @inheritdoc + * @returns {ReactElement} + */ + render() { + return ( + + + ); + } + + /** + * Updates the entered display name. + * + * @param {Object} event - The DOM event triggered from the entered display + * name value having changed. + * @private + * @returns {void} + */ + _onDisplayNameChange(event) { + this.setState({ + displayName: event.target.value + }); + } + + /** + * Dispatches an action to update the local participant's display name. A + * name must be entered for the action to dispatch. + * + * @private + * @returns {void} + */ + _onSubmit() { + const { displayName } = this.state; + + if (!displayName.trim()) { + return false; + } + + const { dispatch, _localParticipantID } = this.props; + + dispatch( + participantDisplayNameChanged(_localParticipantID, displayName)); + + return true; + } +} + +/** + * 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)); diff --git a/react/features/display-name/components/index.js b/react/features/display-name/components/index.js index be74b9fa7..29a1a619f 100644 --- a/react/features/display-name/components/index.js +++ b/react/features/display-name/components/index.js @@ -1 +1,2 @@ export { default as DisplayName } from './DisplayName'; +export { default as DisplayNamePrompt } from './DisplayNamePrompt'; diff --git a/react/features/display-name/index.js b/react/features/display-name/index.js index 07635cbbc..3c46ed49d 100644 --- a/react/features/display-name/index.js +++ b/react/features/display-name/index.js @@ -1 +1,2 @@ +export * from './actions'; export * from './components';