mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Refactor listener out of user profile and fix thread logic
This commit is contained in:
@@ -68,7 +68,7 @@ export default class DeletePostModal extends React.Component {
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_POST_SELECTED,
|
||||
results: null
|
||||
postId: null
|
||||
});
|
||||
} else if (selectedPost.id === this.state.post.id && this.state.root_id) {
|
||||
if (selectedPost.root_id && selectedPost.root_id.length > 0 && selectedList.posts[selectedPost.root_id]) {
|
||||
@@ -77,7 +77,7 @@ export default class DeletePostModal extends React.Component {
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_POST_SELECTED,
|
||||
post_list: selectedList
|
||||
postId: selectedPost.root_id
|
||||
});
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
|
||||
@@ -90,7 +90,7 @@ export default class Navbar extends React.Component {
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_POST_SELECTED,
|
||||
results: null
|
||||
postId: null
|
||||
});
|
||||
|
||||
if (e.target.className !== 'navbar-toggle' && e.target.className !== 'icon-bar') {
|
||||
|
||||
@@ -3,15 +3,18 @@
|
||||
|
||||
import PostHeader from './post_header.jsx';
|
||||
import PostBody from './post_body.jsx';
|
||||
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
|
||||
import Constants from '../utils/constants.jsx';
|
||||
|
||||
import UserStore from '../stores/user_store.jsx';
|
||||
import PostStore from '../stores/post_store.jsx';
|
||||
import ChannelStore from '../stores/channel_store.jsx';
|
||||
import * as client from '../utils/client.jsx';
|
||||
|
||||
import Constants from '../utils/constants.jsx';
|
||||
const ActionTypes = Constants.ActionTypes;
|
||||
|
||||
import * as Client from '../utils/client.jsx';
|
||||
import * as AsyncClient from '../utils/async_client.jsx';
|
||||
var ActionTypes = Constants.ActionTypes;
|
||||
import * as utils from '../utils/utils.jsx';
|
||||
import * as Utils from '../utils/utils.jsx';
|
||||
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
|
||||
|
||||
export default class Post extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -26,13 +29,9 @@ export default class Post extends React.Component {
|
||||
handleCommentClick(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var data = {};
|
||||
data.order = [this.props.post.id];
|
||||
data.posts = this.props.posts;
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_POST_SELECTED,
|
||||
post_list: data
|
||||
postId: Utils.getRootId(this.props.post)
|
||||
});
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
@@ -48,14 +47,14 @@ export default class Post extends React.Component {
|
||||
e.preventDefault();
|
||||
|
||||
var post = this.props.post;
|
||||
client.createPost(post, post.channel_id,
|
||||
Client.createPost(post, post.channel_id,
|
||||
(data) => {
|
||||
AsyncClient.getPosts();
|
||||
|
||||
var channel = ChannelStore.get(post.channel_id);
|
||||
var member = ChannelStore.getMember(post.channel_id);
|
||||
member.msg_count = channel.total_msg_count;
|
||||
member.last_viewed_at = utils.getTimestamp();
|
||||
member.last_viewed_at = Utils.getTimestamp();
|
||||
ChannelStore.setChannelMember(member);
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
@@ -75,7 +74,7 @@ export default class Post extends React.Component {
|
||||
this.forceUpdate();
|
||||
}
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (!utils.areObjectsEqual(nextProps.post, this.props.post)) {
|
||||
if (!Utils.areObjectsEqual(nextProps.post, this.props.post)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -129,6 +128,7 @@ export default class Post extends React.Component {
|
||||
const post = this.props.post;
|
||||
const parentPost = this.props.parentPost;
|
||||
const posts = this.props.posts;
|
||||
const user = this.props.user || {};
|
||||
|
||||
if (!post.props) {
|
||||
post.props = {};
|
||||
@@ -156,15 +156,13 @@ export default class Post extends React.Component {
|
||||
}
|
||||
|
||||
let currentUserCss = '';
|
||||
if (UserStore.getCurrentId() === post.user_id && !post.props.from_webhook && !utils.isSystemMessage(post)) {
|
||||
if (UserStore.getCurrentId() === post.user_id && !post.props.from_webhook && !Utils.isSystemMessage(post)) {
|
||||
currentUserCss = 'current--user';
|
||||
}
|
||||
|
||||
const userProfile = UserStore.getProfile(post.user_id);
|
||||
|
||||
let timestamp = UserStore.getCurrentUser().update_at;
|
||||
if (userProfile) {
|
||||
timestamp = userProfile.update_at;
|
||||
let timestamp = user.update_at;
|
||||
if (timestamp == null) {
|
||||
timestamp = UserStore.getCurrentUser().update_at;
|
||||
}
|
||||
|
||||
let sameUserClass = '';
|
||||
@@ -178,18 +176,18 @@ export default class Post extends React.Component {
|
||||
}
|
||||
|
||||
let systemMessageClass = '';
|
||||
if (utils.isSystemMessage(post)) {
|
||||
if (Utils.isSystemMessage(post)) {
|
||||
systemMessageClass = 'post--system';
|
||||
}
|
||||
|
||||
let profilePic = null;
|
||||
if (!this.props.hideProfilePic) {
|
||||
let src = '/api/v1/users/' + post.user_id + '/image?time=' + timestamp + '&' + utils.getSessionIndex();
|
||||
let src = '/api/v1/users/' + post.user_id + '/image?time=' + timestamp + '&' + Utils.getSessionIndex();
|
||||
if (post.props && post.props.from_webhook && global.window.mm_config.EnablePostIconOverride === 'true') {
|
||||
if (post.props.override_icon_url) {
|
||||
src = post.props.override_icon_url;
|
||||
}
|
||||
} else if (utils.isSystemMessage(post)) {
|
||||
} else if (Utils.isSystemMessage(post)) {
|
||||
src = Constants.SYSTEM_MESSAGE_PROFILE_IMAGE;
|
||||
}
|
||||
|
||||
@@ -219,6 +217,7 @@ export default class Post extends React.Component {
|
||||
handleCommentClick={this.handleCommentClick}
|
||||
isLastComment={this.props.isLastComment}
|
||||
sameUser={this.props.sameUser}
|
||||
user={this.props.user}
|
||||
/>
|
||||
<PostBody
|
||||
post={post}
|
||||
@@ -241,6 +240,7 @@ Post.propTypes = {
|
||||
post: React.PropTypes.object.isRequired,
|
||||
posts: React.PropTypes.object,
|
||||
parentPost: React.PropTypes.object,
|
||||
user: React.PropTypes.object,
|
||||
sameUser: React.PropTypes.bool,
|
||||
sameRoot: React.PropTypes.bool,
|
||||
hideProfilePic: React.PropTypes.bool,
|
||||
|
||||
@@ -39,12 +39,10 @@ class PostBody extends React.Component {
|
||||
this.loadImg = this.loadImg.bind(this);
|
||||
|
||||
const linkData = Utils.extractLinks(this.props.post.message);
|
||||
const profiles = UserStore.getProfiles();
|
||||
|
||||
this.state = {
|
||||
links: linkData.links,
|
||||
post: this.props.post,
|
||||
hasUserProfiles: profiles && Object.keys(profiles).length > 1
|
||||
post: this.props.post
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ export default class PostDeletedModal extends React.Component {
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_POST_SELECTED,
|
||||
results: null
|
||||
postId: null
|
||||
});
|
||||
|
||||
this.props.onHide();
|
||||
|
||||
@@ -13,16 +13,17 @@ export default class PostHeader extends React.Component {
|
||||
this.state = {};
|
||||
}
|
||||
render() {
|
||||
var post = this.props.post;
|
||||
const post = this.props.post;
|
||||
const user = this.props.user;
|
||||
|
||||
let userProfile = <UserProfile userId={post.user_id}/>;
|
||||
let userProfile = <UserProfile user={user}/>;
|
||||
let botIndicator;
|
||||
|
||||
if (post.props && post.props.from_webhook) {
|
||||
if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') {
|
||||
userProfile = (
|
||||
<UserProfile
|
||||
userId={post.user_id}
|
||||
user={user}
|
||||
overwriteName={post.props.override_username}
|
||||
disablePopover={true}
|
||||
/>
|
||||
@@ -33,7 +34,7 @@ export default class PostHeader extends React.Component {
|
||||
} else if (Utils.isSystemMessage(post)) {
|
||||
userProfile = (
|
||||
<UserProfile
|
||||
userId={''}
|
||||
user={{}}
|
||||
overwriteName={Constants.SYSTEM_MESSAGE_PROFILE_NAME}
|
||||
overwriteImage={Constants.SYSTEM_MESSAGE_PROFILE_IMAGE}
|
||||
disablePopover={true}
|
||||
@@ -68,6 +69,7 @@ PostHeader.defaultProps = {
|
||||
};
|
||||
PostHeader.propTypes = {
|
||||
post: React.PropTypes.object,
|
||||
user: React.PropTypes.object,
|
||||
commentCount: React.PropTypes.number,
|
||||
isLastComment: React.PropTypes.bool,
|
||||
handleCommentClick: React.PropTypes.func,
|
||||
|
||||
@@ -28,7 +28,6 @@ export default class PostsView extends React.Component {
|
||||
this.handleResize = this.handleResize.bind(this);
|
||||
this.scrollToBottom = this.scrollToBottom.bind(this);
|
||||
this.scrollToBottomAnimated = this.scrollToBottomAnimated.bind(this);
|
||||
this.onUserChange = this.onUserChange.bind(this);
|
||||
|
||||
this.jumpToPostNode = null;
|
||||
this.wasAtBottom = true;
|
||||
@@ -39,8 +38,7 @@ export default class PostsView extends React.Component {
|
||||
this.state = {
|
||||
displayNameType: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, 'name_format', 'false'),
|
||||
isScrolling: false,
|
||||
topPostId: null,
|
||||
hasProfiles: false
|
||||
topPostId: null
|
||||
};
|
||||
}
|
||||
static get SCROLL_TYPE_FREE() {
|
||||
@@ -147,6 +145,7 @@ export default class PostsView extends React.Component {
|
||||
const postCtls = [];
|
||||
let previousPostDay = new Date(0);
|
||||
const userId = UserStore.getCurrentId();
|
||||
const profiles = this.props.profiles;
|
||||
|
||||
let renderedLastViewed = false;
|
||||
|
||||
@@ -230,6 +229,13 @@ export default class PostsView extends React.Component {
|
||||
|
||||
const shouldHighlight = this.props.postsToHighlight && this.props.postsToHighlight.hasOwnProperty(post.id);
|
||||
|
||||
let profile;
|
||||
if (UserStore.getCurrentId() === post.user_id) {
|
||||
profile = UserStore.getCurrentUser();
|
||||
} else {
|
||||
profile = profiles[post.user_id];
|
||||
}
|
||||
|
||||
const postCtl = (
|
||||
<Post
|
||||
key={keyPrefix + 'postKey'}
|
||||
@@ -244,7 +250,8 @@ export default class PostsView extends React.Component {
|
||||
shouldHighlight={shouldHighlight}
|
||||
onClick={() => EventHelpers.emitPostFocusEvent(post.id)} //eslint-disable-line no-loop-func
|
||||
displayNameType={this.state.displayNameType}
|
||||
hasProfiles={this.state.hasProfiles}
|
||||
hasProfiles={profiles && Object.keys(profiles).length > 1}
|
||||
user={profile}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -370,11 +377,9 @@ export default class PostsView extends React.Component {
|
||||
if (this.props.postList != null) {
|
||||
this.updateScrolling();
|
||||
}
|
||||
UserStore.addChangeListener(this.onUserChange);
|
||||
window.addEventListener('resize', this.handleResize);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
UserStore.removeChangeListener(this.onUserChange);
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
}
|
||||
componentDidUpdate() {
|
||||
@@ -418,19 +423,12 @@ export default class PostsView extends React.Component {
|
||||
if (this.state.isScrolling !== nextState.isScrolling) {
|
||||
return true;
|
||||
}
|
||||
if (this.state.hasProfiles !== nextState.hasProfiles) {
|
||||
if (!Utils.areObjectsEqual(this.props.profiles, nextProps.profiles)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
onUserChange() {
|
||||
if (!this.state.hasProfiles) {
|
||||
const profiles = UserStore.getProfiles();
|
||||
|
||||
this.setState({hasProfiles: profiles && Object.keys(profiles).length > 1});
|
||||
}
|
||||
}
|
||||
render() {
|
||||
let posts = [];
|
||||
let order = [];
|
||||
@@ -528,6 +526,7 @@ PostsView.defaultProps = {
|
||||
PostsView.propTypes = {
|
||||
isActive: React.PropTypes.bool,
|
||||
postList: React.PropTypes.object,
|
||||
profiles: React.PropTypes.object,
|
||||
scrollPostId: React.PropTypes.string,
|
||||
scrollType: React.PropTypes.number,
|
||||
postViewScrolled: React.PropTypes.func.isRequired,
|
||||
|
||||
@@ -6,6 +6,7 @@ import LoadingScreen from './loading_screen.jsx';
|
||||
|
||||
import ChannelStore from '../stores/channel_store.jsx';
|
||||
import PostStore from '../stores/post_store.jsx';
|
||||
import UserStore from '../stores/user_store.jsx';
|
||||
|
||||
import * as Utils from '../utils/utils.jsx';
|
||||
import * as EventHelpers from '../dispatcher/event_helpers.jsx';
|
||||
@@ -24,11 +25,13 @@ export default class PostsViewContainer extends React.Component {
|
||||
this.handlePostsViewScroll = this.handlePostsViewScroll.bind(this);
|
||||
this.loadMorePostsTop = this.loadMorePostsTop.bind(this);
|
||||
this.handlePostsViewJumpRequest = this.handlePostsViewJumpRequest.bind(this);
|
||||
this.onUserChange = this.onUserChange.bind(this);
|
||||
|
||||
const currentChannelId = ChannelStore.getCurrentId();
|
||||
const state = {
|
||||
scrollType: PostsView.SCROLL_TYPE_BOTTOM,
|
||||
scrollPost: null
|
||||
scrollPost: null,
|
||||
profiles: JSON.parse(JSON.stringify(UserStore.getProfiles()))
|
||||
};
|
||||
if (currentChannelId) {
|
||||
Object.assign(state, {
|
||||
@@ -54,12 +57,14 @@ export default class PostsViewContainer extends React.Component {
|
||||
ChannelStore.addLeaveListener(this.onChannelLeave);
|
||||
PostStore.addChangeListener(this.onPostsChange);
|
||||
PostStore.addPostsViewJumpListener(this.handlePostsViewJumpRequest);
|
||||
UserStore.addChangeListener(this.onUserChange);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
ChannelStore.removeChangeListener(this.onChannelChange);
|
||||
ChannelStore.removeLeaveListener(this.onChannelLeave);
|
||||
PostStore.removeChangeListener(this.onPostsChange);
|
||||
PostStore.removePostsViewJumpListener(this.handlePostsViewJumpRequest);
|
||||
UserStore.removeChangeListener(this.onUserChange);
|
||||
}
|
||||
handlePostsViewJumpRequest(type, post) {
|
||||
switch (type) {
|
||||
@@ -135,6 +140,9 @@ export default class PostsViewContainer extends React.Component {
|
||||
atTop[this.state.currentChannelIndex] = PostStore.getVisibilityAtTop(currentChannelId);
|
||||
this.setState({postLists, atTop});
|
||||
}
|
||||
onUserChange() {
|
||||
this.setState({profiles: JSON.parse(JSON.stringify(UserStore.getProfiles()))});
|
||||
}
|
||||
getChannelPosts(id) {
|
||||
return PostStore.getVisiblePosts(id);
|
||||
}
|
||||
@@ -180,6 +188,7 @@ export default class PostsViewContainer extends React.Component {
|
||||
showMoreMessagesBottom={false}
|
||||
introText={channel ? createChannelIntroMessage(channel) : null}
|
||||
messageSeparatorTime={this.state.currentLastViewed}
|
||||
profiles={this.state.profiles}
|
||||
/>
|
||||
);
|
||||
if (!postLists[i] && isActive) {
|
||||
|
||||
@@ -194,8 +194,16 @@ class RhsComment extends React.Component {
|
||||
|
||||
var timestamp = UserStore.getCurrentUser().update_at;
|
||||
|
||||
var loading;
|
||||
var postClass = '';
|
||||
let loading;
|
||||
let postClass = '';
|
||||
let message = (
|
||||
<div
|
||||
ref='message_holder'
|
||||
onClick={TextFormatting.handleClick}
|
||||
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(post.message)}}
|
||||
/>
|
||||
);
|
||||
|
||||
if (post.state === Constants.POST_FAILED) {
|
||||
postClass += ' post-fail';
|
||||
loading = (
|
||||
@@ -218,6 +226,13 @@ class RhsComment extends React.Component {
|
||||
src='/static/images/load.gif'
|
||||
/>
|
||||
);
|
||||
} else if (this.props.post.state === Constants.POST_DELETED) {
|
||||
message = (
|
||||
<FormattedMessage
|
||||
id='post_body.deleted'
|
||||
defaultMessage='(message deleted)'
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
var dropdown = this.createDropdown();
|
||||
@@ -246,7 +261,7 @@ class RhsComment extends React.Component {
|
||||
<div>
|
||||
<ul className='post__header'>
|
||||
<li className='col__name'>
|
||||
<strong><UserProfile userId={post.user_id}/></strong>
|
||||
<strong><UserProfile user={this.props.user}/></strong>
|
||||
</li>
|
||||
<li className='col'>
|
||||
<time className='post__time'>
|
||||
@@ -268,11 +283,7 @@ class RhsComment extends React.Component {
|
||||
<div className='post__body'>
|
||||
<div className={postClass}>
|
||||
{loading}
|
||||
<div
|
||||
ref='message_holder'
|
||||
onClick={TextFormatting.handleClick}
|
||||
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(post.message)}}
|
||||
/>
|
||||
{message}
|
||||
</div>
|
||||
{fileAttachment}
|
||||
</div>
|
||||
@@ -288,7 +299,8 @@ RhsComment.defaultProps = {
|
||||
};
|
||||
RhsComment.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
post: React.PropTypes.object
|
||||
post: React.PropTypes.object,
|
||||
user: React.PropTypes.object
|
||||
};
|
||||
|
||||
export default injectIntl(RhsComment);
|
||||
|
||||
@@ -27,7 +27,7 @@ export default class RhsHeaderPost extends React.Component {
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_POST_SELECTED,
|
||||
results: null
|
||||
postId: null
|
||||
});
|
||||
}
|
||||
handleBack(e) {
|
||||
@@ -42,7 +42,7 @@ export default class RhsHeaderPost extends React.Component {
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_POST_SELECTED,
|
||||
results: null
|
||||
postId: null
|
||||
});
|
||||
}
|
||||
render() {
|
||||
|
||||
@@ -50,10 +50,10 @@ export default class RhsRootPost extends React.Component {
|
||||
this.parseEmojis();
|
||||
}
|
||||
render() {
|
||||
var post = this.props.post;
|
||||
var currentUser = UserStore.getCurrentUser();
|
||||
var isOwner = currentUser.id === post.user_id;
|
||||
var isAdmin = Utils.isAdmin(currentUser.roles);
|
||||
const post = this.props.post;
|
||||
const user = this.props.user;
|
||||
var isOwner = user.id === post.user_id;
|
||||
var isAdmin = Utils.isAdmin(user.roles);
|
||||
var timestamp = UserStore.getProfile(post.user_id).update_at;
|
||||
var channel = ChannelStore.get(post.channel_id);
|
||||
|
||||
@@ -62,9 +62,9 @@ export default class RhsRootPost extends React.Component {
|
||||
type = 'Comment';
|
||||
}
|
||||
|
||||
var currentUserCss = '';
|
||||
var userCss = '';
|
||||
if (UserStore.getCurrentId() === post.user_id) {
|
||||
currentUserCss = 'current--user';
|
||||
userCss = 'current--user';
|
||||
}
|
||||
|
||||
var systemMessageClass = '';
|
||||
@@ -185,14 +185,14 @@ export default class RhsRootPost extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
let userProfile = <UserProfile userId={post.user_id}/>;
|
||||
let userProfile = <UserProfile user={user}/>;
|
||||
let botIndicator;
|
||||
|
||||
if (post.props && post.props.from_webhook) {
|
||||
if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') {
|
||||
userProfile = (
|
||||
<UserProfile
|
||||
userId={post.user_id}
|
||||
user={user}
|
||||
overwriteName={post.props.override_username}
|
||||
disablePopover={true}
|
||||
/>
|
||||
@@ -203,7 +203,7 @@ export default class RhsRootPost extends React.Component {
|
||||
} else if (Utils.isSystemMessage(post)) {
|
||||
userProfile = (
|
||||
<UserProfile
|
||||
userId={''}
|
||||
user={{}}
|
||||
overwriteName={Constants.SYSTEM_MESSAGE_PROFILE_NAME}
|
||||
overwriteImage={Constants.SYSTEM_MESSAGE_PROFILE_IMAGE}
|
||||
disablePopover={true}
|
||||
@@ -230,7 +230,7 @@ export default class RhsRootPost extends React.Component {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={'post post--root ' + currentUserCss + ' ' + systemMessageClass}>
|
||||
<div className={'post post--root ' + userCss + ' ' + systemMessageClass}>
|
||||
<div className='post-right-channel__name'>{channelName}</div>
|
||||
<div className='post__content'>
|
||||
<div className='post__img'>
|
||||
@@ -278,10 +278,10 @@ export default class RhsRootPost extends React.Component {
|
||||
}
|
||||
|
||||
RhsRootPost.defaultProps = {
|
||||
post: null,
|
||||
commentCount: 0
|
||||
};
|
||||
RhsRootPost.propTypes = {
|
||||
post: React.PropTypes.object,
|
||||
post: React.PropTypes.object.isRequired,
|
||||
user: React.PropTypes.object.isRequired,
|
||||
commentCount: React.PropTypes.number
|
||||
};
|
||||
|
||||
@@ -19,39 +19,25 @@ export default class RhsThread extends React.Component {
|
||||
|
||||
this.mounted = false;
|
||||
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.onChangeAll = this.onChangeAll.bind(this);
|
||||
this.onPostChange = this.onPostChange.bind(this);
|
||||
this.onUserChange = this.onUserChange.bind(this);
|
||||
this.forceUpdateInfo = this.forceUpdateInfo.bind(this);
|
||||
this.handleResize = this.handleResize.bind(this);
|
||||
|
||||
const state = this.getStateFromStores();
|
||||
const state = {};
|
||||
state.windowWidth = Utils.windowWidth();
|
||||
state.windowHeight = Utils.windowHeight();
|
||||
state.selected = PostStore.getSelectedPost();
|
||||
state.posts = PostStore.getSelectedPostThread();
|
||||
state.profiles = JSON.parse(JSON.stringify(UserStore.getProfiles()));
|
||||
|
||||
this.state = state;
|
||||
}
|
||||
getStateFromStores() {
|
||||
var postList = PostStore.getSelectedPost();
|
||||
if (!postList || postList.order.length < 1 || !postList.posts[postList.order[0]]) {
|
||||
return {postList: {}};
|
||||
}
|
||||
|
||||
var channelId = postList.posts[postList.order[0]].channel_id;
|
||||
var pendingPostsList = PostStore.getPendingPosts(channelId);
|
||||
|
||||
if (pendingPostsList) {
|
||||
for (var pid in pendingPostsList.posts) {
|
||||
if (pendingPostsList.posts.hasOwnProperty(pid)) {
|
||||
postList.posts[pid] = pendingPostsList.posts[pid];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {postList: postList};
|
||||
}
|
||||
componentDidMount() {
|
||||
PostStore.addSelectedPostChangeListener(this.onChange);
|
||||
PostStore.addChangeListener(this.onChangeAll);
|
||||
PostStore.addSelectedPostChangeListener(this.onPostChange);
|
||||
PostStore.addChangeListener(this.onPostChange);
|
||||
PreferenceStore.addChangeListener(this.forceUpdateInfo);
|
||||
UserStore.addChangeListener(this.onUserChange);
|
||||
|
||||
this.resize();
|
||||
window.addEventListener('resize', this.handleResize);
|
||||
@@ -65,14 +51,30 @@ export default class RhsThread extends React.Component {
|
||||
this.resize();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
PostStore.removeSelectedPostChangeListener(this.onChange);
|
||||
PostStore.removeChangeListener(this.onChangeAll);
|
||||
PostStore.removeSelectedPostChangeListener(this.onPostChange);
|
||||
PostStore.removeChangeListener(this.onPostChange);
|
||||
PreferenceStore.removeChangeListener(this.forceUpdateInfo);
|
||||
UserStore.removeChangeListener(this.onUserChange);
|
||||
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
|
||||
this.mounted = false;
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
if (!Utils.areObjectsEqual(nextState.posts, this.state.posts)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Utils.areObjectsEqual(nextState.selected, this.state.selected)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Utils.areObjectsEqual(nextState.profiles, this.state.profiles)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
forceUpdateInfo() {
|
||||
if (this.state.postList) {
|
||||
for (var postId in this.state.postList.posts) {
|
||||
@@ -88,49 +90,14 @@ export default class RhsThread extends React.Component {
|
||||
windowHeight: Utils.windowHeight()
|
||||
});
|
||||
}
|
||||
onChange() {
|
||||
var newState = this.getStateFromStores();
|
||||
if (this.mounted && !Utils.areObjectsEqual(newState, this.state)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
onPostChange() {
|
||||
const selected = PostStore.getSelectedPost();
|
||||
const posts = PostStore.getSelectedPostThread();
|
||||
this.setState({posts, selected});
|
||||
}
|
||||
onChangeAll() {
|
||||
// if something was changed in the channel like adding a
|
||||
// comment or post then lets refresh the sidebar list
|
||||
var currentSelected = PostStore.getSelectedPost();
|
||||
if (!currentSelected || currentSelected.order.length === 0 || !currentSelected.posts[currentSelected.order[0]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
var currentPosts = PostStore.getVisiblePosts(currentSelected.posts[currentSelected.order[0]].channel_id);
|
||||
|
||||
if (!currentPosts || currentPosts.order.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentPosts.posts[currentPosts.order[0]].channel_id === currentSelected.posts[currentSelected.order[0]].channel_id) {
|
||||
for (var key in currentSelected.posts) {
|
||||
if (currentSelected.posts.hasOwnProperty(key)) {
|
||||
var post = currentSelected.posts[key];
|
||||
if (post.pending_post_id) {
|
||||
Reflect.deleteProperty(currentSelected.posts, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var postId in currentPosts.posts) {
|
||||
if (currentPosts.posts.hasOwnProperty(postId)) {
|
||||
currentSelected.posts[postId] = currentPosts.posts[postId];
|
||||
}
|
||||
}
|
||||
|
||||
PostStore.storeSelectedPost(currentSelected);
|
||||
}
|
||||
|
||||
var newState = this.getStateFromStores();
|
||||
if (this.mounted && !Utils.areObjectsEqual(newState, this.state)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
onUserChange() {
|
||||
const profiles = JSON.parse(JSON.stringify(UserStore.getProfiles()));
|
||||
this.setState({profiles});
|
||||
}
|
||||
resize() {
|
||||
$('.post-right__scroll').scrollTop(100000);
|
||||
@@ -140,29 +107,21 @@ export default class RhsThread extends React.Component {
|
||||
}
|
||||
}
|
||||
render() {
|
||||
var postList = this.state.postList;
|
||||
const posts = this.state.posts;
|
||||
const selected = this.state.selected;
|
||||
|
||||
if (postList == null || !postList.order) {
|
||||
if (posts == null || selected == null) {
|
||||
return (
|
||||
<div></div>
|
||||
);
|
||||
}
|
||||
|
||||
var selectedPost = postList.posts[postList.order[0]];
|
||||
var rootPost = null;
|
||||
|
||||
if (selectedPost.root_id === '') {
|
||||
rootPost = selectedPost;
|
||||
} else {
|
||||
rootPost = postList.posts[selectedPost.root_id];
|
||||
}
|
||||
|
||||
var postsArray = [];
|
||||
|
||||
for (var postId in postList.posts) {
|
||||
if (postList.posts.hasOwnProperty(postId)) {
|
||||
var cpost = postList.posts[postId];
|
||||
if (cpost.root_id === rootPost.id) {
|
||||
for (const id in posts) {
|
||||
if (posts.hasOwnProperty(id)) {
|
||||
const cpost = posts[id];
|
||||
if (cpost.root_id === selected.id) {
|
||||
postsArray.push(cpost);
|
||||
}
|
||||
}
|
||||
@@ -199,6 +158,13 @@ export default class RhsThread extends React.Component {
|
||||
searchForm = <SearchBox/>;
|
||||
}
|
||||
|
||||
let profile;
|
||||
if (UserStore.getCurrentId() === selected.user_id) {
|
||||
profile = UserStore.getCurrentUser();
|
||||
} else {
|
||||
profile = this.state.profiles[selected.user_id];
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='post-right__container'>
|
||||
<FileUploadOverlay overlayType='right'/>
|
||||
@@ -210,26 +176,33 @@ export default class RhsThread extends React.Component {
|
||||
/>
|
||||
<div className='post-right__scroll'>
|
||||
<RootPost
|
||||
ref={rootPost.id}
|
||||
post={rootPost}
|
||||
ref={selected.id}
|
||||
post={selected}
|
||||
commentCount={postsArray.length}
|
||||
user={profile}
|
||||
/>
|
||||
<div className='post-right-comments-container'>
|
||||
{postsArray.map(function mapPosts(comPost) {
|
||||
let p;
|
||||
if (UserStore.getCurrentId() === selected.user_id) {
|
||||
p = UserStore.getCurrentUser();
|
||||
} else {
|
||||
p = this.state.profiles[selected.user_id];
|
||||
}
|
||||
return (
|
||||
<Comment
|
||||
ref={comPost.id}
|
||||
key={comPost.id + 'commentKey'}
|
||||
post={comPost}
|
||||
selected={(comPost.id === selectedPost.id)}
|
||||
user={p}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className='post-create__container'>
|
||||
<CreateComment
|
||||
channelId={rootPost.channel_id}
|
||||
rootId={rootPost.id}
|
||||
channelId={selected.channel_id}
|
||||
rootId={selected.id}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -87,7 +87,7 @@ class SearchBar extends React.Component {
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_POST_SELECTED,
|
||||
results: null
|
||||
postId: null
|
||||
});
|
||||
}
|
||||
handleUserInput(text) {
|
||||
|
||||
@@ -32,7 +32,7 @@ export default class SearchResultsHeader extends React.Component {
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_POST_SELECTED,
|
||||
results: null
|
||||
postId: null
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// See License.txt for license information.
|
||||
|
||||
import * as Utils from '../utils/utils.jsx';
|
||||
import UserStore from '../stores/user_store.jsx';
|
||||
|
||||
import {FormattedMessage} from 'mm-intl';
|
||||
|
||||
@@ -19,45 +18,15 @@ function nextId() {
|
||||
export default class UserProfile extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.uniqueId = nextId();
|
||||
this.onChange = this.onChange.bind(this);
|
||||
|
||||
this.state = this.getStateFromStores(this.props.userId);
|
||||
}
|
||||
getStateFromStores(userId) {
|
||||
var profile = UserStore.getProfile(userId);
|
||||
|
||||
if (profile == null) {
|
||||
return {profile: {id: '0', username: '...'}};
|
||||
}
|
||||
|
||||
return {profile};
|
||||
}
|
||||
componentDidMount() {
|
||||
UserStore.addChangeListener(this.onChange);
|
||||
if (!this.props.disablePopover) {
|
||||
$('body').tooltip({selector: '[data-toggle=tooltip]', trigger: 'hover click'});
|
||||
}
|
||||
}
|
||||
componentWillUnmount() {
|
||||
UserStore.removeChangeListener(this.onChange);
|
||||
}
|
||||
onChange(userId) {
|
||||
if (!userId || userId === this.props.userId) {
|
||||
var newState = this.getStateFromStores(this.props.userId);
|
||||
if (!Utils.areObjectsEqual(newState, this.state)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.userId !== nextProps.userId) {
|
||||
this.setState(this.getStateFromStores(nextProps.userId));
|
||||
}
|
||||
}
|
||||
render() {
|
||||
var name = Utils.displayUsername(this.state.profile.id);
|
||||
var name = Utils.displayUsername(this.props.user.id);
|
||||
if (this.props.overwriteName) {
|
||||
name = this.props.overwriteName;
|
||||
} else if (!name) {
|
||||
@@ -68,7 +37,7 @@ export default class UserProfile extends React.Component {
|
||||
return <div>{name}</div>;
|
||||
}
|
||||
|
||||
var profileImg = '/api/v1/users/' + this.state.profile.id + '/image?time=' + this.state.profile.update_at + '&' + Utils.getSessionIndex();
|
||||
var profileImg = '/api/v1/users/' + this.props.user.id + '/image?time=' + this.props.user.update_at + '&' + Utils.getSessionIndex();
|
||||
if (this.props.overwriteImage) {
|
||||
profileImg = this.props.overwriteImage;
|
||||
}
|
||||
@@ -100,14 +69,14 @@ export default class UserProfile extends React.Component {
|
||||
dataContent.push(
|
||||
<div
|
||||
data-toggle='tooltip'
|
||||
title={this.state.profile.email}
|
||||
title={this.props.user.email}
|
||||
key='user-popover-email'
|
||||
>
|
||||
<a
|
||||
href={'mailto:' + this.state.profile.email}
|
||||
href={'mailto:' + this.props.user.email}
|
||||
className='text-nowrap text-lowercase user-popover__email'
|
||||
>
|
||||
{this.state.profile.email}
|
||||
{this.props.user.email}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
@@ -139,13 +108,13 @@ export default class UserProfile extends React.Component {
|
||||
}
|
||||
|
||||
UserProfile.defaultProps = {
|
||||
userId: '',
|
||||
user: {},
|
||||
overwriteName: '',
|
||||
overwriteImage: '',
|
||||
disablePopover: false
|
||||
};
|
||||
UserProfile.propTypes = {
|
||||
userId: React.PropTypes.string,
|
||||
user: React.PropTypes.object.isRequired,
|
||||
overwriteName: React.PropTypes.string,
|
||||
overwriteImage: React.PropTypes.string,
|
||||
disablePopover: React.PropTypes.bool
|
||||
|
||||
@@ -20,72 +20,7 @@ const SELECTED_POST_CHANGE_EVENT = 'selected_post_change';
|
||||
class PostStoreClass extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.emitChange = this.emitChange.bind(this);
|
||||
this.addChangeListener = this.addChangeListener.bind(this);
|
||||
this.removeChangeListener = this.removeChangeListener.bind(this);
|
||||
|
||||
this.emitEditPost = this.emitEditPost.bind(this);
|
||||
this.addEditPostListener = this.addEditPostListener.bind(this);
|
||||
this.removeEditPostListener = this.removeEditPostListner.bind(this);
|
||||
|
||||
this.emitPostsViewJump = this.emitPostsViewJump.bind(this);
|
||||
this.addPostsViewJumpListener = this.addPostsViewJumpListener.bind(this);
|
||||
this.removePostsViewJumpListener = this.removePostsViewJumpListener.bind(this);
|
||||
|
||||
this.emitPostFocused = this.emitPostFocused.bind(this);
|
||||
this.addPostFocusedListener = this.addPostFocusedListener.bind(this);
|
||||
this.removePostFocusedListener = this.removePostFocusedListener.bind(this);
|
||||
|
||||
this.makePostsInfo = this.makePostsInfo.bind(this);
|
||||
|
||||
this.getPost = this.getPost.bind(this);
|
||||
this.getAllPosts = this.getAllPosts.bind(this);
|
||||
this.getEarliestPost = this.getEarliestPost.bind(this);
|
||||
this.getLatestPost = this.getLatestPost.bind(this);
|
||||
this.getVisiblePosts = this.getVisiblePosts.bind(this);
|
||||
this.getVisibilityAtTop = this.getVisibilityAtTop.bind(this);
|
||||
this.getVisibilityAtBottom = this.getVisibilityAtBottom.bind(this);
|
||||
this.requestVisibilityIncrease = this.requestVisibilityIncrease.bind(this);
|
||||
this.getFocusedPostId = this.getFocusedPostId.bind(this);
|
||||
|
||||
this.storePosts = this.storePosts.bind(this);
|
||||
this.storePost = this.storePost.bind(this);
|
||||
this.storeFocusedPost = this.storeFocusedPost.bind(this);
|
||||
this.checkBounds = this.checkBounds.bind(this);
|
||||
|
||||
this.clearFocusedPost = this.clearFocusedPost.bind(this);
|
||||
this.clearChannelVisibility = this.clearChannelVisibility.bind(this);
|
||||
|
||||
this.deletePost = this.deletePost.bind(this);
|
||||
this.removePost = this.removePost.bind(this);
|
||||
|
||||
this.getPendingPosts = this.getPendingPosts.bind(this);
|
||||
this.storePendingPost = this.storePendingPost.bind(this);
|
||||
this.removePendingPost = this.removePendingPost.bind(this);
|
||||
this.clearPendingPosts = this.clearPendingPosts.bind(this);
|
||||
this.updatePendingPost = this.updatePendingPost.bind(this);
|
||||
|
||||
// These functions are bad and work should be done to remove this system when the RHS dies
|
||||
this.storeSelectedPost = this.storeSelectedPost.bind(this);
|
||||
this.getSelectedPost = this.getSelectedPost.bind(this);
|
||||
this.emitSelectedPostChange = this.emitSelectedPostChange.bind(this);
|
||||
this.addSelectedPostChangeListener = this.addSelectedPostChangeListener.bind(this);
|
||||
this.removeSelectedPostChangeListener = this.removeSelectedPostChangeListener.bind(this);
|
||||
this.selectedPost = null;
|
||||
|
||||
this.getEmptyDraft = this.getEmptyDraft.bind(this);
|
||||
this.storeCurrentDraft = this.storeCurrentDraft.bind(this);
|
||||
this.getCurrentDraft = this.getCurrentDraft.bind(this);
|
||||
this.storeDraft = this.storeDraft.bind(this);
|
||||
this.getDraft = this.getDraft.bind(this);
|
||||
this.storeCommentDraft = this.storeCommentDraft.bind(this);
|
||||
this.getCommentDraft = this.getCommentDraft.bind(this);
|
||||
this.clearDraftUploads = this.clearDraftUploads.bind(this);
|
||||
this.clearCommentDraftUploads = this.clearCommentDraftUploads.bind(this);
|
||||
this.getCurrentUsersLatestPost = this.getCurrentUsersLatestPost.bind(this);
|
||||
this.getCommentCount = this.getCommentCount.bind(this);
|
||||
|
||||
this.selectedPostId = null;
|
||||
this.postsInfo = {};
|
||||
this.currentFocusedPostId = null;
|
||||
}
|
||||
@@ -421,12 +356,59 @@ class PostStoreClass extends EventEmitter {
|
||||
this.emitChange();
|
||||
}
|
||||
|
||||
storeSelectedPost(postList) {
|
||||
this.selectedPost = postList;
|
||||
storeSelectedPostId(postId) {
|
||||
this.selectedPostId = postId;
|
||||
}
|
||||
|
||||
getSelectedPostId() {
|
||||
return this.selectedPostId;
|
||||
}
|
||||
|
||||
getSelectedPost() {
|
||||
return this.selectedPost;
|
||||
if (this.selectedPostId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const k in this.postsInfo) {
|
||||
if (this.postsInfo[k].postList.posts.hasOwnProperty(this.selectedPostId)) {
|
||||
return this.postsInfo[k].postList.posts[this.selectedPostId];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
getSelectedPostThread() {
|
||||
if (this.selectedPostId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let posts;
|
||||
let pendingPosts;
|
||||
for (const k in this.postsInfo) {
|
||||
if (this.postsInfo[k].postList.posts.hasOwnProperty(this.selectedPostId)) {
|
||||
posts = this.postsInfo[k].postList.posts;
|
||||
if (this.postsInfo[k].pendingPosts != null) {
|
||||
pendingPosts = this.postsInfo[k].pendingPosts.posts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const threadPosts = {};
|
||||
const rootId = this.selectedPostId;
|
||||
for (const k in posts) {
|
||||
if (posts[k].root_id === rootId) {
|
||||
threadPosts[k] = JSON.parse(JSON.stringify(posts[k]));
|
||||
}
|
||||
}
|
||||
|
||||
for (const k in pendingPosts) {
|
||||
if (pendingPosts[k].root_id === rootId) {
|
||||
threadPosts[k] = JSON.parse(JSON.stringify(pendingPosts[k]));
|
||||
}
|
||||
}
|
||||
|
||||
return threadPosts;
|
||||
}
|
||||
|
||||
emitSelectedPostChange(fromSearch) {
|
||||
@@ -565,7 +547,7 @@ PostStore.dispatchToken = AppDispatcher.register((payload) => {
|
||||
PostStore.emitChange();
|
||||
break;
|
||||
case ActionTypes.RECEIVED_POST_SELECTED:
|
||||
PostStore.storeSelectedPost(action.post_list);
|
||||
PostStore.storeSelectedPostId(action.postId);
|
||||
PostStore.emitSelectedPostChange(action.from_search);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -290,7 +290,7 @@ class UserStoreClass extends EventEmitter {
|
||||
}
|
||||
|
||||
var UserStore = new UserStoreClass();
|
||||
UserStore.setMaxListeners(0);
|
||||
UserStore.setMaxListeners(15);
|
||||
|
||||
UserStore.dispatchToken = AppDispatcher.register((payload) => {
|
||||
var action = payload.action;
|
||||
|
||||
@@ -1417,3 +1417,7 @@ export function languages() {
|
||||
export function isPostEphemeral(post) {
|
||||
return post.type === Constants.POST_TYPE_EPHEMERAL || post.state === Constants.POST_DELETED;
|
||||
}
|
||||
|
||||
export function getRootId(post) {
|
||||
return post.root_id === '' ? post.id : post.root_id;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user