From ff741740eebceb43b1d69b13d97ae7eed2aa32d1 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Mon, 13 Feb 2017 09:27:28 -0500 Subject: Increase performance when receiving messages (#5375) --- webapp/actions/global_actions.jsx | 7 ++-- webapp/actions/post_actions.jsx | 20 ------------ webapp/actions/team_actions.jsx | 5 +++ webapp/actions/websocket_actions.jsx | 13 -------- webapp/components/needs_team.jsx | 9 ++++++ webapp/components/post_view/post_view_cache.jsx | 2 +- .../team_sidebar/components/team_button.jsx | 10 +++++- webapp/root.jsx | 3 ++ webapp/stores/channel_store.jsx | 37 ++++++++++++++++++++++ webapp/stores/team_store.jsx | 25 +++++++++++++++ 10 files changed, 93 insertions(+), 38 deletions(-) (limited to 'webapp') diff --git a/webapp/actions/global_actions.jsx b/webapp/actions/global_actions.jsx index 2d1638060..5def48858 100644 --- a/webapp/actions/global_actions.jsx +++ b/webapp/actions/global_actions.jsx @@ -47,16 +47,17 @@ export function emitChannelClickEvent(channel) { function switchToChannel(chan) { const channelMember = ChannelStore.getMyMember(chan.id); const getMyChannelMembersPromise = AsyncClient.getChannelMember(chan.id, UserStore.getCurrentId()); + const oldChannelId = ChannelStore.getCurrentId(); getMyChannelMembersPromise.then(() => { AsyncClient.getChannelStats(chan.id, true); - AsyncClient.viewChannel(chan.id, ChannelStore.getCurrentId()); + AsyncClient.viewChannel(chan.id, oldChannelId); loadPosts(chan.id); trackPage(); }); // Mark previous and next channel as read - ChannelStore.resetCounts(ChannelStore.getCurrentId()); + ChannelStore.resetCounts(oldChannelId); ChannelStore.resetCounts(chan.id); BrowserStore.setGlobalItem(chan.team_id, chan.id); @@ -68,7 +69,7 @@ export function emitChannelClickEvent(channel) { team_id: chan.team_id, total_msg_count: chan.total_msg_count, channelMember, - prev: ChannelStore.getCurrentId() + prev: oldChannelId }); } diff --git a/webapp/actions/post_actions.jsx b/webapp/actions/post_actions.jsx index 61f193b66..633a6f66a 100644 --- a/webapp/actions/post_actions.jsx +++ b/webapp/actions/post_actions.jsx @@ -5,7 +5,6 @@ import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; import ChannelStore from 'stores/channel_store.jsx'; import PostStore from 'stores/post_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; import UserStore from 'stores/user_store.jsx'; import {loadStatusesForChannel} from 'actions/status_actions.jsx'; @@ -18,30 +17,11 @@ const ActionTypes = Constants.ActionTypes; const Preferences = Constants.Preferences; export function handleNewPost(post, msg) { - const teamId = TeamStore.getCurrentId(); - - if (ChannelStore.getCurrentId() === post.channel_id) { - if (window.isActive) { - AsyncClient.viewChannel(); - } else { - AsyncClient.getChannel(post.channel_id); - } - } else if (msg && (teamId === msg.data.team_id || msg.data.channel_type === Constants.DM_CHANNEL)) { - if (Client.teamId) { - AsyncClient.getChannel(post.channel_id); - } - } - let websocketMessageProps = null; if (msg) { websocketMessageProps = msg.data; } - const myTeams = TeamStore.getMyTeamMembers(); - if (msg.data.team_id !== teamId && myTeams.filter((m) => m.team_id === msg.data.team_id).length) { - AsyncClient.getMyTeamsUnread(teamId); - } - if (post.root_id && PostStore.getPost(post.channel_id, post.root_id) == null) { Client.getPost( post.channel_id, diff --git a/webapp/actions/team_actions.jsx b/webapp/actions/team_actions.jsx index e23fe1e5d..478d3dffc 100644 --- a/webapp/actions/team_actions.jsx +++ b/webapp/actions/team_actions.jsx @@ -145,3 +145,8 @@ export function inviteMembers(data, success, error) { } ); } + +export function switchTeams(url) { + AsyncClient.viewChannel(); + browserHistory.push(url); +} diff --git a/webapp/actions/websocket_actions.jsx b/webapp/actions/websocket_actions.jsx index 3f3e81d16..2e95c712c 100644 --- a/webapp/actions/websocket_actions.jsx +++ b/webapp/actions/websocket_actions.jsx @@ -137,10 +137,6 @@ function handleEvent(msg) { handleUserUpdatedEvent(msg); break; - case SocketEvents.CHANNEL_VIEWED: - handleChannelViewedEvent(msg); - break; - case SocketEvents.CHANNEL_DELETED: handleChannelDeletedEvent(msg); break; @@ -282,15 +278,6 @@ function handleUserUpdatedEvent(msg) { } } -function handleChannelViewedEvent(msg) { - // Useful for when multiple devices have the app open to different channels - if (TeamStore.getCurrentId() === msg.broadcast.team_id && - ChannelStore.getCurrentId() !== msg.data.channel_id && - UserStore.getCurrentId() === msg.broadcast.user_id) { - AsyncClient.getChannel(msg.data.channel_id); - } -} - function handleChannelDeletedEvent(msg) { if (ChannelStore.getCurrentId() === msg.data.channel_id) { const teamUrl = TeamStore.getCurrentTeamRelativeUrl(); diff --git a/webapp/components/needs_team.jsx b/webapp/components/needs_team.jsx index 0b91814c3..fb6029c2b 100644 --- a/webapp/components/needs_team.jsx +++ b/webapp/components/needs_team.jsx @@ -42,6 +42,8 @@ import SelectTeamModal from 'components/admin_console/select_team_modal.jsx'; import iNoBounce from 'inobounce'; import * as UserAgent from 'utils/user_agent.jsx'; +const UNREAD_CHECK_TIME_MILLISECONDS = 10000; + export default class NeedsTeam extends React.Component { constructor(params) { super(params); @@ -49,6 +51,8 @@ export default class NeedsTeam extends React.Component { this.onTeamChanged = this.onTeamChanged.bind(this); this.onPreferencesChanged = this.onPreferencesChanged.bind(this); + this.blurTime = new Date().getTime(); + const team = TeamStore.getCurrent(); this.state = { @@ -97,11 +101,16 @@ export default class NeedsTeam extends React.Component { AsyncClient.viewChannel(); ChannelStore.resetCounts(ChannelStore.getCurrentId()); ChannelStore.emitChange(); + window.isActive = true; + if (new Date().getTime() - this.blurTime > UNREAD_CHECK_TIME_MILLISECONDS) { + AsyncClient.getMyChannelMembers(); + } }); $(window).on('blur', () => { window.isActive = false; + this.blurTime = new Date().getTime(); if (UserStore.getCurrentUser()) { AsyncClient.viewChannel(''); } diff --git a/webapp/components/post_view/post_view_cache.jsx b/webapp/components/post_view/post_view_cache.jsx index 9c3f1db1b..b0b35a5c0 100644 --- a/webapp/components/post_view/post_view_cache.jsx +++ b/webapp/components/post_view/post_view_cache.jsx @@ -33,7 +33,7 @@ export default class PostViewCache extends React.Component { componentWillUnmount() { if (UserStore.getCurrentUser()) { - AsyncClient.viewChannel(''); + AsyncClient.viewChannel('', this.state.currentChannelId || ''); } ChannelStore.removeChangeListener(this.onChannelChange); } diff --git a/webapp/components/team_sidebar/components/team_button.jsx b/webapp/components/team_sidebar/components/team_button.jsx index 2df21b20b..6fbf8aef9 100644 --- a/webapp/components/team_sidebar/components/team_button.jsx +++ b/webapp/components/team_sidebar/components/team_button.jsx @@ -3,6 +3,8 @@ import Constants from 'utils/constants.jsx'; +import {switchTeams} from 'actions/team_actions.jsx'; + import React from 'react'; import {Link} from 'react-router/es6'; import {Tooltip, OverlayTrigger} from 'react-bootstrap'; @@ -11,9 +13,15 @@ export default class TeamButton extends React.Component { constructor(props) { super(props); + this.handleSwitch = this.handleSwitch.bind(this); this.handleDisabled = this.handleDisabled.bind(this); } + handleSwitch(e) { + e.preventDefault(); + switchTeams(this.props.url); + } + handleDisabled(e) { e.preventDefault(); } @@ -22,7 +30,7 @@ export default class TeamButton extends React.Component { let teamClass = this.props.active ? 'active' : ''; const btnClass = this.props.btnClass; const disabled = this.props.disabled ? 'team-disabled' : ''; - const handleClick = (this.props.active || this.props.disabled) ? this.handleDisabled : null; + const handleClick = (this.props.active || this.props.disabled) ? this.handleDisabled : this.handleSwitch; let badge; if (!teamClass) { diff --git a/webapp/root.jsx b/webapp/root.jsx index b8fa4e6a2..93cfa5a38 100644 --- a/webapp/root.jsx +++ b/webapp/root.jsx @@ -11,7 +11,9 @@ import PDFJS from 'pdfjs-dist'; import * as GlobalActions from 'actions/global_actions.jsx'; import * as Websockets from 'actions/websocket_actions.jsx'; import BrowserStore from 'stores/browser_store.jsx'; +import ChannelStore from 'stores/channel_store.jsx'; import * as I18n from 'i18n/i18n.jsx'; +import * as AsyncClient from 'utils/async_client.jsx'; // Import our styles import 'bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css'; @@ -58,6 +60,7 @@ function preRenderSetup(callwhendone) { $(window).on('beforeunload', () => { BrowserStore.setLastServerVersion(''); + AsyncClient.viewChannel('', ChannelStore.getCurrentId() || ''); Websockets.close(); } ); diff --git a/webapp/stores/channel_store.jsx b/webapp/stores/channel_store.jsx index 575f68f4c..488e49492 100644 --- a/webapp/stores/channel_store.jsx +++ b/webapp/stores/channel_store.jsx @@ -392,6 +392,31 @@ class ChannelStoreClass extends EventEmitter { return false; } + + incrementMessages(id) { + if (!this.unreadCounts[id]) { + return; + } + + this.unreadCounts[id].msgs++; + this.get(id).total_msg_count++; + } + + incrementMentionsIfNeeded(id, msgProps) { + let mentions = []; + if (msgProps && msgProps.mentions) { + mentions = JSON.parse(msgProps.mentions); + } + + if (!this.unreadCounts[id]) { + return; + } + + if (mentions.indexOf(UserStore.getCurrentId()) !== -1) { + this.unreadCounts[id].mentions++; + this.getMyMember(id).mention_count++; + } + } } var ChannelStore = new ChannelStoreClass(); @@ -469,6 +494,18 @@ ChannelStore.dispatchToken = AppDispatcher.register((payload) => { ChannelStore.emitStatsChange(); break; + case ActionTypes.RECEIVED_POST: + var id = action.post.channel_id; + var teamId = action.websocketMessageProps ? action.websocketMessageProps.team_id : ''; + + // Current team and not current channel or the window is inactive + if (TeamStore.getCurrentId() === teamId && (ChannelStore.getCurrentId() !== id || !window.isActive)) { + ChannelStore.incrementMessages(id); + ChannelStore.incrementMentionsIfNeeded(id, action.websocketMessageProps); + ChannelStore.emitChange(); + } + break; + default: break; } diff --git a/webapp/stores/team_store.jsx b/webapp/stores/team_store.jsx index 2752c6b57..e58c79806 100644 --- a/webapp/stores/team_store.jsx +++ b/webapp/stores/team_store.jsx @@ -316,6 +316,23 @@ class TeamStoreClass extends EventEmitter { member.mention_count -= channelMember.mention_count; } } + + incrementMessages(id) { + const member = this.my_team_members.filter((m) => m.team_id === id)[0]; + member.msg_count++; + } + + incrementMentionsIfNeeded(id, msgProps) { + let mentions = []; + if (msgProps && msgProps.mentions) { + mentions = JSON.parse(msgProps.mentions); + } + + if (mentions.indexOf(UserStore.getCurrentId()) !== -1) { + const member = this.my_team_members.filter((m) => m.team_id === id)[0]; + member.mention_count++; + } + } } var TeamStore = new TeamStoreClass(); @@ -370,6 +387,14 @@ TeamStore.dispatchToken = AppDispatcher.register((payload) => { TeamStore.emitUnreadChange(); } break; + case ActionTypes.RECEIVED_POST: + var id = action.websocketMessageProps ? action.websocketMessageProps.team_id : ''; + if (TeamStore.getCurrentId() !== id && id.length > 0) { + TeamStore.incrementMessages(id); + TeamStore.incrementMentionsIfNeeded(id, action.websocketMessageProps); + TeamStore.emitChange(); + } + break; default: } }); -- cgit v1.2.3-1-g7c22