Merge pull request #226 from matrix-org/matthew/fix-last-active

fix last_active_ago timestamps, tab completion ordering, and implement currently_active semantics
pull/21833/head
Matthew Hodgson 2016-03-17 14:36:52 +00:00
commit c51dac2f29
8 changed files with 33 additions and 23 deletions

View File

@ -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 {

View File

@ -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);

View File

@ -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())
)
);

View File

@ -38,6 +38,7 @@ module.exports = React.createClass({
className: React.PropTypes.string,
presenceState: React.PropTypes.string,
presenceActiveAgo: React.PropTypes.number,
presenceCurrentlyActive: React.PropTypes.bool,
showInviteButton: React.PropTypes.bool,
shouldComponentUpdate: React.PropTypes.func,
onClick: React.PropTypes.func,
@ -88,6 +89,7 @@ module.exports = React.createClass({
<img className="mx_EntityTile_chevron" src="img/member_chevron.png" width="8" height="12"/>
<div className="mx_EntityTile_name_hover">{ this.props.name }</div>
<PresenceLabel activeAgo={this.props.presenceActiveAgo}
currentlyActive={this.props.presenceCurrentlyActive}
presenceState={this.props.presenceState} />
</div>
);

View File

@ -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) {

View File

@ -84,14 +84,14 @@ 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();
return (
<EntityTile {...this.props} presenceActiveAgo={active} presenceState={presenceState}
presenceCurrentlyActive={ member.user ? member.user.currentlyActive : false }
avatarJsx={av} title={this.getPowerLabel()} onClick={this.onClick}
name={name} powerLevel={this.props.member.powerLevel} />
);

View File

@ -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
},
@ -67,9 +75,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 (
<div className="mx_PresenceLabel">
{ this.getPrettyPresence(this.props.presenceState) } { this.getDuration(this.props.activeAgo) } ago
{ this.getPrettyPresence(this.props.presenceState) } { ago }
</div>
);
}

View File

@ -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 = user.lastActiveAgo ?
(Date.now() - (user.lastPresenceTs - user.lastActiveAgo)) : -1;
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
var avatarJsx = (
@ -50,6 +49,7 @@ module.exports = React.createClass({
return (
<EntityTile {...this.props} presenceState={user.presence} presenceActiveAgo={active}
presenceCurrentlyActive={ user.currentlyActive }
name={name} title={user.userId} avatarJsx={avatarJsx} />
);
}