mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Small refactor of websocket code on client and server
This commit is contained in:
@@ -568,7 +568,7 @@ func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
Srv.Store.Channel().UpdateLastViewedAt(id, c.Session.UserId)
|
Srv.Store.Channel().UpdateLastViewedAt(id, c.Session.UserId)
|
||||||
|
|
||||||
message := model.NewMessage(c.Session.TeamId, id, c.Session.UserId, model.ACTION_VIEWED)
|
message := model.NewMessage(c.Session.TeamId, id, c.Session.UserId, model.ACTION_CHANNEL_VIEWED)
|
||||||
message.Add("channel_id", id)
|
message.Add("channel_id", id)
|
||||||
|
|
||||||
PublishAndForget(message)
|
PublishAndForget(message)
|
||||||
@@ -777,9 +777,8 @@ func RemoveUserFromChannel(userIdToRemove string, removerUserId string, channel
|
|||||||
|
|
||||||
UpdateChannelAccessCacheAndForget(channel.TeamId, userIdToRemove, channel.Id)
|
UpdateChannelAccessCacheAndForget(channel.TeamId, userIdToRemove, channel.Id)
|
||||||
|
|
||||||
message := model.NewMessage(channel.TeamId, "", userIdToRemove, model.ACTION_USER_REMOVED)
|
message := model.NewMessage(channel.TeamId, channel.Id, userIdToRemove, model.ACTION_USER_REMOVED)
|
||||||
message.Add("channel_id", channel.Id)
|
message.Add("remover_id", removerUserId)
|
||||||
message.Add("remover", removerUserId)
|
|
||||||
PublishAndForget(message)
|
PublishAndForget(message)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -92,25 +92,10 @@ func (c *WebConn) writePump() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(msg.ChannelId) > 0 {
|
|
||||||
allowed, ok := c.ChannelAccessCache[msg.ChannelId]
|
|
||||||
if !ok {
|
|
||||||
allowed = hasPermissionsToChannel(Srv.Store.Channel().CheckPermissionsTo(c.TeamId, msg.ChannelId, c.UserId))
|
|
||||||
c.ChannelAccessCache[msg.ChannelId] = allowed
|
|
||||||
}
|
|
||||||
|
|
||||||
if allowed {
|
|
||||||
c.WebSocket.SetWriteDeadline(time.Now().Add(WRITE_WAIT))
|
c.WebSocket.SetWriteDeadline(time.Now().Add(WRITE_WAIT))
|
||||||
if err := c.WebSocket.WriteJSON(msg); err != nil {
|
if err := c.WebSocket.WriteJSON(msg); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c.WebSocket.SetWriteDeadline(time.Now().Add(WRITE_WAIT))
|
|
||||||
if err := c.WebSocket.WriteJSON(msg); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
c.WebSocket.SetWriteDeadline(time.Now().Add(WRITE_WAIT))
|
c.WebSocket.SetWriteDeadline(time.Now().Add(WRITE_WAIT))
|
||||||
@@ -121,9 +106,11 @@ func (c *WebConn) writePump() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *WebConn) updateChannelAccessCache(channelId string) {
|
func (c *WebConn) updateChannelAccessCache(channelId string) bool {
|
||||||
allowed := hasPermissionsToChannel(Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.UserId))
|
allowed := hasPermissionsToChannel(Srv.Store.Channel().CheckPermissionsTo(c.TeamId, channelId, c.UserId))
|
||||||
c.ChannelAccessCache[channelId] = allowed
|
c.ChannelAccessCache[channelId] = allowed
|
||||||
|
|
||||||
|
return allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasPermissionsToChannel(sc store.StoreChannel) bool {
|
func hasPermissionsToChannel(sc store.StoreChannel) bool {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ func (h *TeamHub) Start() {
|
|||||||
}
|
}
|
||||||
case msg := <-h.broadcast:
|
case msg := <-h.broadcast:
|
||||||
for webCon := range h.connections {
|
for webCon := range h.connections {
|
||||||
if !(webCon.UserId == msg.UserId && msg.Action == model.ACTION_TYPING) {
|
if ShouldSendEvent(webCon, msg) {
|
||||||
select {
|
select {
|
||||||
case webCon.Send <- msg:
|
case webCon.Send <- msg:
|
||||||
default:
|
default:
|
||||||
@@ -86,3 +86,32 @@ func (h *TeamHub) UpdateChannelAccessCache(userId string, channelId string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ShouldSendEvent(webCon *WebConn, msg *model.Message) bool {
|
||||||
|
|
||||||
|
if webCon.UserId == msg.UserId {
|
||||||
|
// Don't need to tell the user they are typing
|
||||||
|
if msg.Action == model.ACTION_TYPING {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Don't share a user's view events with other users
|
||||||
|
if msg.Action == model.ACTION_CHANNEL_VIEWED {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only report events to a user who is the subject of the event, or is in the channel of the event
|
||||||
|
if len(msg.ChannelId) > 0 {
|
||||||
|
allowed, ok := webCon.ChannelAccessCache[msg.ChannelId]
|
||||||
|
if !ok {
|
||||||
|
allowed = webCon.updateChannelAccessCache(msg.ChannelId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !allowed {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const (
|
|||||||
ACTION_POSTED = "posted"
|
ACTION_POSTED = "posted"
|
||||||
ACTION_POST_EDITED = "post_edited"
|
ACTION_POST_EDITED = "post_edited"
|
||||||
ACTION_POST_DELETED = "post_deleted"
|
ACTION_POST_DELETED = "post_deleted"
|
||||||
ACTION_VIEWED = "viewed"
|
ACTION_CHANNEL_VIEWED = "channel_viewed"
|
||||||
ACTION_NEW_USER = "new_user"
|
ACTION_NEW_USER = "new_user"
|
||||||
ACTION_USER_ADDED = "user_added"
|
ACTION_USER_ADDED = "user_added"
|
||||||
ACTION_USER_REMOVED = "user_removed"
|
ACTION_USER_REMOVED = "user_removed"
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
const ChannelStore = require('../stores/channel_store.jsx');
|
const ChannelStore = require('../stores/channel_store.jsx');
|
||||||
const UserStore = require('../stores/user_store.jsx');
|
const UserStore = require('../stores/user_store.jsx');
|
||||||
const PostStore = require('../stores/post_store.jsx');
|
const PostStore = require('../stores/post_store.jsx');
|
||||||
const SocketStore = require('../stores/socket_store.jsx');
|
|
||||||
const NavbarSearchBox = require('./search_bar.jsx');
|
const NavbarSearchBox = require('./search_bar.jsx');
|
||||||
const AsyncClient = require('../utils/async_client.jsx');
|
const AsyncClient = require('../utils/async_client.jsx');
|
||||||
const Client = require('../utils/client.jsx');
|
const Client = require('../utils/client.jsx');
|
||||||
@@ -25,7 +24,6 @@ export default class ChannelHeader extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.onListenerChange = this.onListenerChange.bind(this);
|
this.onListenerChange = this.onListenerChange.bind(this);
|
||||||
this.onSocketChange = this.onSocketChange.bind(this);
|
|
||||||
this.handleLeave = this.handleLeave.bind(this);
|
this.handleLeave = this.handleLeave.bind(this);
|
||||||
this.searchMentions = this.searchMentions.bind(this);
|
this.searchMentions = this.searchMentions.bind(this);
|
||||||
|
|
||||||
@@ -45,7 +43,6 @@ export default class ChannelHeader extends React.Component {
|
|||||||
ChannelStore.addExtraInfoChangeListener(this.onListenerChange);
|
ChannelStore.addExtraInfoChangeListener(this.onListenerChange);
|
||||||
PostStore.addSearchChangeListener(this.onListenerChange);
|
PostStore.addSearchChangeListener(this.onListenerChange);
|
||||||
UserStore.addChangeListener(this.onListenerChange);
|
UserStore.addChangeListener(this.onListenerChange);
|
||||||
SocketStore.addChangeListener(this.onSocketChange);
|
|
||||||
}
|
}
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
ChannelStore.removeChangeListener(this.onListenerChange);
|
ChannelStore.removeChangeListener(this.onListenerChange);
|
||||||
@@ -60,16 +57,9 @@ export default class ChannelHeader extends React.Component {
|
|||||||
}
|
}
|
||||||
$('.channel-header__info .description').popover({placement: 'bottom', trigger: 'hover', html: true, delay: {show: 500, hide: 500}});
|
$('.channel-header__info .description').popover({placement: 'bottom', trigger: 'hover', html: true, delay: {show: 500, hide: 500}});
|
||||||
}
|
}
|
||||||
onSocketChange(msg) {
|
|
||||||
if (msg.action === 'new_user' ||
|
|
||||||
msg.action === 'user_added' ||
|
|
||||||
(msg.action === 'user_removed' && msg.user_id !== UserStore.getCurrentId())) {
|
|
||||||
AsyncClient.getChannelExtraInfo(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handleLeave() {
|
handleLeave() {
|
||||||
Client.leaveChannel(this.state.channel.id,
|
Client.leaveChannel(this.state.channel.id,
|
||||||
function handleLeaveSuccess() {
|
() => {
|
||||||
AppDispatcher.handleViewAction({
|
AppDispatcher.handleViewAction({
|
||||||
type: ActionTypes.LEAVE_CHANNEL,
|
type: ActionTypes.LEAVE_CHANNEL,
|
||||||
id: this.state.channel.id
|
id: this.state.channel.id
|
||||||
@@ -77,8 +67,8 @@ export default class ChannelHeader extends React.Component {
|
|||||||
|
|
||||||
const townsquare = ChannelStore.getByName('town-square');
|
const townsquare = ChannelStore.getByName('town-square');
|
||||||
Utils.switchChannel(townsquare);
|
Utils.switchChannel(townsquare);
|
||||||
}.bind(this),
|
},
|
||||||
function handleLeaveError(err) {
|
(err) => {
|
||||||
AsyncClient.dispatchError(err, 'handleLeave');
|
AsyncClient.dispatchError(err, 'handleLeave');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
var SocketStore = require('../stores/socket_store.jsx');
|
const SocketStore = require('../stores/socket_store.jsx');
|
||||||
var UserStore = require('../stores/user_store.jsx');
|
const UserStore = require('../stores/user_store.jsx');
|
||||||
|
|
||||||
|
const Constants = require('../utils/constants.jsx');
|
||||||
|
const SocketEvents = Constants.SocketEvents;
|
||||||
|
|
||||||
export default class MsgTyping extends React.Component {
|
export default class MsgTyping extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -33,7 +36,7 @@ export default class MsgTyping extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onChange(msg) {
|
onChange(msg) {
|
||||||
if (msg.action === 'typing' &&
|
if (msg.action === SocketEvents.TYPING &&
|
||||||
this.props.channelId === msg.channel_id &&
|
this.props.channelId === msg.channel_id &&
|
||||||
this.props.parentId === msg.props.parent_id) {
|
this.props.parentId === msg.props.parent_id) {
|
||||||
this.lastTime = new Date().getTime();
|
this.lastTime = new Date().getTime();
|
||||||
@@ -52,7 +55,7 @@ export default class MsgTyping extends React.Component {
|
|||||||
}
|
}
|
||||||
}.bind(this), 3000);
|
}.bind(this), 3000);
|
||||||
}
|
}
|
||||||
} else if (msg.action === 'posted' && msg.channel_id === this.props.channelId) {
|
} else if (msg.action === SocketEvents.POSTED && msg.channel_id === this.props.channelId) {
|
||||||
this.setState({text: ''});
|
this.setState({text: ''});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
var PostStore = require('../stores/post_store.jsx');
|
const Post = require('./post.jsx');
|
||||||
var ChannelStore = require('../stores/channel_store.jsx');
|
const UserProfile = require('./user_profile.jsx');
|
||||||
var UserStore = require('../stores/user_store.jsx');
|
const AsyncClient = require('../utils/async_client.jsx');
|
||||||
var PreferenceStore = require('../stores/preference_store.jsx');
|
const LoadingScreen = require('./loading_screen.jsx');
|
||||||
var UserProfile = require('./user_profile.jsx');
|
|
||||||
var AsyncClient = require('../utils/async_client.jsx');
|
const PostStore = require('../stores/post_store.jsx');
|
||||||
var Post = require('./post.jsx');
|
const ChannelStore = require('../stores/channel_store.jsx');
|
||||||
var LoadingScreen = require('./loading_screen.jsx');
|
const UserStore = require('../stores/user_store.jsx');
|
||||||
var SocketStore = require('../stores/socket_store.jsx');
|
const SocketStore = require('../stores/socket_store.jsx');
|
||||||
var utils = require('../utils/utils.jsx');
|
const PreferenceStore = require('../stores/preference_store.jsx');
|
||||||
var Client = require('../utils/client.jsx');
|
|
||||||
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
const utils = require('../utils/utils.jsx');
|
||||||
var Constants = require('../utils/constants.jsx');
|
const Client = require('../utils/client.jsx');
|
||||||
var ActionTypes = Constants.ActionTypes;
|
const Constants = require('../utils/constants.jsx');
|
||||||
|
const ActionTypes = Constants.ActionTypes;
|
||||||
|
const SocketEvents = Constants.SocketEvents;
|
||||||
|
|
||||||
|
const AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
||||||
|
|
||||||
export default class PostList extends React.Component {
|
export default class PostList extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -58,7 +62,7 @@ export default class PostList extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
postList.order.sort(function postSort(a, b) {
|
postList.order.sort((a, b) => {
|
||||||
if (postList.posts[a].create_at > postList.posts[b].create_at) {
|
if (postList.posts[a].create_at > postList.posts[b].create_at) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -82,7 +86,7 @@ export default class PostList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
postList: postList
|
postList
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -263,14 +267,14 @@ export default class PostList extends React.Component {
|
|||||||
Client.getPosts(
|
Client.getPosts(
|
||||||
id,
|
id,
|
||||||
PostStore.getLatestUpdate(id),
|
PostStore.getLatestUpdate(id),
|
||||||
function success() {
|
() => {
|
||||||
this.loadInProgress = false;
|
this.loadInProgress = false;
|
||||||
this.setState({isFirstLoadComplete: true});
|
this.setState({isFirstLoadComplete: true});
|
||||||
}.bind(this),
|
},
|
||||||
function fail() {
|
() => {
|
||||||
this.loadInProgress = false;
|
this.loadInProgress = false;
|
||||||
this.setState({isFirstLoadComplete: true});
|
this.setState({isFirstLoadComplete: true});
|
||||||
}.bind(this)
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
onChange() {
|
onChange() {
|
||||||
@@ -281,28 +285,16 @@ export default class PostList extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onSocketChange(msg) {
|
onSocketChange(msg) {
|
||||||
var post;
|
if (msg.action === SocketEvents.POST_DELETED) {
|
||||||
if (msg.action === 'posted' || msg.action === 'post_edited') {
|
|
||||||
post = JSON.parse(msg.props.post);
|
|
||||||
PostStore.storePost(post);
|
|
||||||
} else if (msg.action === 'post_deleted') {
|
|
||||||
var activeRoot = $(document.activeElement).closest('.comment-create-body')[0];
|
var activeRoot = $(document.activeElement).closest('.comment-create-body')[0];
|
||||||
var activeRootPostId = '';
|
var activeRootPostId = '';
|
||||||
if (activeRoot && activeRoot.id.length > 0) {
|
if (activeRoot && activeRoot.id.length > 0) {
|
||||||
activeRootPostId = activeRoot.id;
|
activeRootPostId = activeRoot.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
post = JSON.parse(msg.props.post);
|
|
||||||
|
|
||||||
PostStore.storeUnseenDeletedPost(post);
|
|
||||||
PostStore.removePost(post, true);
|
|
||||||
PostStore.emitChange();
|
|
||||||
|
|
||||||
if (activeRootPostId === msg.props.post_id && UserStore.getCurrentId() !== msg.user_id) {
|
if (activeRootPostId === msg.props.post_id && UserStore.getCurrentId() !== msg.user_id) {
|
||||||
$('#post_deleted').modal('show');
|
$('#post_deleted').modal('show');
|
||||||
}
|
}
|
||||||
} else if (msg.action === 'new_user') {
|
|
||||||
AsyncClient.getProfiles();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onTimeChange() {
|
onTimeChange() {
|
||||||
@@ -352,7 +344,7 @@ export default class PostList extends React.Component {
|
|||||||
data-title={channel.display_name}
|
data-title={channel.display_name}
|
||||||
data-channelid={channel.id}
|
data-channelid={channel.id}
|
||||||
>
|
>
|
||||||
<i className='fa fa-pencil'></i>Set a description
|
<i className='fa fa-pencil'></i>{'Set a description'}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
const AsyncClient = require('../utils/async_client.jsx');
|
const AsyncClient = require('../utils/async_client.jsx');
|
||||||
const BrowserStore = require('../stores/browser_store.jsx');
|
|
||||||
const ChannelStore = require('../stores/channel_store.jsx');
|
const ChannelStore = require('../stores/channel_store.jsx');
|
||||||
const Client = require('../utils/client.jsx');
|
const Client = require('../utils/client.jsx');
|
||||||
const Constants = require('../utils/constants.jsx');
|
const Constants = require('../utils/constants.jsx');
|
||||||
@@ -11,7 +10,6 @@ const NewChannelFlow = require('./new_channel_flow.jsx');
|
|||||||
const MoreDirectChannels = require('./more_direct_channels.jsx');
|
const MoreDirectChannels = require('./more_direct_channels.jsx');
|
||||||
const SearchBox = require('./search_bar.jsx');
|
const SearchBox = require('./search_bar.jsx');
|
||||||
const SidebarHeader = require('./sidebar_header.jsx');
|
const SidebarHeader = require('./sidebar_header.jsx');
|
||||||
const SocketStore = require('../stores/socket_store.jsx');
|
|
||||||
const TeamStore = require('../stores/team_store.jsx');
|
const TeamStore = require('../stores/team_store.jsx');
|
||||||
const UnreadChannelIndicator = require('./unread_channel_indicator.jsx');
|
const UnreadChannelIndicator = require('./unread_channel_indicator.jsx');
|
||||||
const UserStore = require('../stores/user_store.jsx');
|
const UserStore = require('../stores/user_store.jsx');
|
||||||
@@ -129,7 +127,6 @@ export default class Sidebar extends React.Component {
|
|||||||
UserStore.addChangeListener(this.onChange);
|
UserStore.addChangeListener(this.onChange);
|
||||||
UserStore.addStatusesChangeListener(this.onChange);
|
UserStore.addStatusesChangeListener(this.onChange);
|
||||||
TeamStore.addChangeListener(this.onChange);
|
TeamStore.addChangeListener(this.onChange);
|
||||||
SocketStore.addChangeListener(this.onSocketChange);
|
|
||||||
PreferenceStore.addChangeListener(this.onChange);
|
PreferenceStore.addChangeListener(this.onChange);
|
||||||
|
|
||||||
$('.nav-pills__container').perfectScrollbar();
|
$('.nav-pills__container').perfectScrollbar();
|
||||||
@@ -160,7 +157,6 @@ export default class Sidebar extends React.Component {
|
|||||||
UserStore.removeChangeListener(this.onChange);
|
UserStore.removeChangeListener(this.onChange);
|
||||||
UserStore.removeStatusesChangeListener(this.onChange);
|
UserStore.removeStatusesChangeListener(this.onChange);
|
||||||
TeamStore.removeChangeListener(this.onChange);
|
TeamStore.removeChangeListener(this.onChange);
|
||||||
SocketStore.removeChangeListener(this.onSocketChange);
|
|
||||||
PreferenceStore.removeChangeListener(this.onChange);
|
PreferenceStore.removeChangeListener(this.onChange);
|
||||||
}
|
}
|
||||||
onChange() {
|
onChange() {
|
||||||
@@ -169,94 +165,6 @@ export default class Sidebar extends React.Component {
|
|||||||
this.setState(newState);
|
this.setState(newState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onSocketChange(msg) {
|
|
||||||
if (msg.action === 'posted') {
|
|
||||||
if (ChannelStore.getCurrentId() === msg.channel_id) {
|
|
||||||
if (window.isActive) {
|
|
||||||
AsyncClient.updateLastViewedAt();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
AsyncClient.getChannels();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UserStore.getCurrentId() !== msg.user_id) {
|
|
||||||
var mentions = [];
|
|
||||||
if (msg.props.mentions) {
|
|
||||||
mentions = JSON.parse(msg.props.mentions);
|
|
||||||
}
|
|
||||||
var channel = ChannelStore.get(msg.channel_id);
|
|
||||||
|
|
||||||
const user = UserStore.getCurrentUser();
|
|
||||||
const member = ChannelStore.getMember(msg.channel_id);
|
|
||||||
|
|
||||||
var notifyLevel = member && member.notify_props ? member.notify_props.desktop : 'default';
|
|
||||||
if (notifyLevel === 'default') {
|
|
||||||
notifyLevel = user.notify_props.desktop;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notifyLevel === 'none') {
|
|
||||||
return;
|
|
||||||
} else if (notifyLevel === 'mention' && mentions.indexOf(user.id) === -1 && channel.type !== 'D') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var username = 'Someone';
|
|
||||||
if (UserStore.hasProfile(msg.user_id)) {
|
|
||||||
username = UserStore.getProfile(msg.user_id).username;
|
|
||||||
}
|
|
||||||
|
|
||||||
var title = 'Posted';
|
|
||||||
if (channel) {
|
|
||||||
title = channel.display_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
var repRegex = new RegExp('<br>', 'g');
|
|
||||||
var post = JSON.parse(msg.props.post);
|
|
||||||
var msgProps = msg.props;
|
|
||||||
var notifyText = post.message.replace(repRegex, '\n').replace(/\n+/g, ' ').replace('<mention>', '').replace('</mention>', '');
|
|
||||||
|
|
||||||
if (notifyText.length > 50) {
|
|
||||||
notifyText = notifyText.substring(0, 49) + '...';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notifyText.length === 0) {
|
|
||||||
if (msgProps.image) {
|
|
||||||
Utils.notifyMe(title, username + ' uploaded an image', channel);
|
|
||||||
} else if (msgProps.otherFile) {
|
|
||||||
Utils.notifyMe(title, username + ' uploaded a file', channel);
|
|
||||||
} else {
|
|
||||||
Utils.notifyMe(title, username + ' did something new', channel);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Utils.notifyMe(title, username + ' wrote: ' + notifyText, channel);
|
|
||||||
}
|
|
||||||
if (!user.notify_props || user.notify_props.desktop_sound === 'true') {
|
|
||||||
Utils.ding();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (msg.action === 'viewed') {
|
|
||||||
if (ChannelStore.getCurrentId() !== msg.channel_id && UserStore.getCurrentId() === msg.user_id) {
|
|
||||||
AsyncClient.getChannel(msg.channel_id);
|
|
||||||
}
|
|
||||||
} else if (msg.action === 'user_added') {
|
|
||||||
if (UserStore.getCurrentId() === msg.user_id) {
|
|
||||||
AsyncClient.getChannel(msg.channel_id);
|
|
||||||
}
|
|
||||||
} else if (msg.action === 'user_removed') {
|
|
||||||
if (msg.user_id === UserStore.getCurrentId()) {
|
|
||||||
AsyncClient.getChannels(true);
|
|
||||||
|
|
||||||
if (msg.props.remover !== msg.user_id && msg.props.channel_id === ChannelStore.getCurrentId() && $('#removed_from_channel').length > 0) {
|
|
||||||
var sentState = {};
|
|
||||||
sentState.channelName = ChannelStore.getCurrent().display_name;
|
|
||||||
sentState.remover = UserStore.getProfile(msg.props.remover).username;
|
|
||||||
|
|
||||||
BrowserStore.setItem('channel-removed-state', sentState);
|
|
||||||
$('#removed_from_channel').modal('show');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateTitle() {
|
updateTitle() {
|
||||||
const channel = ChannelStore.getCurrent();
|
const channel = ChannelStore.getCurrent();
|
||||||
if (channel) {
|
if (channel) {
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
const AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
||||||
var UserStore = require('./user_store.jsx');
|
const UserStore = require('./user_store.jsx');
|
||||||
var ErrorStore = require('./error_store.jsx');
|
const PostStore = require('./post_store.jsx');
|
||||||
var EventEmitter = require('events').EventEmitter;
|
const ChannelStore = require('./channel_store.jsx');
|
||||||
|
const BrowserStore = require('./browser_store.jsx');
|
||||||
|
const ErrorStore = require('./error_store.jsx');
|
||||||
|
const EventEmitter = require('events').EventEmitter;
|
||||||
|
|
||||||
var Constants = require('../utils/constants.jsx');
|
const Utils = require('../utils/utils.jsx');
|
||||||
var ActionTypes = Constants.ActionTypes;
|
const AsyncClient = require('../utils/async_client.jsx');
|
||||||
|
|
||||||
var CHANGE_EVENT = 'change';
|
const Constants = require('../utils/constants.jsx');
|
||||||
|
const ActionTypes = Constants.ActionTypes;
|
||||||
|
const SocketEvents = Constants.SocketEvents;
|
||||||
|
|
||||||
|
const CHANGE_EVENT = 'change';
|
||||||
|
|
||||||
var conn;
|
var conn;
|
||||||
|
|
||||||
@@ -21,6 +28,7 @@ class SocketStoreClass extends EventEmitter {
|
|||||||
this.emitChange = this.emitChange.bind(this);
|
this.emitChange = this.emitChange.bind(this);
|
||||||
this.addChangeListener = this.addChangeListener.bind(this);
|
this.addChangeListener = this.addChangeListener.bind(this);
|
||||||
this.removeChangeListener = this.removeChangeListener.bind(this);
|
this.removeChangeListener = this.removeChangeListener.bind(this);
|
||||||
|
this.handleMessage = this.handleMessage.bind(this);
|
||||||
this.sendMessage = this.sendMessage.bind(this);
|
this.sendMessage = this.sendMessage.bind(this);
|
||||||
this.failCount = 0;
|
this.failCount = 0;
|
||||||
|
|
||||||
@@ -94,6 +102,39 @@ class SocketStoreClass extends EventEmitter {
|
|||||||
removeChangeListener(callback) {
|
removeChangeListener(callback) {
|
||||||
this.removeListener(CHANGE_EVENT, callback);
|
this.removeListener(CHANGE_EVENT, callback);
|
||||||
}
|
}
|
||||||
|
handleMessage(msg) {
|
||||||
|
switch (msg.action) {
|
||||||
|
case SocketEvents.POSTED:
|
||||||
|
handleNewPostEvent(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SocketEvents.POST_EDITED:
|
||||||
|
handlePostEditEvent(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SocketEvents.POST_DELETED:
|
||||||
|
handlePostDeleteEvent(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SocketEvents.NEW_USER:
|
||||||
|
handleNewUserEvent();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SocketEvents.USER_ADDED:
|
||||||
|
handleUserAddedEvent(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SocketEvents.USER_REMOVED:
|
||||||
|
handleUserRemovedEvent(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SocketEvents.CHANNEL_VIEWED:
|
||||||
|
handleChannelViewedEvent(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
sendMessage(msg) {
|
sendMessage(msg) {
|
||||||
if (conn && conn.readyState === WebSocket.OPEN) {
|
if (conn && conn.readyState === WebSocket.OPEN) {
|
||||||
conn.send(JSON.stringify(msg));
|
conn.send(JSON.stringify(msg));
|
||||||
@@ -104,6 +145,138 @@ class SocketStoreClass extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleNewPostEvent(msg) {
|
||||||
|
// Store post
|
||||||
|
const post = JSON.parse(msg.props.post);
|
||||||
|
PostStore.storePost(post);
|
||||||
|
|
||||||
|
// Update channel state
|
||||||
|
if (ChannelStore.getCurrentId() === msg.channel_id) {
|
||||||
|
if (window.isActive) {
|
||||||
|
AsyncClient.updateLastViewedAt();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AsyncClient.getChannel(msg.channel_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send desktop notification
|
||||||
|
if (UserStore.getCurrentId() !== msg.user_id) {
|
||||||
|
const msgProps = msg.props;
|
||||||
|
|
||||||
|
let mentions = [];
|
||||||
|
if (msgProps.mentions) {
|
||||||
|
mentions = JSON.parse(msg.props.mentions);
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = ChannelStore.get(msg.channel_id);
|
||||||
|
const user = UserStore.getCurrentUser();
|
||||||
|
const member = ChannelStore.getMember(msg.channel_id);
|
||||||
|
|
||||||
|
let notifyLevel = member && member.notify_props ? member.notify_props.desktop : 'default';
|
||||||
|
if (notifyLevel === 'default') {
|
||||||
|
notifyLevel = user.notify_props.desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notifyLevel === 'none') {
|
||||||
|
return;
|
||||||
|
} else if (notifyLevel === 'mention' && mentions.indexOf(user.id) === -1 && channel.type !== 'D') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let username = 'Someone';
|
||||||
|
if (UserStore.hasProfile(msg.user_id)) {
|
||||||
|
username = UserStore.getProfile(msg.user_id).username;
|
||||||
|
}
|
||||||
|
|
||||||
|
let title = 'Posted';
|
||||||
|
if (channel) {
|
||||||
|
title = channel.display_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
let notifyText = post.message.replace(/\n+/g, ' ');
|
||||||
|
if (notifyText.length > 50) {
|
||||||
|
notifyText = notifyText.substring(0, 49) + '...';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notifyText.length === 0) {
|
||||||
|
if (msgProps.image) {
|
||||||
|
Utils.notifyMe(title, username + ' uploaded an image', channel);
|
||||||
|
} else if (msgProps.otherFile) {
|
||||||
|
Utils.notifyMe(title, username + ' uploaded a file', channel);
|
||||||
|
} else {
|
||||||
|
Utils.notifyMe(title, username + ' did something new', channel);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Utils.notifyMe(title, username + ' wrote: ' + notifyText, channel);
|
||||||
|
}
|
||||||
|
if (!user.notify_props || user.notify_props.desktop_sound === 'true') {
|
||||||
|
Utils.ding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePostEditEvent(msg) {
|
||||||
|
// Store post
|
||||||
|
const post = JSON.parse(msg.props.post);
|
||||||
|
PostStore.storePost(post);
|
||||||
|
|
||||||
|
// Update channel state
|
||||||
|
if (ChannelStore.getCurrentId() === msg.channel_id) {
|
||||||
|
if (window.isActive) {
|
||||||
|
AsyncClient.updateLastViewedAt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePostDeleteEvent(msg) {
|
||||||
|
const post = JSON.parse(msg.props.post);
|
||||||
|
|
||||||
|
PostStore.storeUnseenDeletedPost(post);
|
||||||
|
PostStore.removePost(post, true);
|
||||||
|
PostStore.emitChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleNewUserEvent() {
|
||||||
|
AsyncClient.getProfiles();
|
||||||
|
AsyncClient.getChannelExtraInfo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleUserAddedEvent(msg) {
|
||||||
|
if (ChannelStore.getCurrentId() === msg.channel_id) {
|
||||||
|
AsyncClient.getChannelExtraInfo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UserStore.getCurrentId() === msg.user_id) {
|
||||||
|
AsyncClient.getChannel(msg.channel_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleUserRemovedEvent(msg) {
|
||||||
|
if (UserStore.getCurrentId() === msg.user_id) {
|
||||||
|
AsyncClient.getChannels();
|
||||||
|
|
||||||
|
if (msg.props.remover_id !== msg.user_id &&
|
||||||
|
msg.channel_id === ChannelStore.getCurrentId() &&
|
||||||
|
$('#removed_from_channel').length > 0) {
|
||||||
|
var sentState = {};
|
||||||
|
sentState.channelName = ChannelStore.getCurrent().display_name;
|
||||||
|
sentState.remover = UserStore.getProfile(msg.props.remover_id).username;
|
||||||
|
|
||||||
|
BrowserStore.setItem('channel-removed-state', sentState);
|
||||||
|
$('#removed_from_channel').modal('show');
|
||||||
|
}
|
||||||
|
} else if (ChannelStore.getCurrentId() === msg.channel_id) {
|
||||||
|
AsyncClient.getChannelExtraInfo(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleChannelViewedEvent(msg) {
|
||||||
|
// Useful for when multiple devices have the app open to different channels
|
||||||
|
if (ChannelStore.getCurrentId() !== msg.channel_id && UserStore.getCurrentId() === msg.user_id) {
|
||||||
|
AsyncClient.getChannel(msg.channel_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var SocketStore = new SocketStoreClass();
|
var SocketStore = new SocketStoreClass();
|
||||||
|
|
||||||
SocketStore.dispatchToken = AppDispatcher.register((payload) => {
|
SocketStore.dispatchToken = AppDispatcher.register((payload) => {
|
||||||
@@ -111,6 +284,7 @@ SocketStore.dispatchToken = AppDispatcher.register((payload) => {
|
|||||||
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionTypes.RECIEVED_MSG:
|
case ActionTypes.RECIEVED_MSG:
|
||||||
|
SocketStore.handleMessage(action.msg);
|
||||||
SocketStore.emitChange(action.msg);
|
SocketStore.emitChange(action.msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,18 @@ module.exports = {
|
|||||||
SERVER_ACTION: null,
|
SERVER_ACTION: null,
|
||||||
VIEW_ACTION: null
|
VIEW_ACTION: null
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
SocketEvents: {
|
||||||
|
POSTED: 'posted',
|
||||||
|
POST_EDITED: 'post_edited',
|
||||||
|
POST_DELETED: 'post_deleted',
|
||||||
|
CHANNEL_VIEWED: 'channel_viewed',
|
||||||
|
NEW_USER: 'new_user',
|
||||||
|
USER_ADDED: 'user_added',
|
||||||
|
USER_REMOVED: 'user_removed',
|
||||||
|
TYPING: 'user_typing'
|
||||||
|
},
|
||||||
|
|
||||||
SPECIAL_MENTIONS: ['all', 'channel'],
|
SPECIAL_MENTIONS: ['all', 'channel'],
|
||||||
CHARACTER_LIMIT: 4000,
|
CHARACTER_LIMIT: 4000,
|
||||||
IMAGE_TYPES: ['jpg', 'gif', 'bmp', 'png', 'jpeg'],
|
IMAGE_TYPES: ['jpg', 'gif', 'bmp', 'png', 'jpeg'],
|
||||||
|
|||||||
Reference in New Issue
Block a user