From 46042d995bc553a10513c527aba106e1b92d04d4 Mon Sep 17 00:00:00 2001 From: Florian Orben Date: Sun, 25 Oct 2015 02:00:55 +0100 Subject: PLT-703: Support multiple users being shown as typing underneath input boxes. --- web/react/components/create_post.jsx | 2 +- web/react/components/msg_typing.jsx | 49 ++++++++++++++++++++++++------------ web/react/utils/constants.jsx | 1 + 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx index 055be112d..b74f1871c 100644 --- a/web/react/components/create_post.jsx +++ b/web/react/components/create_post.jsx @@ -208,7 +208,7 @@ export default class CreatePost extends React.Component { } const t = Date.now(); - if ((t - this.lastTime) > 5000) { + if ((t - this.lastTime) > Constants.UPDATE_TYPING_MS) { SocketStore.sendMessage({channel_id: this.state.channelId, action: 'typing', props: {parent_id: ''}, state: {}}); this.lastTime = t; } diff --git a/web/react/components/msg_typing.jsx b/web/react/components/msg_typing.jsx index 1bd23c55c..42ae4bcc4 100644 --- a/web/react/components/msg_typing.jsx +++ b/web/react/components/msg_typing.jsx @@ -11,11 +11,11 @@ export default class MsgTyping extends React.Component { constructor(props) { super(props); - this.timer = null; - this.lastTime = 0; - this.onChange = this.onChange.bind(this); + this.getTypingText = this.getTypingText.bind(this); + this.componentWillReceiveProps = this.componentWillReceiveProps.bind(this); + this.typingUsers = {}; this.state = { text: '' }; @@ -27,7 +27,7 @@ export default class MsgTyping extends React.Component { componentWillReceiveProps(newProps) { if (this.props.channelId !== newProps.channelId) { - this.setState({text: ''}); + this.setState({text: this.getTypingText()}); } } @@ -36,27 +36,44 @@ export default class MsgTyping extends React.Component { } onChange(msg) { + let username = 'Someone'; if (msg.action === SocketEvents.TYPING && this.props.channelId === msg.channel_id && this.props.parentId === msg.props.parent_id) { - this.lastTime = new Date().getTime(); - - var username = 'Someone'; if (UserStore.hasProfile(msg.user_id)) { username = UserStore.getProfile(msg.user_id).username; } - this.setState({text: username + ' is typing...'}); - - if (!this.timer) { - this.timer = setInterval(function myTimer() { - if ((new Date().getTime() - this.lastTime) > 8000) { - this.setState({text: ''}); - } - }.bind(this), 3000); + if (this.typingUsers[username]) { + clearTimeout(this.typingUsers[username]); } + + this.typingUsers[username] = setTimeout(function myTimer(user) { + delete this.typingUsers[user]; + this.setState({text: this.getTypingText()}); + }.bind(this, username), Constants.UPDATE_TYPING_MS); + + this.setState({text: this.getTypingText()}); } else if (msg.action === SocketEvents.POSTED && msg.channel_id === this.props.channelId) { - this.setState({text: ''}); + if (UserStore.hasProfile(msg.user_id)) { + username = UserStore.getProfile(msg.user_id).username; + } + clearTimeout(this.typingUsers[username]); + delete this.typingUsers[username]; + this.setState({text: this.getTypingText()}); + } + } + + getTypingText() { + let users = Object.keys(this.typingUsers); + switch (users.length) { + case 0: + return ''; + case 1: + return users[0] + ' is typing...'; + default: + const last = users.pop(); + return users.join(', ') + ' and ' + last + ' are typing...'; } } diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx index c20d84f40..cda04bf04 100644 --- a/web/react/utils/constants.jsx +++ b/web/react/utils/constants.jsx @@ -132,6 +132,7 @@ module.exports = { OFFLINE_ICON_SVG: "", MENU_ICON: " ", COMMENT_ICON: " ", + UPDATE_TYPING_MS: 5000, THEMES: { default: { type: 'Mattermost', -- cgit v1.2.3-1-g7c22 From b7aa4220d575d446830a0b0c9a3f753214272422 Mon Sep 17 00:00:00 2001 From: Florian Orben Date: Mon, 26 Oct 2015 02:24:46 +0100 Subject: use constant value to check if to send a typing event for comments --- web/react/components/create_comment.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/react/components/create_comment.jsx b/web/react/components/create_comment.jsx index 435c7d542..18936e808 100644 --- a/web/react/components/create_comment.jsx +++ b/web/react/components/create_comment.jsx @@ -147,7 +147,7 @@ export default class CreateComment extends React.Component { } const t = Date.now(); - if ((t - this.lastTime) > 5000) { + if ((t - this.lastTime) > Constants.UPDATE_TYPING_MS) { SocketStore.sendMessage({channel_id: this.props.channelId, action: 'typing', props: {parent_id: this.props.rootId}}); this.lastTime = t; } -- cgit v1.2.3-1-g7c22 From 9a4d648c9b9a6c78cd2a171b665bc5aa9ade3634 Mon Sep 17 00:00:00 2001 From: Florian Orben Date: Mon, 26 Oct 2015 17:44:29 +0100 Subject: rename getTypingText to updateTypingText and set component's state in it --- web/react/components/msg_typing.jsx | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/web/react/components/msg_typing.jsx b/web/react/components/msg_typing.jsx index 42ae4bcc4..ccf8a2445 100644 --- a/web/react/components/msg_typing.jsx +++ b/web/react/components/msg_typing.jsx @@ -12,7 +12,7 @@ export default class MsgTyping extends React.Component { super(props); this.onChange = this.onChange.bind(this); - this.getTypingText = this.getTypingText.bind(this); + this.updateTypingText = this.updateTypingText.bind(this); this.componentWillReceiveProps = this.componentWillReceiveProps.bind(this); this.typingUsers = {}; @@ -27,7 +27,7 @@ export default class MsgTyping extends React.Component { componentWillReceiveProps(newProps) { if (this.props.channelId !== newProps.channelId) { - this.setState({text: this.getTypingText()}); + this.updateTypingText(); } } @@ -50,31 +50,37 @@ export default class MsgTyping extends React.Component { this.typingUsers[username] = setTimeout(function myTimer(user) { delete this.typingUsers[user]; - this.setState({text: this.getTypingText()}); + this.updateTypingText(); }.bind(this, username), Constants.UPDATE_TYPING_MS); - this.setState({text: this.getTypingText()}); + this.updateTypingText(); } else if (msg.action === SocketEvents.POSTED && msg.channel_id === this.props.channelId) { if (UserStore.hasProfile(msg.user_id)) { username = UserStore.getProfile(msg.user_id).username; } clearTimeout(this.typingUsers[username]); delete this.typingUsers[username]; - this.setState({text: this.getTypingText()}); + this.updateTypingText(); } } - getTypingText() { - let users = Object.keys(this.typingUsers); + updateTypingText() { + const users = Object.keys(this.typingUsers); + let text = ''; switch (users.length) { case 0: - return ''; + text = ''; + break; case 1: - return users[0] + ' is typing...'; + text = users[0] + ' is typing...'; + break; default: const last = users.pop(); - return users.join(', ') + ' and ' + last + ' are typing...'; + text = users.join(', ') + ' and ' + last + ' are typing...'; + break; } + + this.setState({text}); } render() { -- cgit v1.2.3-1-g7c22