From 9b9facd3d21a7ab341dd6d80fd8b53fb852ae036 Mon Sep 17 00:00:00 2001 From: samogot Date: Thu, 14 Jul 2016 15:19:27 +0300 Subject: PLT-3366 Holding down the ALT key and clicking on a message adds a new messages indicator (squashed) (#3374) --- webapp/components/post_view/components/post.jsx | 9 +++++++++ webapp/components/post_view/components/post_list.jsx | 18 ++++++++++++++++-- webapp/components/post_view/post_view_controller.jsx | 14 ++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) (limited to 'webapp/components/post_view') 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 {
{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} /> ); } -- cgit v1.2.3-1-g7c22