summaryrefslogtreecommitdiffstats
path: root/webapp/stores/user_typing_store.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/stores/user_typing_store.jsx')
-rw-r--r--webapp/stores/user_typing_store.jsx108
1 files changed, 108 insertions, 0 deletions
diff --git a/webapp/stores/user_typing_store.jsx b/webapp/stores/user_typing_store.jsx
new file mode 100644
index 000000000..ab0a9af1d
--- /dev/null
+++ b/webapp/stores/user_typing_store.jsx
@@ -0,0 +1,108 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
+import UserStore from 'stores/user_store.jsx';
+import EventEmitter from 'events';
+import * as Utils from 'utils/utils.jsx';
+
+import Constants from 'utils/constants.jsx';
+const ActionTypes = Constants.ActionTypes;
+
+const CHANGE_EVENT = 'change';
+
+class UserTypingStoreClass extends EventEmitter {
+ constructor() {
+ super();
+
+ // All typeing users by channel
+ // this.typingUsers.[channelId+postParentId].user if present then user us typing
+ // Value is timeout to remove user
+ this.typingUsers = {};
+ }
+
+ emitChange() {
+ this.emit(CHANGE_EVENT);
+ }
+
+ addChangeListener(callback) {
+ this.on(CHANGE_EVENT, callback);
+ }
+
+ removeChangeListener(callback) {
+ this.removeListener(CHANGE_EVENT, callback);
+ }
+
+ usernameFromId(userId) {
+ let username = Utils.localizeMessage('msg_typing.someone', 'Someone');
+ if (UserStore.hasProfile(userId)) {
+ username = UserStore.getProfile(userId).username;
+ }
+ return username;
+ }
+
+ userTyping(channelId, userId, postParentId) {
+ const username = this.usernameFromId(userId);
+
+ // Key representing a location where users can type
+ const loc = channelId + postParentId;
+
+ // Create entry
+ if (!this.typingUsers[loc]) {
+ this.typingUsers[loc] = {};
+ }
+
+ // If we already have this user, clear it's timeout to be deleted
+ if (this.typingUsers[loc][username]) {
+ clearTimeout(this.typingUsers[loc][username].timeout);
+ }
+
+ // Set the user and a timeout to remove it
+ this.typingUsers[loc][username] = setTimeout(() => {
+ delete this.typingUsers[loc][username];
+ if (this.typingUsers[loc] === {}) {
+ delete this.typingUsers[loc];
+ }
+ this.emitChange();
+ }, Constants.UPDATE_TYPING_MS);
+ this.emitChange();
+ }
+
+ getUsersTyping(channelId, postParentId) {
+ // Key representing a location where users can type
+ const loc = channelId + postParentId;
+
+ return this.typingUsers[loc];
+ }
+
+ userPosted(userId, channelId, postParentId) {
+ const username = this.usernameFromId(userId);
+ const loc = channelId + postParentId;
+
+ if (this.typingUsers[loc]) {
+ clearTimeout(this.typingUsers[loc][username]);
+ delete this.typingUsers[loc][username];
+ if (this.typingUsers[loc] === {}) {
+ delete this.typingUsers[loc];
+ }
+ this.emitChange();
+ }
+ }
+}
+
+var UserTypingStore = new UserTypingStoreClass();
+
+UserTypingStore.dispatchToken = AppDispatcher.register((payload) => {
+ var action = payload.action;
+
+ switch (action.type) {
+ case ActionTypes.RECEIVED_POST:
+ UserTypingStore.userPosted(action.post.user_id, action.post.channel_id, action.post.parent_id);
+ break;
+ case ActionTypes.USER_TYPING:
+ UserTypingStore.userTyping(action.channelId, action.userId, action.postParentId);
+ break;
+ }
+});
+
+export default UserTypingStore;