diff --git a/webapp/components/channel_switch_modal.jsx b/webapp/components/channel_switch_modal.jsx index 9bb98d74d1..18e0f9f594 100644 --- a/webapp/components/channel_switch_modal.jsx +++ b/webapp/components/channel_switch_modal.jsx @@ -21,7 +21,7 @@ export default class SwitchChannelModal extends React.Component { constructor() { super(); - this.onUserInput = this.onUserInput.bind(this); + this.onInput = this.onInput.bind(this); this.onShow = this.onShow.bind(this); this.onHide = this.onHide.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); @@ -57,8 +57,8 @@ export default class SwitchChannelModal extends React.Component { this.props.onHide(); } - onUserInput(message) { - this.setState({text: message}); + onInput(e) { + this.setState({text: e.target.value}); } handleKeyDown(e) { @@ -122,7 +122,7 @@ export default class SwitchChannelModal extends React.Component { ref='search' className='form-control focused' type='input' - onUserInput={this.onUserInput} + onInput={this.onInput} value={this.state.text} onKeyDown={this.handleKeyDown} listComponent={SuggestionList} diff --git a/webapp/components/create_comment.jsx b/webapp/components/create_comment.jsx index 1f21febf1c..bf23f7b446 100644 --- a/webapp/components/create_comment.jsx +++ b/webapp/components/create_comment.jsx @@ -19,33 +19,14 @@ import * as GlobalActions from 'actions/global_actions.jsx'; import Constants from 'utils/constants.jsx'; -import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'react-intl'; +import {FormattedMessage} from 'react-intl'; const ActionTypes = Constants.ActionTypes; const KeyCodes = Constants.KeyCodes; -const holders = defineMessages({ - commentLength: { - id: 'create_comment.commentLength', - defaultMessage: 'Comment length must be less than {max} characters.' - }, - comment: { - id: 'create_comment.comment', - defaultMessage: 'Add Comment' - }, - addComment: { - id: 'create_comment.addComment', - defaultMessage: 'Add a comment...' - }, - commentTitle: { - id: 'create_comment.commentTitle', - defaultMessage: 'Comment' - } -}); - import React from 'react'; -class CreateComment extends React.Component { +export default class CreateComment extends React.Component { constructor(props) { super(props); @@ -53,7 +34,7 @@ class CreateComment extends React.Component { this.handleSubmit = this.handleSubmit.bind(this); this.commentMsgKeyPress = this.commentMsgKeyPress.bind(this); - this.handleUserInput = this.handleUserInput.bind(this); + this.handleInput = this.handleInput.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.handleUploadClick = this.handleUploadClick.bind(this); this.handleUploadStart = this.handleUploadStart.bind(this); @@ -76,8 +57,7 @@ class CreateComment extends React.Component { previews: draft.previews, submitting: false, ctrlSend: PreferenceStore.getBool(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter'), - showPostDeletedModal: false, - typing: false + showPostDeletedModal: false }; } @@ -126,7 +106,15 @@ class CreateComment extends React.Component { } if (post.message.length > Constants.CHARACTER_LIMIT) { - this.setState({postError: this.props.intl.formatMessage(holders.commentLength, {max: Constants.CHARACTER_LIMIT})}); + this.setState({ + postError: ( + + ) + }); return; } @@ -175,8 +163,7 @@ class CreateComment extends React.Component { submitting: false, postError: null, previews: [], - serverError: null, - typing: false + serverError: null }); } @@ -192,15 +179,16 @@ class CreateComment extends React.Component { GlobalActions.emitLocalUserTypingEvent(this.props.channelId, this.props.rootId); } - handleUserInput(messageText) { + handleInput(e) { + const messageText = e.target.value; + const draft = PostStore.getCommentDraft(this.props.rootId); draft.message = messageText; PostStore.storeCommentDraft(this.props.rootId, draft); $('.post-right__scroll').parent().scrollTop($('.post-right__scroll')[0].scrollHeight); - const typing = messageText !== ''; - this.setState({messageText, typing}); + this.setState({messageText}); } handleKeyDown(e) { @@ -220,7 +208,7 @@ class CreateComment extends React.Component { AppDispatcher.handleViewAction({ type: ActionTypes.RECEIVED_EDIT_POST, refocusId: '#reply_textbox', - title: this.props.intl.formatMessage(holders.commentTitle), + title: Utils.localizeMessage('create_comment.commentTitle', 'Comment'), message: lastPost.message, postId: lastPost.id, channelId: lastPost.channel_id, @@ -319,7 +307,7 @@ class CreateComment extends React.Component { componentWillReceiveProps(newProps) { if (newProps.rootId !== this.props.rootId) { const draft = PostStore.getCommentDraft(newProps.rootId); - this.setState({messageText: draft.message, uploadsInProgress: draft.uploadsInProgress, previews: draft.previews, typing: false}); + this.setState({messageText: draft.message, uploadsInProgress: draft.uploadsInProgress, previews: draft.previews}); } } @@ -395,7 +383,6 @@ class CreateComment extends React.Component { ); } - const {formatMessage} = this.props.intl; return (
@@ -405,12 +392,11 @@ class CreateComment extends React.Component { >
{uploadsInProgressText} @@ -455,9 +441,6 @@ class CreateComment extends React.Component { } CreateComment.propTypes = { - intl: intlShape.isRequired, channelId: React.PropTypes.string.isRequired, rootId: React.PropTypes.string.isRequired -}; - -export default injectIntl(CreateComment); +}; \ No newline at end of file diff --git a/webapp/components/create_post.jsx b/webapp/components/create_post.jsx index 5101c751d3..9b61cca247 100644 --- a/webapp/components/create_post.jsx +++ b/webapp/components/create_post.jsx @@ -23,7 +23,7 @@ import PreferenceStore from 'stores/preference_store.jsx'; import Constants from 'utils/constants.jsx'; -import {intlShape, injectIntl, defineMessages, FormattedHTMLMessage} from 'react-intl'; +import {FormattedHTMLMessage} from 'react-intl'; import {browserHistory} from 'react-router/es6'; const Preferences = Constants.Preferences; @@ -31,24 +31,9 @@ const TutorialSteps = Constants.TutorialSteps; const ActionTypes = Constants.ActionTypes; const KeyCodes = Constants.KeyCodes; -const holders = defineMessages({ - comment: { - id: 'create_post.comment', - defaultMessage: 'Comment' - }, - post: { - id: 'create_post.post', - defaultMessage: 'Post' - }, - write: { - id: 'create_post.write', - defaultMessage: 'Write a message...' - } -}); - import React from 'react'; -class CreatePost extends React.Component { +export default class CreatePost extends React.Component { constructor(props) { super(props); @@ -57,7 +42,7 @@ class CreatePost extends React.Component { this.getCurrentDraft = this.getCurrentDraft.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.postMsgKeyPress = this.postMsgKeyPress.bind(this); - this.handleUserInput = this.handleUserInput.bind(this); + this.handleInput = this.handleInput.bind(this); this.handleUploadClick = this.handleUploadClick.bind(this); this.handleUploadStart = this.handleUploadStart.bind(this); this.handleFileUploadComplete = this.handleFileUploadComplete.bind(this); @@ -87,8 +72,7 @@ class CreatePost extends React.Component { ctrlSend: PreferenceStore.getBool(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter'), fullWidthTextBox: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT) === Preferences.CHANNEL_DISPLAY_MODE_FULL_SCREEN, showTutorialTip: false, - showPostDeletedModal: false, - typing: false + showPostDeletedModal: false }; } @@ -133,7 +117,7 @@ class CreatePost extends React.Component { MessageHistoryStore.storeMessageInHistory(this.state.messageText); - this.setState({submitting: true, serverError: null, typing: false}); + this.setState({submitting: true, serverError: null}); if (post.message.indexOf('/') === 0) { ChannelActions.executeCommand( @@ -223,9 +207,9 @@ class CreatePost extends React.Component { GlobalActions.emitLocalUserTypingEvent(this.state.channelId, ''); } - handleUserInput(messageText) { - const typing = messageText !== ''; - this.setState({messageText, typing}); + handleInput(e) { + const messageText = e.target.value; + this.setState({messageText}); const draft = PostStore.getCurrentDraft(); draft.message = messageText; @@ -372,7 +356,7 @@ class CreatePost extends React.Component { if (this.state.channelId !== channelId) { const draft = this.getCurrentDraft(); - this.setState({channelId, messageText: draft.messageText, initialText: draft.messageText, submitting: false, typing: false, serverError: null, postError: null, previews: draft.previews, uploadsInProgress: draft.uploadsInProgress}); + this.setState({channelId, messageText: draft.messageText, initialText: draft.messageText, submitting: false, serverError: null, postError: null, previews: draft.previews, uploadsInProgress: draft.uploadsInProgress}); } } @@ -408,8 +392,13 @@ class CreatePost extends React.Component { if (!lastPost) { return; } - const {formatMessage} = this.props.intl; - var type = (lastPost.root_id && lastPost.root_id.length > 0) ? formatMessage(holders.comment) : formatMessage(holders.post); + + let type; + if (lastPost.root_id && lastPost.root_id.length > 0) { + type = Utils.localizeMessage('create_post.comment', 'Comment'); + } else { + type = Utils.localizeMessage('create_post.post', 'Post'); + } AppDispatcher.handleViewAction({ type: ActionTypes.RECEIVED_EDIT_POST, @@ -519,12 +508,11 @@ class CreatePost extends React.Component {
); } -} - -CreatePost.propTypes = { - intl: intlShape.isRequired -}; - -export default injectIntl(CreatePost); +} \ No newline at end of file diff --git a/webapp/components/edit_post_modal.jsx b/webapp/components/edit_post_modal.jsx index 1ddaee535f..8be0ba2438 100644 --- a/webapp/components/edit_post_modal.jsx +++ b/webapp/components/edit_post_modal.jsx @@ -11,31 +11,25 @@ import BrowserStore from 'stores/browser_store.jsx'; import PostStore from 'stores/post_store.jsx'; import MessageHistoryStore from 'stores/message_history_store.jsx'; import PreferenceStore from 'stores/preference_store.jsx'; +import * as Utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; -import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'react-intl'; +import {FormattedMessage} from 'react-intl'; var KeyCodes = Constants.KeyCodes; -const holders = defineMessages({ - editPost: { - id: 'edit_post.editPost', - defaultMessage: 'Edit the post...' - } -}); - import React from 'react'; -class EditPostModal extends React.Component { +export default class EditPostModal extends React.Component { constructor(props) { super(props); this.handleEdit = this.handleEdit.bind(this); - this.handleEditInput = this.handleEditInput.bind(this); this.handleEditKeyPress = this.handleEditKeyPress.bind(this); this.handleEditPostEvent = this.handleEditPostEvent.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); + this.handleInput = this.handleInput.bind(this); this.onPreferenceChange = this.onPreferenceChange.bind(this); this.onModalHidden = this.onModalHidden.bind(this); this.onModalShow = this.onModalShow.bind(this); @@ -43,8 +37,9 @@ class EditPostModal extends React.Component { this.onModalHide = this.onModalHide.bind(this); this.onModalKeyDown = this.onModalKeyDown.bind(this); - this.state = {editText: '', originalText: '', title: '', post_id: '', channel_id: '', comments: 0, refocusId: '', typing: false}; + this.state = {editText: '', originalText: '', title: '', post_id: '', channel_id: '', comments: 0, refocusId: ''}; } + handleEdit() { var updatedPost = {}; updatedPost.message = this.state.editText.trim(); @@ -82,10 +77,13 @@ class EditPostModal extends React.Component { $('#edit_post').modal('hide'); } - handleEditInput(editMessage) { - const typing = editMessage !== ''; - this.setState({editText: editMessage, typing}); + + handleInput(e) { + this.setState({ + editText: e.target.value + }); } + handleEditKeyPress(e) { if (!this.state.ctrlSend && e.which === KeyCodes.ENTER && !e.shiftKey && !e.altKey) { e.preventDefault(); @@ -97,6 +95,7 @@ class EditPostModal extends React.Component { this.handleSubmit(e); } } + handleEditPostEvent(options) { this.setState({ editText: options.message || '', @@ -105,25 +104,28 @@ class EditPostModal extends React.Component { post_id: options.postId || '', channel_id: options.channelId || '', comments: options.comments || 0, - refocusId: options.refocusId || '', - typing: false + refocusId: options.refocusId || '' }); $(ReactDOM.findDOMNode(this.refs.modal)).modal('show'); } + handleKeyDown(e) { if (this.state.ctrlSend && e.keyCode === KeyCodes.ENTER && e.ctrlKey === true) { this.handleEdit(e); } } + onPreferenceChange() { this.setState({ ctrlSend: PreferenceStore.getBool(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter') }); } + onModalHidden() { this.setState({editText: '', originalText: '', title: '', channel_id: '', post_id: '', comments: 0, refocusId: '', error: '', typing: false}); } + onModalShow(e) { var button = e.relatedTarget; if (!button) { @@ -140,9 +142,11 @@ class EditPostModal extends React.Component { typing: false }); } + onModalShown() { this.refs.editbox.focus(); } + onModalHide() { if (this.state.refocusId !== '') { setTimeout(() => { @@ -150,11 +154,13 @@ class EditPostModal extends React.Component { }); } } + onModalKeyDown(e) { if (e.which === Constants.KeyCodes.ESCAPE) { e.stopPropagation(); } } + componentDidMount() { $(this.refs.modal).on('hidden.bs.modal', this.onModalHidden); $(this.refs.modal).on('show.bs.modal', this.onModalShow); @@ -164,6 +170,7 @@ class EditPostModal extends React.Component { PostStore.addEditPostListener(this.handleEditPostEvent); PreferenceStore.addChangeListener(this.onPreferenceChange); } + componentWillUnmount() { $(this.refs.modal).off('hidden.bs.modal', this.onModalHidden); $(this.refs.modal).off('show.bs.modal', this.onModalShow); @@ -173,6 +180,7 @@ class EditPostModal extends React.Component { PostStore.removeEditPostListner(this.handleEditPostEvent); PreferenceStore.removeChangeListener(this.onPreferenceChange); } + render() { var error = (

); if (this.state.error) { @@ -212,12 +220,11 @@ class EditPostModal extends React.Component {
{ this.setState({isSearching: false}); - if (utils.isMobile()) { + if (Utils.isMobile()) { ReactDOM.findDOMNode(this.refs.search).value = ''; } @@ -134,6 +137,7 @@ class SearchBar extends React.Component { ); } } + handleSubmit(e) { e.preventDefault(); this.performSearch(this.state.searchTerm.trim()); @@ -178,11 +182,11 @@ class SearchBar extends React.Component { ); } -} - -SearchBar.propTypes = { - intl: intlShape.isRequired -}; - -export default injectIntl(SearchBar); - +} \ No newline at end of file diff --git a/webapp/components/suggestion/suggestion_box.jsx b/webapp/components/suggestion/suggestion_box.jsx index 47426f6db0..d4b1507875 100644 --- a/webapp/components/suggestion/suggestion_box.jsx +++ b/webapp/components/suggestion/suggestion_box.jsx @@ -21,8 +21,8 @@ export default class SuggestionBox extends React.Component { this.handleDocumentClick = this.handleDocumentClick.bind(this); - this.handleChange = this.handleChange.bind(this); this.handleCompleteWord = this.handleCompleteWord.bind(this); + this.handleInput = this.handleInput.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.handlePretextChanged = this.handlePretextChanged.bind(this); @@ -70,27 +70,24 @@ export default class SuggestionBox extends React.Component { } } - handleChange(e) { + handleInput(e) { const textbox = ReactDOM.findDOMNode(this.refs.textbox); const caret = Utils.getCaretPosition(textbox); const pretext = textbox.value.substring(0, caret); GlobalActions.emitSuggestionPretextChanged(this.suggestionId, pretext); - if (this.props.onUserInput) { - this.props.onUserInput(textbox.value); - } - - if (this.props.onChange) { - this.props.onChange(e); + if (this.props.onInput) { + this.props.onInput(e); } } handleCompleteWord(term, matchedPretext) { - const textbox = ReactDOM.findDOMNode(this.refs.textbox); + const textbox = this.refs.textbox; const caret = Utils.getCaretPosition(textbox); const text = textbox.value; const pretext = text.substring(0, caret); + let prefix; if (pretext.endsWith(matchedPretext)) { prefix = pretext.substring(0, pretext.length - matchedPretext.length); @@ -104,10 +101,17 @@ export default class SuggestionBox extends React.Component { const suffix = text.substring(caret); - if (this.props.onUserInput) { - this.props.onUserInput(prefix + term + ' ' + suffix); + this.refs.textbox.value = prefix + term + ' ' + suffix; + + if (this.props.onInput) { + // fake an input event to send back to parent components + const e = { + target: this.refs.textbox + }; + + // don't call handleInput or we'll get into an event loop + this.props.onInput(e); } - this.refs.textbox.value = (prefix + term + ' ' + suffix); // set the caret position after the next rendering window.requestAnimationFrame(() => { @@ -144,18 +148,15 @@ export default class SuggestionBox extends React.Component { } render() { - const newProps = Object.assign({}, this.props, { - onChange: this.handleChange, - onKeyDown: this.handleKeyDown - }); - let textbox = null; if (this.props.type === 'input') { textbox = ( ); } else if (this.props.type === 'search') { @@ -163,7 +164,9 @@ export default class SuggestionBox extends React.Component { ); } else if (this.props.type === 'textarea') { @@ -171,7 +174,9 @@ export default class SuggestionBox extends React.Component { ); } @@ -213,12 +218,10 @@ SuggestionBox.propTypes = { listComponent: React.PropTypes.func.isRequired, type: React.PropTypes.oneOf(['input', 'textarea', 'search']).isRequired, value: React.PropTypes.string.isRequired, - onUserInput: React.PropTypes.func, providers: React.PropTypes.arrayOf(React.PropTypes.object), listStyle: React.PropTypes.string, // explicitly name any input event handlers we override and need to manually call - onChange: React.PropTypes.func, - onKeyDown: React.PropTypes.func, - onHeightChange: React.PropTypes.func + onInput: React.PropTypes.func, + onKeyDown: React.PropTypes.func }; diff --git a/webapp/components/textbox.jsx b/webapp/components/textbox.jsx index 40e6aec4a7..24f58f43e9 100644 --- a/webapp/components/textbox.jsx +++ b/webapp/components/textbox.jsx @@ -176,11 +176,6 @@ export default class Textbox extends React.Component {
); - const otherProps = {}; - if (!this.props.typing) { - otherProps.value = this.props.messageText; - } - return (