PLT-3366 Holding down the ALT key and clicking on a message adds a new messages indicator (squashed) (#3374)
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
6abc9601be
Коммит
9b9facd3d2
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user