mirror of https://github.com/vector-im/riot-web
Rename
parent
999ebe6a19
commit
ce9f3d8a57
|
@ -34,8 +34,8 @@ const CURRENTLY_PASSIVE_THRESHOLD_MS = 2 * 60 * 1000;
|
||||||
* This class watches for user activity (moving the mouse or pressing a key)
|
* This class watches for user activity (moving the mouse or pressing a key)
|
||||||
* and starts/stops attached timers while the user is active.
|
* and starts/stops attached timers while the user is active.
|
||||||
*
|
*
|
||||||
* There are two classes of 'active' a user can be: 'active' and 'passive':
|
* There are two classes of 'active': 'active now' and 'active recently'
|
||||||
* see doc on the userCurrently* functions for what these mean.
|
* see doc on the userActive* functions for what these mean.
|
||||||
*/
|
*/
|
||||||
export default class UserActivity {
|
export default class UserActivity {
|
||||||
constructor(windowObj, documentObj) {
|
constructor(windowObj, documentObj) {
|
||||||
|
@ -44,8 +44,8 @@ export default class UserActivity {
|
||||||
|
|
||||||
this._attachedTimersActive = [];
|
this._attachedTimersActive = [];
|
||||||
this._attachedTimersPassive = [];
|
this._attachedTimersPassive = [];
|
||||||
this._activeTimeout = new Timer(CURRENTLY_ACTIVE_THRESHOLD_MS);
|
this._activeNowTimeout = new Timer(CURRENTLY_ACTIVE_THRESHOLD_MS);
|
||||||
this._passiveTimeout = new Timer(CURRENTLY_PASSIVE_THRESHOLD_MS);
|
this._activeRecentlyTimeout = new Timer(CURRENTLY_PASSIVE_THRESHOLD_MS);
|
||||||
this._onUserActivity = this._onUserActivity.bind(this);
|
this._onUserActivity = this._onUserActivity.bind(this);
|
||||||
this._onWindowBlurred = this._onWindowBlurred.bind(this);
|
this._onWindowBlurred = this._onWindowBlurred.bind(this);
|
||||||
this._onPageVisibilityChanged = this._onPageVisibilityChanged.bind(this);
|
this._onPageVisibilityChanged = this._onPageVisibilityChanged.bind(this);
|
||||||
|
@ -61,8 +61,9 @@ export default class UserActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the given timer while the user is 'active', aborting when the user becomes 'passive'.
|
* Runs the given timer while the user is 'active', aborting when the user is no longer
|
||||||
* See userCurrentlyActive() for what it means for a user to be 'active'.
|
* considered currently active.
|
||||||
|
* See userActiveNow() for what it means for a user to be 'active'.
|
||||||
* Can be called multiple times with the same already running timer, which is a NO-OP.
|
* Can be called multiple times with the same already running timer, which is a NO-OP.
|
||||||
* Can be called before the user becomes active, in which case it is only started
|
* Can be called before the user becomes active, in which case it is only started
|
||||||
* later on when the user does become active.
|
* later on when the user does become active.
|
||||||
|
@ -70,15 +71,15 @@ export default class UserActivity {
|
||||||
*/
|
*/
|
||||||
timeWhileActive(timer) {
|
timeWhileActive(timer) {
|
||||||
this._timeWhile(timer, this._attachedTimersActive);
|
this._timeWhile(timer, this._attachedTimersActive);
|
||||||
if (this.userCurrentlyActive()) {
|
if (this.userActiveNow()) {
|
||||||
timer.start();
|
timer.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the given timer while the user is 'active' or 'passive', aborting when the user becomes
|
* Runs the given timer while the user is 'active' now or recently,
|
||||||
* inactive.
|
* aborting when the user becomes inactive.
|
||||||
* See userCurrentlyPassive() for what it means for a user to be 'passive'.
|
* See userActiveRecently() for what it means for a user to be 'active recently'.
|
||||||
* Can be called multiple times with the same already running timer, which is a NO-OP.
|
* Can be called multiple times with the same already running timer, which is a NO-OP.
|
||||||
* Can be called before the user becomes active, in which case it is only started
|
* Can be called before the user becomes active, in which case it is only started
|
||||||
* later on when the user does become active.
|
* later on when the user does become active.
|
||||||
|
@ -86,7 +87,7 @@ export default class UserActivity {
|
||||||
*/
|
*/
|
||||||
timeWhilePassive(timer) {
|
timeWhilePassive(timer) {
|
||||||
this._timeWhile(timer, this._attachedTimersPassive);
|
this._timeWhile(timer, this._attachedTimersPassive);
|
||||||
if (this.userCurrentlyPassive()) {
|
if (this.userActiveRecently()) {
|
||||||
timer.start();
|
timer.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,33 +151,34 @@ export default class UserActivity {
|
||||||
* user's attention at any given moment.
|
* user's attention at any given moment.
|
||||||
* @returns {boolean} true if user is currently 'active'
|
* @returns {boolean} true if user is currently 'active'
|
||||||
*/
|
*/
|
||||||
userCurrentlyActive() {
|
userActiveNow() {
|
||||||
return this._activeTimeout.isRunning();
|
return this._activeNowTimeout.isRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the user is currently 'active' or 'passive'
|
* Return true if the user is currently active or has been recently
|
||||||
* A user is 'passive' for a longer period of time (~2 mins) after they have been 'active' and
|
* A user is 'active recently' for a longer period of time (~2 mins) after
|
||||||
* while the app still has the focus. This is intended to indicate when the app may still have
|
* they have been 'active' and while the app still has the focus. This is
|
||||||
* the user's attention (or they may have gone to make tea and left the window focused).
|
* intended to indicate when the app may still have the user's attention
|
||||||
* @returns {boolean} true if user is currently 'active' or 'passive'
|
* (or they may have gone to make tea and left the window focused).
|
||||||
|
* @returns {boolean} true if user has been active recently
|
||||||
*/
|
*/
|
||||||
userCurrentlyPassive() {
|
userActiveRecently() {
|
||||||
return this._passiveTimeout.isRunning();
|
return this._activeRecentlyTimeout.isRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPageVisibilityChanged(e) {
|
_onPageVisibilityChanged(e) {
|
||||||
if (this._document.visibilityState === "hidden") {
|
if (this._document.visibilityState === "hidden") {
|
||||||
this._activeTimeout.abort();
|
this._activeNowTimeout.abort();
|
||||||
this._passiveTimeout.abort();
|
this._activeRecentlyTimeout.abort();
|
||||||
} else {
|
} else {
|
||||||
this._onUserActivity(e);
|
this._onUserActivity(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onWindowBlurred() {
|
_onWindowBlurred() {
|
||||||
this._activeTimeout.abort();
|
this._activeNowTimeout.abort();
|
||||||
this._passiveTimeout.abort();
|
this._activeRecentlyTimeout.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onUserActivity(event) {
|
_onUserActivity(event) {
|
||||||
|
@ -193,21 +195,21 @@ export default class UserActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
dis.dispatch({action: 'user_activity'});
|
dis.dispatch({action: 'user_activity'});
|
||||||
if (!this._activeTimeout.isRunning()) {
|
if (!this._activeNowTimeout.isRunning()) {
|
||||||
this._activeTimeout.start();
|
this._activeNowTimeout.start();
|
||||||
dis.dispatch({action: 'user_activity_start'});
|
dis.dispatch({action: 'user_activity_start'});
|
||||||
|
|
||||||
this._runTimersUntilTimeout(this._attachedTimersActive, this._activeTimeout);
|
this._runTimersUntilTimeout(this._attachedTimersActive, this._activeNowTimeout);
|
||||||
} else {
|
} else {
|
||||||
this._activeTimeout.restart();
|
this._activeNowTimeout.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._passiveTimeout.isRunning()) {
|
if (!this._activeRecentlyTimeout.isRunning()) {
|
||||||
this._passiveTimeout.start();
|
this._activeRecentlyTimeout.start();
|
||||||
|
|
||||||
this._runTimersUntilTimeout(this._attachedTimersPassive, this._passiveTimeout);
|
this._runTimersUntilTimeout(this._attachedTimersPassive, this._activeRecentlyTimeout);
|
||||||
} else {
|
} else {
|
||||||
this._passiveTimeout.restart();
|
this._activeRecentlyTimeout.restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -451,12 +451,12 @@ var TimelinePanel = React.createClass({
|
||||||
//
|
//
|
||||||
// We ignore events we have sent ourselves; we don't want to see the
|
// We ignore events we have sent ourselves; we don't want to see the
|
||||||
// read-marker when a remote echo of an event we have just sent takes
|
// read-marker when a remote echo of an event we have just sent takes
|
||||||
// more than the timeout on userCurrentlyPassive.
|
// more than the timeout on userRecentlyActive.
|
||||||
//
|
//
|
||||||
const myUserId = MatrixClientPeg.get().credentials.userId;
|
const myUserId = MatrixClientPeg.get().credentials.userId;
|
||||||
const sender = ev.sender ? ev.sender.userId : null;
|
const sender = ev.sender ? ev.sender.userId : null;
|
||||||
var callRMUpdated = false;
|
var callRMUpdated = false;
|
||||||
if (sender != myUserId && !UserActivity.sharedInstance().userCurrentlyPassive()) {
|
if (sender != myUserId && !UserActivity.sharedInstance().userRecentlyActive()) {
|
||||||
updatedState.readMarkerVisible = true;
|
updatedState.readMarkerVisible = true;
|
||||||
} else if (lastEv && this.getReadMarkerPosition() === 0) {
|
} else if (lastEv && this.getReadMarkerPosition() === 0) {
|
||||||
// we know we're stuckAtBottom, so we can advance the RM
|
// we know we're stuckAtBottom, so we can advance the RM
|
||||||
|
|
|
@ -56,30 +56,30 @@ describe('UserActivity', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should consider user inactive if no activity', function() {
|
it('should consider user inactive if no activity', function() {
|
||||||
expect(userActivity.userCurrentlyActive()).toBe(false);
|
expect(userActivity.userActiveNow()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should consider user not passive if no activity', function() {
|
it('should consider user not active recently if no activity', function() {
|
||||||
expect(userActivity.userCurrentlyPassive()).toBe(false);
|
expect(userActivity.userActiveRecently()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not consider user active after activity if no window focus', function() {
|
it('should not consider user active after activity if no window focus', function() {
|
||||||
fakeDocument.hasFocus = jest.fn().mockReturnValue(false);
|
fakeDocument.hasFocus = jest.fn().mockReturnValue(false);
|
||||||
|
|
||||||
userActivity._onUserActivity({});
|
userActivity._onUserActivity({});
|
||||||
expect(userActivity.userCurrentlyActive()).toBe(false);
|
expect(userActivity.userActiveNow()).toBe(false);
|
||||||
expect(userActivity.userCurrentlyPassive()).toBe(false);
|
expect(userActivity.userActiveRecently()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should consider user active shortly after activity', function() {
|
it('should consider user active shortly after activity', function() {
|
||||||
fakeDocument.hasFocus = jest.fn().mockReturnValue(true);
|
fakeDocument.hasFocus = jest.fn().mockReturnValue(true);
|
||||||
|
|
||||||
userActivity._onUserActivity({});
|
userActivity._onUserActivity({});
|
||||||
expect(userActivity.userCurrentlyActive()).toBe(true);
|
expect(userActivity.userActiveNow()).toBe(true);
|
||||||
expect(userActivity.userCurrentlyPassive()).toBe(true);
|
expect(userActivity.userActiveRecently()).toBe(true);
|
||||||
clock.tick(200);
|
clock.tick(200);
|
||||||
expect(userActivity.userCurrentlyActive()).toBe(true);
|
expect(userActivity.userActiveNow()).toBe(true);
|
||||||
expect(userActivity.userCurrentlyPassive()).toBe(true);
|
expect(userActivity.userActiveRecently()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should consider user not active after 10s of no activity', function() {
|
it('should consider user not active after 10s of no activity', function() {
|
||||||
|
@ -87,7 +87,7 @@ describe('UserActivity', function() {
|
||||||
|
|
||||||
userActivity._onUserActivity({});
|
userActivity._onUserActivity({});
|
||||||
clock.tick(10000);
|
clock.tick(10000);
|
||||||
expect(userActivity.userCurrentlyActive()).toBe(false);
|
expect(userActivity.userActiveNow()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should consider user passive after 10s of no activity', function() {
|
it('should consider user passive after 10s of no activity', function() {
|
||||||
|
@ -95,7 +95,7 @@ describe('UserActivity', function() {
|
||||||
|
|
||||||
userActivity._onUserActivity({});
|
userActivity._onUserActivity({});
|
||||||
clock.tick(10000);
|
clock.tick(10000);
|
||||||
expect(userActivity.userCurrentlyPassive()).toBe(true);
|
expect(userActivity.userActiveRecently()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not consider user passive after 10s if window un-focused', function() {
|
it('should not consider user passive after 10s if window un-focused', function() {
|
||||||
|
@ -107,7 +107,7 @@ describe('UserActivity', function() {
|
||||||
fakeDocument.hasFocus = jest.fn().mockReturnValue(false);
|
fakeDocument.hasFocus = jest.fn().mockReturnValue(false);
|
||||||
fakeWindow.emit('blur', {});
|
fakeWindow.emit('blur', {});
|
||||||
|
|
||||||
expect(userActivity.userCurrentlyPassive()).toBe(false);
|
expect(userActivity.userActiveRecently()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not consider user passive after 3 mins', function() {
|
it('should not consider user passive after 3 mins', function() {
|
||||||
|
@ -116,7 +116,7 @@ describe('UserActivity', function() {
|
||||||
userActivity._onUserActivity({});
|
userActivity._onUserActivity({});
|
||||||
clock.tick(3 * 60 * 1000);
|
clock.tick(3 * 60 * 1000);
|
||||||
|
|
||||||
expect(userActivity.userCurrentlyPassive()).toBe(false);
|
expect(userActivity.userActiveRecently()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should extend timer on activity', function() {
|
it('should extend timer on activity', function() {
|
||||||
|
@ -129,6 +129,6 @@ describe('UserActivity', function() {
|
||||||
userActivity._onUserActivity({});
|
userActivity._onUserActivity({});
|
||||||
clock.tick(1 * 60 * 1000);
|
clock.tick(1 * 60 * 1000);
|
||||||
|
|
||||||
expect(userActivity.userCurrentlyPassive()).toBe(true);
|
expect(userActivity.userActiveRecently()).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue