diff options
Diffstat (limited to 'webapp/components')
-rw-r--r-- | webapp/components/edit_post_modal.jsx | 82 | ||||
-rw-r--r-- | webapp/components/post_view/components/post.jsx | 9 | ||||
-rw-r--r-- | webapp/components/post_view/components/post_list.jsx | 18 | ||||
-rw-r--r-- | webapp/components/post_view/post_view_controller.jsx | 14 | ||||
-rw-r--r-- | webapp/components/suggestion/suggestion_box.jsx | 1 |
5 files changed, 88 insertions, 36 deletions
diff --git a/webapp/components/edit_post_modal.jsx b/webapp/components/edit_post_modal.jsx index 4bd23a26d..1ddaee535 100644 --- a/webapp/components/edit_post_modal.jsx +++ b/webapp/components/edit_post_modal.jsx @@ -37,6 +37,11 @@ class EditPostModal extends React.Component { this.handleEditPostEvent = this.handleEditPostEvent.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.onPreferenceChange = this.onPreferenceChange.bind(this); + this.onModalHidden = this.onModalHidden.bind(this); + this.onModalShow = this.onModalShow.bind(this); + this.onModalShown = this.onModalShown.bind(this); + 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}; } @@ -116,46 +121,55 @@ class EditPostModal extends React.Component { ctrlSend: PreferenceStore.getBool(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter') }); } - componentDidMount() { - var self = this; - - $(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', () => { - self.setState({editText: '', originalText: '', title: '', channel_id: '', post_id: '', comments: 0, refocusId: '', error: '', typing: false}); + onModalHidden() { + this.setState({editText: '', originalText: '', title: '', channel_id: '', post_id: '', comments: 0, refocusId: '', error: '', typing: false}); + } + onModalShow(e) { + var button = e.relatedTarget; + if (!button) { + return; + } + this.setState({ + editText: $(button).attr('data-message'), + originalText: $(button).attr('data-message'), + title: $(button).attr('data-title'), + channel_id: $(button).attr('data-channelid'), + post_id: $(button).attr('data-postid'), + comments: $(button).attr('data-comments'), + refocusId: $(button).attr('data-refocusid'), + typing: false }); - - $(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', (e) => { - var button = e.relatedTarget; - if (!button) { - return; - } - self.setState({ - editText: $(button).attr('data-message'), - originalText: $(button).attr('data-message'), - title: $(button).attr('data-title'), - channel_id: $(button).attr('data-channelid'), - post_id: $(button).attr('data-postid'), - comments: $(button).attr('data-comments'), - refocusId: $(button).attr('data-refocusid'), - typing: false + } + onModalShown() { + this.refs.editbox.focus(); + } + onModalHide() { + if (this.state.refocusId !== '') { + setTimeout(() => { + $(this.state.refocusId).get(0).focus(); }); - }); - - $(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', () => { - self.refs.editbox.focus(); - }); - - $(ReactDOM.findDOMNode(this.refs.modal)).on('hide.bs.modal', () => { - if (self.state.refocusId !== '') { - setTimeout(() => { - $(self.state.refocusId).get(0).focus(); - }); - } - }); - + } + } + 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); + $(this.refs.modal).on('shown.bs.modal', this.onModalShown); + $(this.refs.modal).on('hide.bs.modal', this.onModalHide); + $(this.refs.modal).on('keydown', this.onModalKeyDown); 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); + $(this.refs.modal).off('shown.bs.modal', this.onModalShown); + $(this.refs.modal).off('hide.bs.modal', this.onModalHide); + $(this.refs.modal).off('keydown', this.onModalKeyDown); PostStore.removeEditPostListner(this.handleEditPostEvent); PreferenceStore.removeChangeListener(this.onPreferenceChange); } diff --git a/webapp/components/post_view/components/post.jsx b/webapp/components/post_view/components/post.jsx index 21d335a51..ff443e355 100644 --- a/webapp/components/post_view/components/post.jsx +++ b/webapp/components/post_view/components/post.jsx @@ -10,6 +10,7 @@ const ActionTypes = Constants.ActionTypes; import * as Utils from 'utils/utils.jsx'; import * as PostUtils from 'utils/post_utils.jsx'; import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; +import * as PostActions from 'actions/post_actions.jsx'; import React from 'react'; @@ -20,6 +21,7 @@ export default class Post extends React.Component { this.handleCommentClick = this.handleCommentClick.bind(this); this.handleDropdownOpened = this.handleDropdownOpened.bind(this); this.forceUpdateInfo = this.forceUpdateInfo.bind(this); + this.handlePostClick = this.handlePostClick.bind(this); this.state = { dropdownOpened: false @@ -47,6 +49,12 @@ export default class Post extends React.Component { this.refs.info.forceUpdate(); this.refs.header.forceUpdate(); } + handlePostClick(e) { + if (e.altKey) { + e.preventDefault(); + PostActions.setUnreadPost(this.props.post.channel_id, this.props.post.id); + } + } shouldComponentUpdate(nextProps, nextState) { if (!Utils.areObjectsEqual(nextProps.post, this.props.post)) { return true; @@ -213,6 +221,7 @@ export default class Post extends React.Component { <div id={'post_' + post.id} className={'post ' + sameUserClass + ' ' + compactClass + ' ' + rootUser + ' ' + postType + ' ' + currentUserCss + ' ' + shouldHighlightClass + ' ' + systemMessageClass + ' ' + hideControls + ' ' + dropdownOpenedClass} + onClick={this.handlePostClick} > <div className={'post__content ' + centerClass}> {profilePicContainer} diff --git a/webapp/components/post_view/components/post_list.jsx b/webapp/components/post_view/components/post_list.jsx index 690cd96c7..70107c838 100644 --- a/webapp/components/post_view/components/post_list.jsx +++ b/webapp/components/post_view/components/post_list.jsx @@ -15,6 +15,8 @@ import * as Utils from 'utils/utils.jsx'; import * as PostUtils from 'utils/post_utils.jsx'; import DelayedAction from 'utils/delayed_action.jsx'; +import * as ChannelActions from 'actions/channel_actions.jsx'; + import Constants from 'utils/constants.jsx'; const ScrollTypes = Constants.ScrollTypes; @@ -41,6 +43,7 @@ export default class PostList extends React.Component { this.handleResize = this.handleResize.bind(this); this.scrollToBottom = this.scrollToBottom.bind(this); this.scrollToBottomAnimated = this.scrollToBottomAnimated.bind(this); + this.handleKeyDown = this.handleKeyDown.bind(this); this.jumpToPostNode = null; this.wasAtBottom = true; @@ -61,6 +64,13 @@ export default class PostList extends React.Component { } } + handleKeyDown(e) { + if (e.which === Constants.KeyCodes.ESCAPE && $('.popover.in,.modal.in').length === 0) { + e.preventDefault(); + ChannelActions.setChannelAsRead(); + } + } + isAtBottom() { // consider the view to be at the bottom if it's within this many pixels of the bottom const atBottomMargin = 10; @@ -297,7 +307,7 @@ export default class PostList extends React.Component { ); } - if (postUserId !== userId && + if ((postUserId !== userId || this.props.ownNewMessage) && this.props.lastViewed !== 0 && post.create_at > this.props.lastViewed && !renderedLastViewed) { @@ -417,10 +427,12 @@ export default class PostList extends React.Component { } window.addEventListener('resize', this.handleResize); + window.addEventListener('keydown', this.handleKeyDown); } componentWillUnmount() { window.removeEventListener('resize', this.handleResize); + window.removeEventListener('keydown', this.handleKeyDown); this.scrollStopAction.cancel(); } @@ -515,7 +527,8 @@ export default class PostList extends React.Component { } PostList.defaultProps = { - lastViewed: 0 + lastViewed: 0, + ownNewMessage: false }; PostList.propTypes = { @@ -529,6 +542,7 @@ PostList.propTypes = { showMoreMessagesTop: React.PropTypes.bool, showMoreMessagesBottom: React.PropTypes.bool, lastViewed: React.PropTypes.number, + ownNewMessage: React.PropTypes.bool, postsToHighlight: React.PropTypes.object, displayNameType: React.PropTypes.string, displayPostsInCenter: React.PropTypes.bool, diff --git a/webapp/components/post_view/post_view_controller.jsx b/webapp/components/post_view/post_view_controller.jsx index 17c3e94ae..3aba569fe 100644 --- a/webapp/components/post_view/post_view_controller.jsx +++ b/webapp/components/post_view/post_view_controller.jsx @@ -27,6 +27,7 @@ export default class PostViewController extends React.Component { this.onPostsChange = this.onPostsChange.bind(this); this.onEmojisChange = this.onEmojisChange.bind(this); this.onPostsViewJumpRequest = this.onPostsViewJumpRequest.bind(this); + this.onSetNewMessageIndicator = this.onSetNewMessageIndicator.bind(this); this.onPostListScroll = this.onPostListScroll.bind(this); this.onActivate = this.onActivate.bind(this); this.onDeactivate = this.onDeactivate.bind(this); @@ -50,6 +51,7 @@ export default class PostViewController extends React.Component { profiles, atTop: PostStore.getVisibilityAtTop(channel.id), lastViewed, + ownNewMessage: false, scrollType: ScrollTypes.NEW_MESSAGE, displayNameType: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, 'name_format', 'false'), displayPostsInCenter: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT) === Preferences.CHANNEL_DISPLAY_MODE_CENTERED, @@ -117,6 +119,7 @@ export default class PostViewController extends React.Component { PostStore.addChangeListener(this.onPostsChange); PostStore.addPostsViewJumpListener(this.onPostsViewJumpRequest); EmojiStore.addChangeListener(this.onEmojisChange); + ChannelStore.addLastViewedListener(this.onSetNewMessageIndicator); } onDeactivate() { @@ -125,6 +128,7 @@ export default class PostViewController extends React.Component { PostStore.removeChangeListener(this.onPostsChange); PostStore.removePostsViewJumpListener(this.onPostsViewJumpRequest); EmojiStore.removeChangeListener(this.onEmojisChange); + ChannelStore.removeLastViewedListener(this.onSetNewMessageIndicator); } componentWillReceiveProps(nextProps) { @@ -149,6 +153,7 @@ export default class PostViewController extends React.Component { this.setState({ channel, lastViewed, + ownNewMessage: false, profiles: JSON.parse(JSON.stringify(profiles)), postList: JSON.parse(JSON.stringify(PostStore.getVisiblePosts(channel.id))), displayNameType: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, 'name_format', 'false'), @@ -178,6 +183,10 @@ export default class PostViewController extends React.Component { } } + onSetNewMessageIndicator(lastViewed, ownNewMessage) { + this.setState({lastViewed, ownNewMessage}); + } + onPostListScroll(atBottom) { if (atBottom) { this.setState({scrollType: ScrollTypes.BOTTOM}); @@ -219,6 +228,10 @@ export default class PostViewController extends React.Component { return true; } + if (nextState.ownNewMessage !== this.state.ownNewMessage) { + return true; + } + if (nextState.showMoreMessagesTop !== this.state.showMoreMessagesTop) { return true; } @@ -277,6 +290,7 @@ export default class PostViewController extends React.Component { useMilitaryTime={this.state.useMilitaryTime} lastViewed={this.state.lastViewed} emojis={this.state.emojis} + ownNewMessage={this.state.ownNewMessage} /> ); } diff --git a/webapp/components/suggestion/suggestion_box.jsx b/webapp/components/suggestion/suggestion_box.jsx index 2184b9fab..47426f6db 100644 --- a/webapp/components/suggestion/suggestion_box.jsx +++ b/webapp/components/suggestion/suggestion_box.jsx @@ -128,6 +128,7 @@ export default class SuggestionBox extends React.Component { e.preventDefault(); } else if (e.which === KeyCodes.ESCAPE) { GlobalActions.emitClearSuggestions(this.suggestionId); + e.stopPropagation(); } else if (this.props.onKeyDown) { this.props.onKeyDown(e); } |