mirror of https://github.com/vector-im/riot-web
Use Timer & new UserActivity api in Presence.
The only behaviour that should have changed here is that presence is also set to online when switching back to the tab/window. Presence is not set to unavailable when coming back to the window/tab, as that might be a bit invasive, but only when timing out.pull/21833/head
parent
6a248c2e72
commit
7f6d581377
|
@ -17,21 +17,33 @@ limitations under the License.
|
||||||
|
|
||||||
const MatrixClientPeg = require("./MatrixClientPeg");
|
const MatrixClientPeg = require("./MatrixClientPeg");
|
||||||
const dis = require("./dispatcher");
|
const dis = require("./dispatcher");
|
||||||
|
import Timer from './utils/Timer';
|
||||||
|
|
||||||
// Time in ms after that a user is considered as unavailable/away
|
// Time in ms after that a user is considered as unavailable/away
|
||||||
const UNAVAILABLE_TIME_MS = 3 * 60 * 1000; // 3 mins
|
const UNAVAILABLE_TIME_MS = 3 * 60 * 1000; // 3 mins
|
||||||
const PRESENCE_STATES = ["online", "offline", "unavailable"];
|
const PRESENCE_STATES = ["online", "offline", "unavailable"];
|
||||||
|
|
||||||
class Presence {
|
class Presence {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._activitySignal = null;
|
||||||
|
this._unavailableTimer = null;
|
||||||
|
this._onAction = this._onAction.bind(this);
|
||||||
|
this._dispatcherRef = null;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Start listening the user activity to evaluate his presence state.
|
* Start listening the user activity to evaluate his presence state.
|
||||||
* Any state change will be sent to the Home Server.
|
* Any state change will be sent to the Home Server.
|
||||||
*/
|
*/
|
||||||
start() {
|
async start() {
|
||||||
this.running = true;
|
this._unavailableTimer = new Timer(UNAVAILABLE_TIME_MS);
|
||||||
if (undefined === this.state) {
|
// the user_activity_start action starts the timer
|
||||||
this._resetTimer();
|
this._dispatcherRef = dis.register(this._onAction);
|
||||||
this.dispatcherRef = dis.register(this._onAction.bind(this));
|
while (this._unavailableTimer) {
|
||||||
|
try {
|
||||||
|
await this._unavailableTimer.finished();
|
||||||
|
this.setState("unavailable");
|
||||||
|
} catch(e) { /* aborted, stop got called */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,13 +51,14 @@ class Presence {
|
||||||
* Stop tracking user activity
|
* Stop tracking user activity
|
||||||
*/
|
*/
|
||||||
stop() {
|
stop() {
|
||||||
this.running = false;
|
if (this._dispatcherRef) {
|
||||||
if (this.timer) {
|
dis.unregister(this._dispatcherRef);
|
||||||
clearInterval(this.timer);
|
this._dispatcherRef = null;
|
||||||
this.timer = undefined;
|
}
|
||||||
dis.unregister(this.dispatcherRef);
|
if (this._unavailableTimer) {
|
||||||
|
this._unavailableTimer.abort();
|
||||||
|
this._unavailableTimer = null;
|
||||||
}
|
}
|
||||||
this.state = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,21 +69,26 @@ class Presence {
|
||||||
return this.state;
|
return this.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onAction(payload) {
|
||||||
|
if (payload.action === 'user_activity_start') {
|
||||||
|
this.setState("online");
|
||||||
|
this._unavailableTimer.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the presence state.
|
* Set the presence state.
|
||||||
* If the state has changed, the Home Server will be notified.
|
* If the state has changed, the Home Server will be notified.
|
||||||
* @param {string} newState the new presence state (see PRESENCE enum)
|
* @param {string} newState the new presence state (see PRESENCE enum)
|
||||||
*/
|
*/
|
||||||
setState(newState) {
|
async setState(newState) {
|
||||||
|
console.log("setting Presence state!!", newState);
|
||||||
if (newState === this.state) {
|
if (newState === this.state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (PRESENCE_STATES.indexOf(newState) === -1) {
|
if (PRESENCE_STATES.indexOf(newState) === -1) {
|
||||||
throw new Error("Bad presence state: " + newState);
|
throw new Error("Bad presence state: " + newState);
|
||||||
}
|
}
|
||||||
if (!this.running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const old_state = this.state;
|
const old_state = this.state;
|
||||||
this.state = newState;
|
this.state = newState;
|
||||||
|
|
||||||
|
@ -78,42 +96,14 @@ class Presence {
|
||||||
return; // don't try to set presence when a guest; it won't work.
|
return; // don't try to set presence when a guest; it won't work.
|
||||||
}
|
}
|
||||||
|
|
||||||
const self = this;
|
try {
|
||||||
MatrixClientPeg.get().setPresence(this.state).done(function() {
|
await MatrixClientPeg.get().setPresence(this.state);
|
||||||
console.log("Presence: %s", newState);
|
console.log("Presence: %s", newState);
|
||||||
}, function(err) {
|
} catch(err) {
|
||||||
console.error("Failed to set presence: %s", err);
|
console.error("Failed to set presence: %s", err);
|
||||||
self.state = old_state;
|
this.state = old_state;
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback called when the user made no action on the page for UNAVAILABLE_TIME ms.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_onUnavailableTimerFire() {
|
|
||||||
this.setState("unavailable");
|
|
||||||
}
|
|
||||||
|
|
||||||
_onAction(payload) {
|
|
||||||
if (payload.action === "user_activity") {
|
|
||||||
this._resetTimer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback called when the user made an action on the page
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_resetTimer() {
|
|
||||||
const self = this;
|
|
||||||
this.setState("online");
|
|
||||||
// Re-arm the timer
|
|
||||||
clearTimeout(this.timer);
|
|
||||||
this.timer = setTimeout(function() {
|
|
||||||
self._onUnavailableTimerFire();
|
|
||||||
}, UNAVAILABLE_TIME_MS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new Presence();
|
module.exports = new Presence();
|
||||||
|
|
Loading…
Reference in New Issue