From 2265d1a82af5b9d36ff2ccaf793c32596b3fca7f Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 16 Mar 2016 22:25:57 +0000 Subject: [PATCH 1/9] fix display of null last_active_ago timestamps --- src/components/views/rooms/MemberTile.js | 5 ++--- src/components/views/rooms/UserTile.js | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.js index d5c124ad21..89f4e35805 100644 --- a/src/components/views/rooms/MemberTile.js +++ b/src/components/views/rooms/MemberTile.js @@ -84,9 +84,8 @@ module.exports = React.createClass({ this.user_last_modified_time = member.user.getLastModifiedTime(); // FIXME: make presence data update whenever User.presence changes... - active = ( - (Date.now() - (member.user.lastPresenceTs - member.user.lastActiveAgo)) || -1 - ); + active = member.user.lastActiveAgo ? + (Date.now() - (member.user.lastPresenceTs - member.user.lastActiveAgo)) : -1; } this.member_last_modified_time = member.getLastModifiedTime(); diff --git a/src/components/views/rooms/UserTile.js b/src/components/views/rooms/UserTile.js index 6597796764..26b9df7e38 100644 --- a/src/components/views/rooms/UserTile.js +++ b/src/components/views/rooms/UserTile.js @@ -38,9 +38,8 @@ module.exports = React.createClass({ var active = -1; // FIXME: make presence data update whenever User.presence changes... - active = ( - (Date.now() - (user.lastPresenceTs - user.lastActiveAgo)) || -1 - ); + active = member.user.lastActiveAgo ? + (Date.now() - (member.user.lastPresenceTs - member.user.lastActiveAgo)) : -1; var BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); var avatarJsx = ( From ce833c9bba8bf637646c1cde23f491df54849218 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 16 Mar 2016 22:26:20 +0000 Subject: [PATCH 2/9] deobfuscate last_active_ago ordering --- src/components/views/rooms/MemberList.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js index cc2983290b..dadc0407c1 100644 --- a/src/components/views/rooms/MemberList.js +++ b/src/components/views/rooms/MemberList.js @@ -317,10 +317,10 @@ module.exports = React.createClass({ return presenceOrdB - presenceOrdA; } - var latA = userA ? (userA.lastPresenceTs - (userA.lastActiveAgo || userA.lastPresenceTs)) : 0; - var latB = userB ? (userB.lastPresenceTs - (userB.lastActiveAgo || userB.lastPresenceTs)) : 0; - - return latB - latA; + var lastActiveTsA = userA && userA.lastActiveAgo ? userA.lastPresenceTs - userA.lastActiveAgo : 0; + var lastActiveTsB = userB && userB.lastActiveAgo ? userB.lastPresenceTs - userB.lastActiveAgo : 0; + + return lastActiveTsB - lastActiveTsA; }, onSearchQueryChanged: function(input) { From 58d46825ce67b9c8950436da0d9588e8138c9329 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 16 Mar 2016 22:27:09 +0000 Subject: [PATCH 3/9] take null last_active_ago values into account correctly when ordering tab complete --- src/TabCompleteEntries.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/TabCompleteEntries.js b/src/TabCompleteEntries.js index 9aef7736a8..a23050063f 100644 --- a/src/TabCompleteEntries.js +++ b/src/TabCompleteEntries.js @@ -127,15 +127,9 @@ MemberEntry.fromMemberList = function(members) { return 0; // don't care } else { // both User objects exist - if (userA.lastActiveAgo < userB.lastActiveAgo) { - return -1; // a comes first - } - else if (userA.lastActiveAgo > userB.lastActiveAgo) { - return 1; // b comes first - } - else { - return 0; // same last active ago - } + var lastActiveAgoA = userA.lastActiveAgo || Number.MAX_SAFE_INTEGER; + var lastActiveAgoB = userB.lastActiveAgo || Number.MAX_SAFE_INTEGER; + return lastActiveAgoA - lastActiveAgoB; } }).map(function(m) { return new MemberEntry(m); From 500b88dc36c1c0373eedcd792bc0c6d22a95350a Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 16 Mar 2016 22:44:54 +0000 Subject: [PATCH 4/9] implement currently_active --- src/components/views/rooms/EntityTile.js | 1 + src/components/views/rooms/MemberTile.js | 1 + src/components/views/rooms/PresenceLabel.js | 3 ++- src/components/views/rooms/UserTile.js | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/EntityTile.js b/src/components/views/rooms/EntityTile.js index ec586431be..61ad43e9c4 100644 --- a/src/components/views/rooms/EntityTile.js +++ b/src/components/views/rooms/EntityTile.js @@ -88,6 +88,7 @@ module.exports = React.createClass({
{ this.props.name }
); diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.js index 89f4e35805..57cb7232d4 100644 --- a/src/components/views/rooms/MemberTile.js +++ b/src/components/views/rooms/MemberTile.js @@ -91,6 +91,7 @@ module.exports = React.createClass({ return ( diff --git a/src/components/views/rooms/PresenceLabel.js b/src/components/views/rooms/PresenceLabel.js index 4ecad5b3df..f3315de80c 100644 --- a/src/components/views/rooms/PresenceLabel.js +++ b/src/components/views/rooms/PresenceLabel.js @@ -67,9 +67,10 @@ module.exports = React.createClass({ render: function() { if (this.props.activeAgo >= 0) { + var ago = this.props.currentlyActive ? "now" : (this.getDuration(this.props.activeAgo) + " ago"); return (
- { this.getPrettyPresence(this.props.presenceState) } { this.getDuration(this.props.activeAgo) } ago + { this.getPrettyPresence(this.props.presenceState) } { ago }
); } diff --git a/src/components/views/rooms/UserTile.js b/src/components/views/rooms/UserTile.js index 26b9df7e38..fe7e95a02a 100644 --- a/src/components/views/rooms/UserTile.js +++ b/src/components/views/rooms/UserTile.js @@ -49,6 +49,7 @@ module.exports = React.createClass({ return ( ); } From e7ec6166fa4b70d0d0e15056d00a90665343548f Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 16 Mar 2016 23:11:07 +0000 Subject: [PATCH 5/9] allow tab-complete to start from a blank text-input. this lets us autocomplete based on the most recently active users in a room, even if we can't spell the first char of their name. it does break tab-complete for accessibility, but that was broken anyway. --- src/TabComplete.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TabComplete.js b/src/TabComplete.js index 8886e21af9..3005411e13 100644 --- a/src/TabComplete.js +++ b/src/TabComplete.js @@ -24,10 +24,10 @@ const KEY_WINDOWS = 91; // // Capturing group containing the start // of line or a whitespace char -// \_______________ __________Capturing group of 1 or more non-whitespace chars +// \_______________ __________Capturing group of 0 or more non-whitespace chars // _|__ _|_ followed by the end of line // / \/ \ -const MATCH_REGEX = /(^|\s)(\S+)$/; +const MATCH_REGEX = /(^|\s)(\S*)$/; class TabComplete { From 50e33d30b6b87f1f5743a76c67a862357955f779 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 16 Mar 2016 23:35:01 +0000 Subject: [PATCH 6/9] never try to tab-complete yourself, doofus --- src/components/structures/RoomView.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index dcb16f7231..65dd9534d7 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -455,11 +455,16 @@ module.exports = React.createClass({ }, _updateTabCompleteList: new rate_limited_func(function() { + var cli = MatrixClientPeg.get(); + if (!this.state.room || !this.tabComplete) { return; } + var members = this.state.room.getJoinedMembers().filter(function(member) { + if (member.userId !== cli.credentials.userId) return true; + }); this.tabComplete.setCompletionList( - MemberEntry.fromMemberList(this.state.room.getJoinedMembers()).concat( + MemberEntry.fromMemberList(members).concat( CommandEntry.fromCommands(SlashCommands.getCommandList()) ) ); From 6acfc8f5087240de8c98f7eb5b0a73984b391cad Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Thu, 17 Mar 2016 00:06:53 +0000 Subject: [PATCH 7/9] comment currentlyActive --- src/components/views/rooms/EntityTile.js | 1 + src/components/views/rooms/PresenceLabel.js | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/components/views/rooms/EntityTile.js b/src/components/views/rooms/EntityTile.js index 61ad43e9c4..a525f9ac24 100644 --- a/src/components/views/rooms/EntityTile.js +++ b/src/components/views/rooms/EntityTile.js @@ -38,6 +38,7 @@ module.exports = React.createClass({ className: React.PropTypes.string, presenceState: React.PropTypes.string, presenceActiveAgo: React.PropTypes.number, + currentlyActive: React.PropTypes.bool, showInviteButton: React.PropTypes.bool, shouldComponentUpdate: React.PropTypes.func, onClick: React.PropTypes.func, diff --git a/src/components/views/rooms/PresenceLabel.js b/src/components/views/rooms/PresenceLabel.js index f3315de80c..ac0410c1f7 100644 --- a/src/components/views/rooms/PresenceLabel.js +++ b/src/components/views/rooms/PresenceLabel.js @@ -25,7 +25,15 @@ module.exports = React.createClass({ displayName: 'PresenceLabel', propTypes: { + // number of milliseconds ago this user was last active. + // zero = unknown activeAgo: React.PropTypes.number, + + // if true, activeAgo is an approximation and "Now" should + // be shown instead + currentlyActive: React.PropTypes.bool, + + // offline, online, etc presenceState: React.PropTypes.string }, From 11a146ed4207793f1ea48229fe7296490fd23dd5 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Thu, 17 Mar 2016 00:07:30 +0000 Subject: [PATCH 8/9] oops --- src/components/views/rooms/EntityTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/EntityTile.js b/src/components/views/rooms/EntityTile.js index a525f9ac24..47e3fd3350 100644 --- a/src/components/views/rooms/EntityTile.js +++ b/src/components/views/rooms/EntityTile.js @@ -38,7 +38,7 @@ module.exports = React.createClass({ className: React.PropTypes.string, presenceState: React.PropTypes.string, presenceActiveAgo: React.PropTypes.number, - currentlyActive: React.PropTypes.bool, + presenceCurrentlyActive: React.PropTypes.bool, showInviteButton: React.PropTypes.bool, shouldComponentUpdate: React.PropTypes.func, onClick: React.PropTypes.func, From 84278a4ed450a47492bf6aac31157537d96bae1c Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Thu, 17 Mar 2016 11:37:26 +0000 Subject: [PATCH 9/9] fix copy-paste bug caught by PR review --- src/components/views/rooms/UserTile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/UserTile.js b/src/components/views/rooms/UserTile.js index fe7e95a02a..9608247d5e 100644 --- a/src/components/views/rooms/UserTile.js +++ b/src/components/views/rooms/UserTile.js @@ -38,8 +38,8 @@ module.exports = React.createClass({ var active = -1; // FIXME: make presence data update whenever User.presence changes... - active = member.user.lastActiveAgo ? - (Date.now() - (member.user.lastPresenceTs - member.user.lastActiveAgo)) : -1; + active = user.lastActiveAgo ? + (Date.now() - (user.lastPresenceTs - user.lastActiveAgo)) : -1; var BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); var avatarJsx = (