Merge pull request #2229 from mattermost/plt-1770

PLT-1770 Refactor store listeners out of highly used components
Этот коммит содержится в:
Harrison Healey
2016-02-23 14:34:06 -05:00
родитель 11093ddb51 1f049af2b7
Коммит 0031c6fd1a
20 изменённых файлов: 253 добавлений и 328 удалений

Просмотреть файл

@@ -27,20 +27,24 @@ export default class CenterPanel extends React.Component {
this.onPreferenceChange = this.onPreferenceChange.bind(this); this.onPreferenceChange = this.onPreferenceChange.bind(this);
this.onChannelChange = this.onChannelChange.bind(this); this.onChannelChange = this.onChannelChange.bind(this);
this.onUserChange = this.onUserChange.bind(this);
const tutorialStep = PreferenceStore.getInt(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), 999); const tutorialStep = PreferenceStore.getInt(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), 999);
this.state = { this.state = {
showTutorialScreens: tutorialStep === TutorialSteps.INTRO_SCREENS, showTutorialScreens: tutorialStep === TutorialSteps.INTRO_SCREENS,
showPostFocus: ChannelStore.getPostMode() === ChannelStore.POST_MODE_FOCUS showPostFocus: ChannelStore.getPostMode() === ChannelStore.POST_MODE_FOCUS,
user: UserStore.getCurrentUser()
}; };
} }
componentDidMount() { componentDidMount() {
PreferenceStore.addChangeListener(this.onPreferenceChange); PreferenceStore.addChangeListener(this.onPreferenceChange);
ChannelStore.addChangeListener(this.onChannelChange); ChannelStore.addChangeListener(this.onChannelChange);
UserStore.addChangeListener(this.onUserChange);
} }
componentWillUnmount() { componentWillUnmount() {
PreferenceStore.removeChangeListener(this.onPreferenceChange); PreferenceStore.removeChangeListener(this.onPreferenceChange);
ChannelStore.removeChangeListener(this.onChannelChange); ChannelStore.removeChangeListener(this.onChannelChange);
UserStore.removeChangeListener(this.onUserChange);
} }
onPreferenceChange() { onPreferenceChange() {
const tutorialStep = PreferenceStore.getInt(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), 999); const tutorialStep = PreferenceStore.getInt(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), 999);
@@ -49,6 +53,9 @@ export default class CenterPanel extends React.Component {
onChannelChange() { onChannelChange() {
this.setState({showPostFocus: ChannelStore.getPostMode() === ChannelStore.POST_MODE_FOCUS}); this.setState({showPostFocus: ChannelStore.getPostMode() === ChannelStore.POST_MODE_FOCUS});
} }
onUserChange() {
this.setState({user: UserStore.getCurrentUser()});
}
render() { render() {
const channel = ChannelStore.getCurrent(); const channel = ChannelStore.getCurrent();
var handleClick = null; var handleClick = null;
@@ -108,7 +115,9 @@ export default class CenterPanel extends React.Component {
className='app__content' className='app__content'
> >
<div id='channel-header'> <div id='channel-header'>
<ChannelHeader/> <ChannelHeader
user={this.state.user}
/>
</div> </div>
{postsContainer} {postsContainer}
{createPost} {createPost}

Просмотреть файл

@@ -55,7 +55,6 @@ export default class ChannelHeader extends React.Component {
return { return {
channel: ChannelStore.getCurrent(), channel: ChannelStore.getCurrent(),
memberChannel: ChannelStore.getCurrentMember(), memberChannel: ChannelStore.getCurrentMember(),
memberTeam: UserStore.getCurrentUser(),
users: extraInfo.members, users: extraInfo.members,
userCount: extraInfo.member_count, userCount: extraInfo.member_count,
searchVisible: SearchStore.getSearchResults() !== null searchVisible: SearchStore.getSearchResults() !== null
@@ -65,14 +64,12 @@ export default class ChannelHeader extends React.Component {
ChannelStore.addChangeListener(this.onListenerChange); ChannelStore.addChangeListener(this.onListenerChange);
ChannelStore.addExtraInfoChangeListener(this.onListenerChange); ChannelStore.addExtraInfoChangeListener(this.onListenerChange);
SearchStore.addSearchChangeListener(this.onListenerChange); SearchStore.addSearchChangeListener(this.onListenerChange);
UserStore.addChangeListener(this.onListenerChange);
PreferenceStore.addChangeListener(this.onListenerChange); PreferenceStore.addChangeListener(this.onListenerChange);
} }
componentWillUnmount() { componentWillUnmount() {
ChannelStore.removeChangeListener(this.onListenerChange); ChannelStore.removeChangeListener(this.onListenerChange);
ChannelStore.removeExtraInfoChangeListener(this.onListenerChange); ChannelStore.removeExtraInfoChangeListener(this.onListenerChange);
SearchStore.removeSearchChangeListener(this.onListenerChange); SearchStore.removeSearchChangeListener(this.onListenerChange);
UserStore.removeChangeListener(this.onListenerChange);
PreferenceStore.removeChangeListener(this.onListenerChange); PreferenceStore.removeChangeListener(this.onListenerChange);
} }
onListenerChange() { onListenerChange() {
@@ -101,11 +98,11 @@ export default class ChannelHeader extends React.Component {
searchMentions(e) { searchMentions(e) {
e.preventDefault(); e.preventDefault();
const user = UserStore.getCurrentUser(); const user = this.props.user;
let terms = ''; let terms = '';
if (user.notify_props && user.notify_props.mention_keys) { if (user.notify_props && user.notify_props.mention_keys) {
const termKeys = UserStore.getCurrentMentionKeys(); const termKeys = UserStore.getMentionKeys(user.id);
if (user.notify_props.all === 'true' && termKeys.indexOf('@all') !== -1) { if (user.notify_props.all === 'true' && termKeys.indexOf('@all') !== -1) {
termKeys.splice(termKeys.indexOf('@all'), 1); termKeys.splice(termKeys.indexOf('@all'), 1);
@@ -166,8 +163,8 @@ export default class ChannelHeader extends React.Component {
</Popover> </Popover>
); );
let channelTitle = channel.display_name; let channelTitle = channel.display_name;
const currentId = UserStore.getCurrentId(); const currentId = this.props.user.id;
const isAdmin = Utils.isAdmin(this.state.memberChannel.roles) || Utils.isAdmin(this.state.memberTeam.roles); const isAdmin = Utils.isAdmin(this.state.memberChannel.roles) || Utils.isAdmin(this.props.user.roles);
const isDirect = (this.state.channel.type === 'D'); const isDirect = (this.state.channel.type === 'D');
if (isDirect) { if (isDirect) {
@@ -491,3 +488,7 @@ export default class ChannelHeader extends React.Component {
); );
} }
} }
ChannelHeader.propTypes = {
user: React.PropTypes.object.isRequired
};

Просмотреть файл

@@ -68,7 +68,7 @@ export default class DeletePostModal extends React.Component {
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_SELECTED, type: ActionTypes.RECEIVED_POST_SELECTED,
results: null postId: null
}); });
} else if (selectedPost.id === this.state.post.id && this.state.root_id) { } 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]) { 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({ AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_SELECTED, type: ActionTypes.RECEIVED_POST_SELECTED,
post_list: selectedList postId: selectedPost.root_id
}); });
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({

Просмотреть файл

@@ -93,7 +93,7 @@ export default class Navbar extends React.Component {
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_SELECTED, type: ActionTypes.RECEIVED_POST_SELECTED,
results: null postId: null
}); });
if (e.target.className !== 'navbar-toggle' && e.target.className !== 'icon-bar') { if (e.target.className !== 'navbar-toggle' && e.target.className !== 'icon-bar') {

Просмотреть файл

@@ -3,15 +3,18 @@
import PostHeader from './post_header.jsx'; import PostHeader from './post_header.jsx';
import PostBody from './post_body.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 UserStore from '../stores/user_store.jsx';
import PostStore from '../stores/post_store.jsx'; import PostStore from '../stores/post_store.jsx';
import ChannelStore from '../stores/channel_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'; 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 { export default class Post extends React.Component {
constructor(props) { constructor(props) {
@@ -26,13 +29,9 @@ export default class Post extends React.Component {
handleCommentClick(e) { handleCommentClick(e) {
e.preventDefault(); e.preventDefault();
var data = {};
data.order = [this.props.post.id];
data.posts = this.props.posts;
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_SELECTED, type: ActionTypes.RECEIVED_POST_SELECTED,
post_list: data postId: Utils.getRootId(this.props.post)
}); });
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
@@ -48,14 +47,14 @@ export default class Post extends React.Component {
e.preventDefault(); e.preventDefault();
var post = this.props.post; var post = this.props.post;
client.createPost(post, post.channel_id, Client.createPost(post, post.channel_id,
(data) => { (data) => {
AsyncClient.getPosts(); AsyncClient.getPosts();
var channel = ChannelStore.get(post.channel_id); var channel = ChannelStore.get(post.channel_id);
var member = ChannelStore.getMember(post.channel_id); var member = ChannelStore.getMember(post.channel_id);
member.msg_count = channel.total_msg_count; member.msg_count = channel.total_msg_count;
member.last_viewed_at = utils.getTimestamp(); member.last_viewed_at = Utils.getTimestamp();
ChannelStore.setChannelMember(member); ChannelStore.setChannelMember(member);
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
@@ -75,7 +74,7 @@ export default class Post extends React.Component {
this.forceUpdate(); this.forceUpdate();
} }
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
if (!utils.areObjectsEqual(nextProps.post, this.props.post)) { if (!Utils.areObjectsEqual(nextProps.post, this.props.post)) {
return true; return true;
} }
@@ -99,6 +98,10 @@ export default class Post extends React.Component {
return true; return true;
} }
if (nextProps.hasProfiles !== this.props.hasProfiles) {
return true;
}
return false; return false;
} }
getCommentCount(props) { getCommentCount(props) {
@@ -125,6 +128,7 @@ export default class Post extends React.Component {
const post = this.props.post; const post = this.props.post;
const parentPost = this.props.parentPost; const parentPost = this.props.parentPost;
const posts = this.props.posts; const posts = this.props.posts;
const user = this.props.user || {};
if (!post.props) { if (!post.props) {
post.props = {}; post.props = {};
@@ -152,15 +156,13 @@ export default class Post extends React.Component {
} }
let currentUserCss = ''; 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'; currentUserCss = 'current--user';
} }
const userProfile = UserStore.getProfile(post.user_id); let timestamp = user.update_at;
if (timestamp == null) {
let timestamp = UserStore.getCurrentUser().update_at; timestamp = UserStore.getCurrentUser().update_at;
if (userProfile) {
timestamp = userProfile.update_at;
} }
let sameUserClass = ''; let sameUserClass = '';
@@ -174,18 +176,18 @@ export default class Post extends React.Component {
} }
let systemMessageClass = ''; let systemMessageClass = '';
if (utils.isSystemMessage(post)) { if (Utils.isSystemMessage(post)) {
systemMessageClass = 'post--system'; systemMessageClass = 'post--system';
} }
let profilePic = null; let profilePic = null;
if (!this.props.hideProfilePic) { 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 && post.props.from_webhook && global.window.mm_config.EnablePostIconOverride === 'true') {
if (post.props.override_icon_url) { if (post.props.override_icon_url) {
src = 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; src = Constants.SYSTEM_MESSAGE_PROFILE_IMAGE;
} }
@@ -215,6 +217,7 @@ export default class Post extends React.Component {
handleCommentClick={this.handleCommentClick} handleCommentClick={this.handleCommentClick}
isLastComment={this.props.isLastComment} isLastComment={this.props.isLastComment}
sameUser={this.props.sameUser} sameUser={this.props.sameUser}
user={this.props.user}
/> />
<PostBody <PostBody
post={post} post={post}
@@ -223,6 +226,7 @@ export default class Post extends React.Component {
posts={posts} posts={posts}
handleCommentClick={this.handleCommentClick} handleCommentClick={this.handleCommentClick}
retryPost={this.retryPost} retryPost={this.retryPost}
hasProfiles={this.props.hasProfiles}
/> />
</div> </div>
</div> </div>
@@ -233,13 +237,15 @@ export default class Post extends React.Component {
} }
Post.propTypes = { Post.propTypes = {
post: React.PropTypes.object, post: React.PropTypes.object.isRequired,
posts: React.PropTypes.object, posts: React.PropTypes.object,
parentPost: React.PropTypes.object, parentPost: React.PropTypes.object,
user: React.PropTypes.object,
sameUser: React.PropTypes.bool, sameUser: React.PropTypes.bool,
sameRoot: React.PropTypes.bool, sameRoot: React.PropTypes.bool,
hideProfilePic: React.PropTypes.bool, hideProfilePic: React.PropTypes.bool,
isLastComment: React.PropTypes.bool, isLastComment: React.PropTypes.bool,
shouldHighlight: React.PropTypes.bool, shouldHighlight: React.PropTypes.bool,
displayNameType: React.PropTypes.string displayNameType: React.PropTypes.string,
hasProfiles: React.PropTypes.bool
}; };

Просмотреть файл

@@ -33,19 +33,16 @@ class PostBody extends React.Component {
this.isImgLoading = false; this.isImgLoading = false;
this.handleUserChange = this.handleUserChange.bind(this);
this.parseEmojis = this.parseEmojis.bind(this); this.parseEmojis = this.parseEmojis.bind(this);
this.createEmbed = this.createEmbed.bind(this); this.createEmbed = this.createEmbed.bind(this);
this.createImageEmbed = this.createImageEmbed.bind(this); this.createImageEmbed = this.createImageEmbed.bind(this);
this.loadImg = this.loadImg.bind(this); this.loadImg = this.loadImg.bind(this);
const linkData = Utils.extractLinks(this.props.post.message); const linkData = Utils.extractLinks(this.props.post.message);
const profiles = UserStore.getProfiles();
this.state = { this.state = {
links: linkData.links, links: linkData.links,
post: this.props.post, post: this.props.post
hasUserProfiles: profiles && Object.keys(profiles).length > 1
}; };
} }
@@ -80,26 +77,12 @@ class PostBody extends React.Component {
componentDidMount() { componentDidMount() {
this.parseEmojis(); this.parseEmojis();
UserStore.addChangeListener(this.handleUserChange);
} }
componentDidUpdate() { componentDidUpdate() {
this.parseEmojis(); this.parseEmojis();
} }
componentWillUnmount() {
UserStore.removeChangeListener(this.handleUserChange);
}
handleUserChange() {
if (!this.state.hasProfiles) {
const profiles = UserStore.getProfiles();
this.setState({hasProfiles: profiles && Object.keys(profiles).length > 1});
}
}
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
const linkData = Utils.extractLinks(nextProps.post.message); const linkData = Utils.extractLinks(nextProps.post.message);
if (this.props.post.filenames.length === 0 && this.state.links && this.state.links.length > 0) { if (this.props.post.filenames.length === 0 && this.state.links && this.state.links.length > 0) {
@@ -357,7 +340,8 @@ PostBody.propTypes = {
post: React.PropTypes.object.isRequired, post: React.PropTypes.object.isRequired,
parentPost: React.PropTypes.object, parentPost: React.PropTypes.object,
retryPost: React.PropTypes.func.isRequired, retryPost: React.PropTypes.func.isRequired,
handleCommentClick: React.PropTypes.func.isRequired handleCommentClick: React.PropTypes.func.isRequired,
hasProfiles: React.PropTypes.bool
}; };
export default injectIntl(PostBody); export default injectIntl(PostBody);

Просмотреть файл

@@ -38,7 +38,7 @@ export default class PostDeletedModal extends React.Component {
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_SELECTED, type: ActionTypes.RECEIVED_POST_SELECTED,
results: null postId: null
}); });
this.props.onHide(); this.props.onHide();

Просмотреть файл

@@ -13,16 +13,17 @@ export default class PostHeader extends React.Component {
this.state = {}; this.state = {};
} }
render() { 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; let botIndicator;
if (post.props && post.props.from_webhook) { if (post.props && post.props.from_webhook) {
if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') { if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') {
userProfile = ( userProfile = (
<UserProfile <UserProfile
userId={post.user_id} user={user}
overwriteName={post.props.override_username} overwriteName={post.props.override_username}
disablePopover={true} disablePopover={true}
/> />
@@ -33,7 +34,7 @@ export default class PostHeader extends React.Component {
} else if (Utils.isSystemMessage(post)) { } else if (Utils.isSystemMessage(post)) {
userProfile = ( userProfile = (
<UserProfile <UserProfile
userId={''} user={{}}
overwriteName={Constants.SYSTEM_MESSAGE_PROFILE_NAME} overwriteName={Constants.SYSTEM_MESSAGE_PROFILE_NAME}
overwriteImage={Constants.SYSTEM_MESSAGE_PROFILE_IMAGE} overwriteImage={Constants.SYSTEM_MESSAGE_PROFILE_IMAGE}
disablePopover={true} disablePopover={true}
@@ -68,6 +69,7 @@ PostHeader.defaultProps = {
}; };
PostHeader.propTypes = { PostHeader.propTypes = {
post: React.PropTypes.object, post: React.PropTypes.object,
user: React.PropTypes.object,
commentCount: React.PropTypes.number, commentCount: React.PropTypes.number,
isLastComment: React.PropTypes.bool, isLastComment: React.PropTypes.bool,
handleCommentClick: React.PropTypes.func, handleCommentClick: React.PropTypes.func,

Просмотреть файл

@@ -145,6 +145,7 @@ export default class PostsView extends React.Component {
const postCtls = []; const postCtls = [];
let previousPostDay = new Date(0); let previousPostDay = new Date(0);
const userId = UserStore.getCurrentId(); const userId = UserStore.getCurrentId();
const profiles = this.props.profiles;
let renderedLastViewed = false; let renderedLastViewed = false;
@@ -228,6 +229,13 @@ export default class PostsView extends React.Component {
const shouldHighlight = this.props.postsToHighlight && this.props.postsToHighlight.hasOwnProperty(post.id); 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 = ( const postCtl = (
<Post <Post
key={keyPrefix + 'postKey'} key={keyPrefix + 'postKey'}
@@ -242,6 +250,8 @@ export default class PostsView extends React.Component {
shouldHighlight={shouldHighlight} shouldHighlight={shouldHighlight}
onClick={() => EventHelpers.emitPostFocusEvent(post.id)} //eslint-disable-line no-loop-func onClick={() => EventHelpers.emitPostFocusEvent(post.id)} //eslint-disable-line no-loop-func
displayNameType={this.state.displayNameType} displayNameType={this.state.displayNameType}
hasProfiles={profiles && Object.keys(profiles).length > 1}
user={profile}
/> />
); );
@@ -413,6 +423,9 @@ export default class PostsView extends React.Component {
if (this.state.isScrolling !== nextState.isScrolling) { if (this.state.isScrolling !== nextState.isScrolling) {
return true; return true;
} }
if (!Utils.areObjectsEqual(this.props.profiles, nextProps.profiles)) {
return true;
}
return false; return false;
} }
@@ -513,6 +526,7 @@ PostsView.defaultProps = {
PostsView.propTypes = { PostsView.propTypes = {
isActive: React.PropTypes.bool, isActive: React.PropTypes.bool,
postList: React.PropTypes.object, postList: React.PropTypes.object,
profiles: React.PropTypes.object,
scrollPostId: React.PropTypes.string, scrollPostId: React.PropTypes.string,
scrollType: React.PropTypes.number, scrollType: React.PropTypes.number,
postViewScrolled: React.PropTypes.func.isRequired, postViewScrolled: React.PropTypes.func.isRequired,

Просмотреть файл

@@ -6,6 +6,7 @@ import LoadingScreen from './loading_screen.jsx';
import ChannelStore from '../stores/channel_store.jsx'; import ChannelStore from '../stores/channel_store.jsx';
import PostStore from '../stores/post_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 Utils from '../utils/utils.jsx';
import * as EventHelpers from '../dispatcher/event_helpers.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.handlePostsViewScroll = this.handlePostsViewScroll.bind(this);
this.loadMorePostsTop = this.loadMorePostsTop.bind(this); this.loadMorePostsTop = this.loadMorePostsTop.bind(this);
this.handlePostsViewJumpRequest = this.handlePostsViewJumpRequest.bind(this); this.handlePostsViewJumpRequest = this.handlePostsViewJumpRequest.bind(this);
this.onUserChange = this.onUserChange.bind(this);
const currentChannelId = ChannelStore.getCurrentId(); const currentChannelId = ChannelStore.getCurrentId();
const state = { const state = {
scrollType: PostsView.SCROLL_TYPE_BOTTOM, scrollType: PostsView.SCROLL_TYPE_BOTTOM,
scrollPost: null scrollPost: null,
profiles: JSON.parse(JSON.stringify(UserStore.getProfiles()))
}; };
if (currentChannelId) { if (currentChannelId) {
Object.assign(state, { Object.assign(state, {
@@ -54,12 +57,14 @@ export default class PostsViewContainer extends React.Component {
ChannelStore.addLeaveListener(this.onChannelLeave); ChannelStore.addLeaveListener(this.onChannelLeave);
PostStore.addChangeListener(this.onPostsChange); PostStore.addChangeListener(this.onPostsChange);
PostStore.addPostsViewJumpListener(this.handlePostsViewJumpRequest); PostStore.addPostsViewJumpListener(this.handlePostsViewJumpRequest);
UserStore.addChangeListener(this.onUserChange);
} }
componentWillUnmount() { componentWillUnmount() {
ChannelStore.removeChangeListener(this.onChannelChange); ChannelStore.removeChangeListener(this.onChannelChange);
ChannelStore.removeLeaveListener(this.onChannelLeave); ChannelStore.removeLeaveListener(this.onChannelLeave);
PostStore.removeChangeListener(this.onPostsChange); PostStore.removeChangeListener(this.onPostsChange);
PostStore.removePostsViewJumpListener(this.handlePostsViewJumpRequest); PostStore.removePostsViewJumpListener(this.handlePostsViewJumpRequest);
UserStore.removeChangeListener(this.onUserChange);
} }
handlePostsViewJumpRequest(type, post) { handlePostsViewJumpRequest(type, post) {
switch (type) { switch (type) {
@@ -135,6 +140,9 @@ export default class PostsViewContainer extends React.Component {
atTop[this.state.currentChannelIndex] = PostStore.getVisibilityAtTop(currentChannelId); atTop[this.state.currentChannelIndex] = PostStore.getVisibilityAtTop(currentChannelId);
this.setState({postLists, atTop}); this.setState({postLists, atTop});
} }
onUserChange() {
this.setState({profiles: JSON.parse(JSON.stringify(UserStore.getProfiles()))});
}
getChannelPosts(id) { getChannelPosts(id) {
return PostStore.getVisiblePosts(id); return PostStore.getVisiblePosts(id);
} }
@@ -180,6 +188,7 @@ export default class PostsViewContainer extends React.Component {
showMoreMessagesBottom={false} showMoreMessagesBottom={false}
introText={channel ? createChannelIntroMessage(channel) : null} introText={channel ? createChannelIntroMessage(channel) : null}
messageSeparatorTime={this.state.currentLastViewed} messageSeparatorTime={this.state.currentLastViewed}
profiles={this.state.profiles}
/> />
); );
if (!postLists[i] && isActive) { if (!postLists[i] && isActive) {

Просмотреть файл

@@ -194,8 +194,16 @@ class RhsComment extends React.Component {
var timestamp = UserStore.getCurrentUser().update_at; var timestamp = UserStore.getCurrentUser().update_at;
var loading; let loading;
var postClass = ''; let postClass = '';
let message = (
<div
ref='message_holder'
onClick={TextFormatting.handleClick}
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(post.message)}}
/>
);
if (post.state === Constants.POST_FAILED) { if (post.state === Constants.POST_FAILED) {
postClass += ' post-fail'; postClass += ' post-fail';
loading = ( loading = (
@@ -218,6 +226,13 @@ class RhsComment extends React.Component {
src='/static/images/load.gif' 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(); var dropdown = this.createDropdown();
@@ -246,7 +261,7 @@ class RhsComment extends React.Component {
<div> <div>
<ul className='post__header'> <ul className='post__header'>
<li className='col__name'> <li className='col__name'>
<strong><UserProfile userId={post.user_id}/></strong> <strong><UserProfile user={this.props.user}/></strong>
</li> </li>
<li className='col'> <li className='col'>
<time className='post__time'> <time className='post__time'>
@@ -268,11 +283,7 @@ class RhsComment extends React.Component {
<div className='post__body'> <div className='post__body'>
<div className={postClass}> <div className={postClass}>
{loading} {loading}
<div {message}
ref='message_holder'
onClick={TextFormatting.handleClick}
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(post.message)}}
/>
</div> </div>
{fileAttachment} {fileAttachment}
</div> </div>
@@ -288,7 +299,8 @@ RhsComment.defaultProps = {
}; };
RhsComment.propTypes = { RhsComment.propTypes = {
intl: intlShape.isRequired, intl: intlShape.isRequired,
post: React.PropTypes.object post: React.PropTypes.object,
user: React.PropTypes.object
}; };
export default injectIntl(RhsComment); export default injectIntl(RhsComment);

Просмотреть файл

@@ -27,7 +27,7 @@ export default class RhsHeaderPost extends React.Component {
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_SELECTED, type: ActionTypes.RECEIVED_POST_SELECTED,
results: null postId: null
}); });
} }
handleBack(e) { handleBack(e) {
@@ -42,7 +42,7 @@ export default class RhsHeaderPost extends React.Component {
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_SELECTED, type: ActionTypes.RECEIVED_POST_SELECTED,
results: null postId: null
}); });
} }
render() { render() {

Просмотреть файл

@@ -50,10 +50,10 @@ export default class RhsRootPost extends React.Component {
this.parseEmojis(); this.parseEmojis();
} }
render() { render() {
var post = this.props.post; const post = this.props.post;
var currentUser = UserStore.getCurrentUser(); const user = this.props.user;
var isOwner = currentUser.id === post.user_id; var isOwner = user.id === post.user_id;
var isAdmin = Utils.isAdmin(currentUser.roles); var isAdmin = Utils.isAdmin(user.roles);
var timestamp = UserStore.getProfile(post.user_id).update_at; var timestamp = UserStore.getProfile(post.user_id).update_at;
var channel = ChannelStore.get(post.channel_id); var channel = ChannelStore.get(post.channel_id);
@@ -62,9 +62,9 @@ export default class RhsRootPost extends React.Component {
type = 'Comment'; type = 'Comment';
} }
var currentUserCss = ''; var userCss = '';
if (UserStore.getCurrentId() === post.user_id) { if (UserStore.getCurrentId() === post.user_id) {
currentUserCss = 'current--user'; userCss = 'current--user';
} }
var systemMessageClass = ''; 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; let botIndicator;
if (post.props && post.props.from_webhook) { if (post.props && post.props.from_webhook) {
if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') { if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') {
userProfile = ( userProfile = (
<UserProfile <UserProfile
userId={post.user_id} user={user}
overwriteName={post.props.override_username} overwriteName={post.props.override_username}
disablePopover={true} disablePopover={true}
/> />
@@ -203,7 +203,7 @@ export default class RhsRootPost extends React.Component {
} else if (Utils.isSystemMessage(post)) { } else if (Utils.isSystemMessage(post)) {
userProfile = ( userProfile = (
<UserProfile <UserProfile
userId={''} user={{}}
overwriteName={Constants.SYSTEM_MESSAGE_PROFILE_NAME} overwriteName={Constants.SYSTEM_MESSAGE_PROFILE_NAME}
overwriteImage={Constants.SYSTEM_MESSAGE_PROFILE_IMAGE} overwriteImage={Constants.SYSTEM_MESSAGE_PROFILE_IMAGE}
disablePopover={true} disablePopover={true}
@@ -230,7 +230,7 @@ export default class RhsRootPost extends React.Component {
); );
return ( 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-right-channel__name'>{channelName}</div>
<div className='post__content'> <div className='post__content'>
<div className='post__img'> <div className='post__img'>
@@ -278,10 +278,10 @@ export default class RhsRootPost extends React.Component {
} }
RhsRootPost.defaultProps = { RhsRootPost.defaultProps = {
post: null,
commentCount: 0 commentCount: 0
}; };
RhsRootPost.propTypes = { RhsRootPost.propTypes = {
post: React.PropTypes.object, post: React.PropTypes.object.isRequired,
user: React.PropTypes.object.isRequired,
commentCount: React.PropTypes.number commentCount: React.PropTypes.number
}; };

Просмотреть файл

@@ -19,39 +19,25 @@ export default class RhsThread extends React.Component {
this.mounted = false; this.mounted = false;
this.onChange = this.onChange.bind(this); this.onPostChange = this.onPostChange.bind(this);
this.onChangeAll = this.onChangeAll.bind(this); this.onUserChange = this.onUserChange.bind(this);
this.forceUpdateInfo = this.forceUpdateInfo.bind(this); this.forceUpdateInfo = this.forceUpdateInfo.bind(this);
this.handleResize = this.handleResize.bind(this); this.handleResize = this.handleResize.bind(this);
const state = this.getStateFromStores(); const state = {};
state.windowWidth = Utils.windowWidth(); state.windowWidth = Utils.windowWidth();
state.windowHeight = Utils.windowHeight(); state.windowHeight = Utils.windowHeight();
state.selected = PostStore.getSelectedPost();
state.posts = PostStore.getSelectedPostThread();
state.profiles = JSON.parse(JSON.stringify(UserStore.getProfiles()));
this.state = state; 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() { componentDidMount() {
PostStore.addSelectedPostChangeListener(this.onChange); PostStore.addSelectedPostChangeListener(this.onPostChange);
PostStore.addChangeListener(this.onChangeAll); PostStore.addChangeListener(this.onPostChange);
PreferenceStore.addChangeListener(this.forceUpdateInfo); PreferenceStore.addChangeListener(this.forceUpdateInfo);
UserStore.addChangeListener(this.onUserChange);
this.resize(); this.resize();
window.addEventListener('resize', this.handleResize); window.addEventListener('resize', this.handleResize);
@@ -65,14 +51,30 @@ export default class RhsThread extends React.Component {
this.resize(); this.resize();
} }
componentWillUnmount() { componentWillUnmount() {
PostStore.removeSelectedPostChangeListener(this.onChange); PostStore.removeSelectedPostChangeListener(this.onPostChange);
PostStore.removeChangeListener(this.onChangeAll); PostStore.removeChangeListener(this.onPostChange);
PreferenceStore.removeChangeListener(this.forceUpdateInfo); PreferenceStore.removeChangeListener(this.forceUpdateInfo);
UserStore.removeChangeListener(this.onUserChange);
window.removeEventListener('resize', this.handleResize); window.removeEventListener('resize', this.handleResize);
this.mounted = false; 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() { forceUpdateInfo() {
if (this.state.postList) { if (this.state.postList) {
for (var postId in this.state.postList.posts) { for (var postId in this.state.postList.posts) {
@@ -88,49 +90,14 @@ export default class RhsThread extends React.Component {
windowHeight: Utils.windowHeight() windowHeight: Utils.windowHeight()
}); });
} }
onChange() { onPostChange() {
var newState = this.getStateFromStores(); const selected = PostStore.getSelectedPost();
if (this.mounted && !Utils.areObjectsEqual(newState, this.state)) { const posts = PostStore.getSelectedPostThread();
this.setState(newState); this.setState({posts, selected});
}
} }
onChangeAll() { onUserChange() {
// if something was changed in the channel like adding a const profiles = JSON.parse(JSON.stringify(UserStore.getProfiles()));
// comment or post then lets refresh the sidebar list this.setState({profiles});
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);
}
} }
resize() { resize() {
$('.post-right__scroll').scrollTop(100000); $('.post-right__scroll').scrollTop(100000);
@@ -140,29 +107,21 @@ export default class RhsThread extends React.Component {
} }
} }
render() { 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 ( return (
<div></div> <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 = []; var postsArray = [];
for (var postId in postList.posts) { for (const id in posts) {
if (postList.posts.hasOwnProperty(postId)) { if (posts.hasOwnProperty(id)) {
var cpost = postList.posts[postId]; const cpost = posts[id];
if (cpost.root_id === rootPost.id) { if (cpost.root_id === selected.id) {
postsArray.push(cpost); postsArray.push(cpost);
} }
} }
@@ -199,6 +158,13 @@ export default class RhsThread extends React.Component {
searchForm = <SearchBox/>; searchForm = <SearchBox/>;
} }
let profile;
if (UserStore.getCurrentId() === selected.user_id) {
profile = UserStore.getCurrentUser();
} else {
profile = this.state.profiles[selected.user_id];
}
return ( return (
<div className='post-right__container'> <div className='post-right__container'>
<FileUploadOverlay overlayType='right'/> <FileUploadOverlay overlayType='right'/>
@@ -210,26 +176,33 @@ export default class RhsThread extends React.Component {
/> />
<div className='post-right__scroll'> <div className='post-right__scroll'>
<RootPost <RootPost
ref={rootPost.id} ref={selected.id}
post={rootPost} post={selected}
commentCount={postsArray.length} commentCount={postsArray.length}
user={profile}
/> />
<div className='post-right-comments-container'> <div className='post-right-comments-container'>
{postsArray.map(function mapPosts(comPost) { {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 ( return (
<Comment <Comment
ref={comPost.id} ref={comPost.id}
key={comPost.id + 'commentKey'} key={comPost.id + 'commentKey'}
post={comPost} post={comPost}
selected={(comPost.id === selectedPost.id)} user={p}
/> />
); );
})} })}
</div> </div>
<div className='post-create__container'> <div className='post-create__container'>
<CreateComment <CreateComment
channelId={rootPost.channel_id} channelId={selected.channel_id}
rootId={rootPost.id} rootId={selected.id}
/> />
</div> </div>
</div> </div>

Просмотреть файл

@@ -87,7 +87,7 @@ class SearchBar extends React.Component {
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_SELECTED, type: ActionTypes.RECEIVED_POST_SELECTED,
results: null postId: null
}); });
} }
handleUserInput(text) { handleUserInput(text) {

Просмотреть файл

@@ -32,7 +32,7 @@ export default class SearchResultsHeader extends React.Component {
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_SELECTED, type: ActionTypes.RECEIVED_POST_SELECTED,
results: null postId: null
}); });
} }

Просмотреть файл

@@ -2,7 +2,6 @@
// See License.txt for license information. // See License.txt for license information.
import * as Utils from '../utils/utils.jsx'; import * as Utils from '../utils/utils.jsx';
import UserStore from '../stores/user_store.jsx';
import {FormattedMessage} from 'mm-intl'; import {FormattedMessage} from 'mm-intl';
@@ -19,45 +18,15 @@ function nextId() {
export default class UserProfile extends React.Component { export default class UserProfile extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.uniqueId = nextId(); 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() { componentDidMount() {
UserStore.addChangeListener(this.onChange);
if (!this.props.disablePopover) { if (!this.props.disablePopover) {
$('body').tooltip({selector: '[data-toggle=tooltip]', trigger: 'hover click'}); $('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() { render() {
var name = Utils.displayUsername(this.state.profile.id); var name = Utils.displayUsername(this.props.user.id);
if (this.props.overwriteName) { if (this.props.overwriteName) {
name = this.props.overwriteName; name = this.props.overwriteName;
} else if (!name) { } else if (!name) {
@@ -68,7 +37,7 @@ export default class UserProfile extends React.Component {
return <div>{name}</div>; 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) { if (this.props.overwriteImage) {
profileImg = this.props.overwriteImage; profileImg = this.props.overwriteImage;
} }
@@ -100,14 +69,14 @@ export default class UserProfile extends React.Component {
dataContent.push( dataContent.push(
<div <div
data-toggle='tooltip' data-toggle='tooltip'
title={this.state.profile.email} title={this.props.user.email}
key='user-popover-email' key='user-popover-email'
> >
<a <a
href={'mailto:' + this.state.profile.email} href={'mailto:' + this.props.user.email}
className='text-nowrap text-lowercase user-popover__email' className='text-nowrap text-lowercase user-popover__email'
> >
{this.state.profile.email} {this.props.user.email}
</a> </a>
</div> </div>
); );
@@ -139,13 +108,13 @@ export default class UserProfile extends React.Component {
} }
UserProfile.defaultProps = { UserProfile.defaultProps = {
userId: '', user: {},
overwriteName: '', overwriteName: '',
overwriteImage: '', overwriteImage: '',
disablePopover: false disablePopover: false
}; };
UserProfile.propTypes = { UserProfile.propTypes = {
userId: React.PropTypes.string, user: React.PropTypes.object.isRequired,
overwriteName: React.PropTypes.string, overwriteName: React.PropTypes.string,
overwriteImage: React.PropTypes.string, overwriteImage: React.PropTypes.string,
disablePopover: React.PropTypes.bool disablePopover: React.PropTypes.bool

Просмотреть файл

@@ -20,72 +20,7 @@ const SELECTED_POST_CHANGE_EVENT = 'selected_post_change';
class PostStoreClass extends EventEmitter { class PostStoreClass extends EventEmitter {
constructor() { constructor() {
super(); super();
this.selectedPostId = null;
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.postsInfo = {}; this.postsInfo = {};
this.currentFocusedPostId = null; this.currentFocusedPostId = null;
} }
@@ -421,12 +356,59 @@ class PostStoreClass extends EventEmitter {
this.emitChange(); this.emitChange();
} }
storeSelectedPost(postList) { storeSelectedPostId(postId) {
this.selectedPost = postList; this.selectedPostId = postId;
}
getSelectedPostId() {
return this.selectedPostId;
} }
getSelectedPost() { 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) { emitSelectedPostChange(fromSearch) {
@@ -565,7 +547,7 @@ PostStore.dispatchToken = AppDispatcher.register((payload) => {
PostStore.emitChange(); PostStore.emitChange();
break; break;
case ActionTypes.RECEIVED_POST_SELECTED: case ActionTypes.RECEIVED_POST_SELECTED:
PostStore.storeSelectedPost(action.post_list); PostStore.storeSelectedPostId(action.postId);
PostStore.emitSelectedPostChange(action.from_search); PostStore.emitSelectedPostChange(action.from_search);
break; break;
default: default:

Просмотреть файл

@@ -17,50 +17,6 @@ const CHANGE_EVENT_STATUSES = 'change_statuses';
class UserStoreClass extends EventEmitter { class UserStoreClass extends EventEmitter {
constructor() { constructor() {
super(); super();
this.emitChange = this.emitChange.bind(this);
this.addChangeListener = this.addChangeListener.bind(this);
this.removeChangeListener = this.removeChangeListener.bind(this);
this.emitSessionsChange = this.emitSessionsChange.bind(this);
this.addSessionsChangeListener = this.addSessionsChangeListener.bind(this);
this.removeSessionsChangeListener = this.removeSessionsChangeListener.bind(this);
this.emitAuditsChange = this.emitAuditsChange.bind(this);
this.addAuditsChangeListener = this.addAuditsChangeListener.bind(this);
this.removeAuditsChangeListener = this.removeAuditsChangeListener.bind(this);
this.emitTeamsChange = this.emitTeamsChange.bind(this);
this.addTeamsChangeListener = this.addTeamsChangeListener.bind(this);
this.removeTeamsChangeListener = this.removeTeamsChangeListener.bind(this);
this.emitStatusesChange = this.emitStatusesChange.bind(this);
this.addStatusesChangeListener = this.addStatusesChangeListener.bind(this);
this.removeStatusesChangeListener = this.removeStatusesChangeListener.bind(this);
this.getCurrentId = this.getCurrentId.bind(this);
this.getCurrentUser = this.getCurrentUser.bind(this);
this.setCurrentUser = this.setCurrentUser.bind(this);
this.getLastEmail = this.getLastEmail.bind(this);
this.setLastEmail = this.setLastEmail.bind(this);
this.getLastUsername = this.getLastUsername.bind(this);
this.setLastUsername = this.setLastUsername.bind(this);
this.hasProfile = this.hasProfile.bind(this);
this.getProfile = this.getProfile.bind(this);
this.getProfileByUsername = this.getProfileByUsername.bind(this);
this.getProfilesUsernameMap = this.getProfilesUsernameMap.bind(this);
this.getProfiles = this.getProfiles.bind(this);
this.getActiveOnlyProfiles = this.getActiveOnlyProfiles.bind(this);
this.getActiveOnlyProfileList = this.getActiveOnlyProfileList.bind(this);
this.saveProfile = this.saveProfile.bind(this);
this.setSessions = this.setSessions.bind(this);
this.getSessions = this.getSessions.bind(this);
this.setAudits = this.setAudits.bind(this);
this.getAudits = this.getAudits.bind(this);
this.setTeams = this.setTeams.bind(this);
this.getTeams = this.getTeams.bind(this);
this.getCurrentMentionKeys = this.getCurrentMentionKeys.bind(this);
this.setStatuses = this.setStatuses.bind(this);
this.pSetStatuses = this.pSetStatuses.bind(this);
this.setStatus = this.setStatus.bind(this);
this.getStatuses = this.getStatuses.bind(this);
this.getStatus = this.getStatus.bind(this);
this.profileCache = null; this.profileCache = null;
} }
@@ -277,7 +233,11 @@ class UserStoreClass extends EventEmitter {
} }
getCurrentMentionKeys() { getCurrentMentionKeys() {
var user = this.getCurrentUser(); return this.getMentionKeys(this.getCurrentId());
}
getMentionKeys(id) {
var user = this.getProfile(id);
var keys = []; var keys = [];
@@ -330,7 +290,7 @@ class UserStoreClass extends EventEmitter {
} }
var UserStore = new UserStoreClass(); var UserStore = new UserStoreClass();
UserStore.setMaxListeners(0); UserStore.setMaxListeners(15);
UserStore.dispatchToken = AppDispatcher.register((payload) => { UserStore.dispatchToken = AppDispatcher.register((payload) => {
var action = payload.action; var action = payload.action;

Просмотреть файл

@@ -1417,3 +1417,7 @@ export function languages() {
export function isPostEphemeral(post) { export function isPostEphemeral(post) {
return post.type === Constants.POST_TYPE_EPHEMERAL || post.state === Constants.POST_DELETED; 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;
}