Commit 5a556dd5 authored by JC Brand's avatar JC Brand Committed by GitHub

Merge pull request #1319 from ChaosKid42/implement_last_user_interaction_in_presence

Send presences according to XEP-0319: Last User Interaction in Presence
parents 4b7d18f4 45c47ab2
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
- #1305 added value 'all' for 'show_desktop_notifications' to notifiy even if converse.js is open - #1305 added value 'all' for 'show_desktop_notifications' to notifiy even if converse.js is open
- #1312 Error `unrecognized expression` in Safari - #1312 Error `unrecognized expression` in Safari
- #1318 added values 'on' and 'off' for 'trusted' option which removes the "This is a trusted device" checkbox from the login form - #1318 added values 'on' and 'off' for 'trusted' option which removes the "This is a trusted device" checkbox from the login form
- #1319 Implement sending of presences according to XEP-0319: Last User Interaction in Presence
## 4.0.4 (2018-10-29) ## 4.0.4 (2018-10-29)
......
...@@ -71780,6 +71780,7 @@ strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('DELAY', 'urn:xm ...@@ -71780,6 +71780,7 @@ strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('DELAY', 'urn:xm
strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('FORWARD', 'urn:xmpp:forward:0'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('FORWARD', 'urn:xmpp:forward:0');
strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('HINTS', 'urn:xmpp:hints'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('HINTS', 'urn:xmpp:hints');
strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('HTTPUPLOAD', 'urn:xmpp:http:upload:0'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('HTTPUPLOAD', 'urn:xmpp:http:upload:0');
strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('IDLE', 'urn:xmpp:idle:1');
strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('MAM', 'urn:xmpp:mam:2'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('MAM', 'urn:xmpp:mam:2');
strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('NICK', 'http://jabber.org/protocol/nick'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('NICK', 'http://jabber.org/protocol/nick');
strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('OMEMO', "eu.siacs.conversations.axolotl"); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('OMEMO', "eu.siacs.conversations.axolotl");
...@@ -71931,6 +71932,8 @@ _converse.default_settings = { ...@@ -71931,6 +71932,8 @@ _converse.default_settings = {
expose_rid_and_sid: false, expose_rid_and_sid: false,
geouri_regex: /https:\/\/www.openstreetmap.org\/.*#map=[0-9]+\/([\-0-9.]+)\/([\-0-9.]+)\S*/g, geouri_regex: /https:\/\/www.openstreetmap.org\/.*#map=[0-9]+\/([\-0-9.]+)\/([\-0-9.]+)\S*/g,
geouri_replacement: 'https://www.openstreetmap.org/?mlat=$1&mlon=$2#map=18/$1/$2', geouri_replacement: 'https://www.openstreetmap.org/?mlat=$1&mlon=$2#map=18/$1/$2',
idle_presence_timeout: 300,
// Seconds after which an idle presence is sent
jid: undefined, jid: undefined,
keepalive: true, keepalive: true,
locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json', locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
...@@ -72166,6 +72169,12 @@ _converse.initialize = function (settings, callback) { ...@@ -72166,6 +72169,12 @@ _converse.initialize = function (settings, callback) {
_converse.sendCSI(_converse.ACTIVE); _converse.sendCSI(_converse.ACTIVE);
} }
if (_converse.idle) {
_converse.idle = false;
_converse.xmppstatus.sendPresence();
}
if (_converse.auto_changed_status === true) { if (_converse.auto_changed_status === true) {
_converse.auto_changed_status = false; // XXX: we should really remember the original state here, and _converse.auto_changed_status = false; // XXX: we should really remember the original state here, and
// then set it back to that... // then set it back to that...
...@@ -72192,6 +72201,12 @@ _converse.initialize = function (settings, callback) { ...@@ -72192,6 +72201,12 @@ _converse.initialize = function (settings, callback) {
_converse.sendCSI(_converse.INACTIVE); _converse.sendCSI(_converse.INACTIVE);
} }
if (_converse.idle_presence_timeout > 0 && _converse.idle_seconds > _converse.idle_presence_timeout && !_converse.idle) {
_converse.idle = true;
_converse.xmppstatus.sendPresence();
}
if (_converse.auto_away > 0 && _converse.idle_seconds > _converse.auto_away && stat !== 'away' && stat !== 'xa' && stat !== 'dnd') { if (_converse.auto_away > 0 && _converse.idle_seconds > _converse.auto_away && stat !== 'away' && stat !== 'xa' && stat !== 'dnd') {
_converse.auto_changed_status = true; _converse.auto_changed_status = true;
...@@ -72207,7 +72222,7 @@ _converse.initialize = function (settings, callback) { ...@@ -72207,7 +72222,7 @@ _converse.initialize = function (settings, callback) {
/* Set an interval of one second and register a handler for it. /* Set an interval of one second and register a handler for it.
* Required for the auto_away, auto_xa and csi_waiting_time features. * Required for the auto_away, auto_xa and csi_waiting_time features.
*/ */
if (_converse.auto_away < 1 && _converse.auto_xa < 1 && _converse.csi_waiting_time < 1) { if (_converse.auto_away < 1 && _converse.auto_xa < 1 && _converse.csi_waiting_time < 1 && _converse.idle_presence_timeout < 1) {
// Waiting time of less then one second means features aren't used. // Waiting time of less then one second means features aren't used.
return; return;
} }
...@@ -72707,7 +72722,17 @@ _converse.initialize = function (settings, callback) { ...@@ -72707,7 +72722,17 @@ _converse.initialize = function (settings, callback) {
presence.c('status').t(status_message).up(); presence.c('status').t(status_message).up();
} }
presence.c('priority').t(_lodash_noconflict__WEBPACK_IMPORTED_MODULE_4___default.a.isNaN(Number(_converse.priority)) ? 0 : _converse.priority); presence.c('priority').t(_lodash_noconflict__WEBPACK_IMPORTED_MODULE_4___default.a.isNaN(Number(_converse.priority)) ? 0 : _converse.priority).up();
if (_converse.idle) {
const idle_since = new Date();
idle_since.setSeconds(idle_since.getSeconds() - _converse.idle_seconds);
presence.c('idle', {
xmlns: strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].NS.IDLE,
since: idle_since.toISOString()
});
}
return presence; return presence;
}, },
...@@ -73015,6 +73040,12 @@ _converse.initialize = function (settings, callback) { ...@@ -73015,6 +73040,12 @@ _converse.initialize = function (settings, callback) {
if (!Backbone.history.started) { if (!Backbone.history.started) {
Backbone.history.start(); Backbone.history.start();
} }
if (_converse.idle_presence_timeout > 0) {
_converse.on('addClientFeatures', () => {
_converse.api.disco.own.features.add(strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].NS.IDLE);
});
}
} }
if (!_lodash_noconflict__WEBPACK_IMPORTED_MODULE_4___default.a.isUndefined(_converse.connection) && _converse.connection.service === 'jasmine tests') { if (!_lodash_noconflict__WEBPACK_IMPORTED_MODULE_4___default.a.isUndefined(_converse.connection) && _converse.connection.service === 'jasmine tests') {
...@@ -757,6 +757,16 @@ then Converse will fall back to trying to determine the browser's language ...@@ -757,6 +757,16 @@ then Converse will fall back to trying to determine the browser's language
and fetching those translations, or if that fails the default English texts and fetching those translations, or if that fails the default English texts
will be used. will be used.
idle_presence_timeout
---------------------
* Default: ``300``
The amount of seconds after which the user is considered to be idle
and an idle presence according to XEP-0319 is sent.
If the given value is negative or ``0``, this feature is disabled.
jid jid
--- ---
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
`<presence xmlns="jabber:client">`+ `<presence xmlns="jabber:client">`+
`<status>Hello world</status>`+ `<status>Hello world</status>`+
`<priority>0</priority>`+ `<priority>0</priority>`+
`<c hash="sha-1" node="https://conversejs.org" ver="K7kn/M6VtmdMyo61pgn/jkZlax8=" xmlns="http://jabber.org/protocol/caps"/>`+ `<c hash="sha-1" node="https://conversejs.org" ver="Hxbsr5fazs62i+O0GxIXf2OEDNs=" xmlns="http://jabber.org/protocol/caps"/>`+
`</presence>` `</presence>`
); );
_converse.priority = 2; _converse.priority = 2;
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
`<show>away</show>`+ `<show>away</show>`+
`<status>Going jogging</status>`+ `<status>Going jogging</status>`+
`<priority>2</priority>`+ `<priority>2</priority>`+
`<c hash="sha-1" node="https://conversejs.org" ver="K7kn/M6VtmdMyo61pgn/jkZlax8=" xmlns="http://jabber.org/protocol/caps"/>`+ `<c hash="sha-1" node="https://conversejs.org" ver="Hxbsr5fazs62i+O0GxIXf2OEDNs=" xmlns="http://jabber.org/protocol/caps"/>`+
`</presence>` `</presence>`
); );
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
`<show>dnd</show>`+ `<show>dnd</show>`+
`<status>Doing taxes</status>`+ `<status>Doing taxes</status>`+
`<priority>0</priority>`+ `<priority>0</priority>`+
`<c hash="sha-1" node="https://conversejs.org" ver="K7kn/M6VtmdMyo61pgn/jkZlax8=" xmlns="http://jabber.org/protocol/caps"/>`+ `<c hash="sha-1" node="https://conversejs.org" ver="Hxbsr5fazs62i+O0GxIXf2OEDNs=" xmlns="http://jabber.org/protocol/caps"/>`+
`</presence>` `</presence>`
); );
})); }));
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
.toBe(`<presence xmlns="jabber:client">`+ .toBe(`<presence xmlns="jabber:client">`+
`<status>My custom status</status>`+ `<status>My custom status</status>`+
`<priority>0</priority>`+ `<priority>0</priority>`+
`<c hash="sha-1" node="https://conversejs.org" ver="K7kn/M6VtmdMyo61pgn/jkZlax8=" xmlns="http://jabber.org/protocol/caps"/>`+ `<c hash="sha-1" node="https://conversejs.org" ver="Hxbsr5fazs62i+O0GxIXf2OEDNs=" xmlns="http://jabber.org/protocol/caps"/>`+
`</presence>`) `</presence>`)
return test_utils.waitUntil(() => modal.el.getAttribute('aria-hidden') === "true"); return test_utils.waitUntil(() => modal.el.getAttribute('aria-hidden') === "true");
...@@ -109,7 +109,7 @@ ...@@ -109,7 +109,7 @@
modal.el.querySelector('[type="submit"]').click(); modal.el.querySelector('[type="submit"]').click();
expect(_converse.connection.send.calls.mostRecent().args[0].toLocaleString()) expect(_converse.connection.send.calls.mostRecent().args[0].toLocaleString())
.toBe(`<presence xmlns="jabber:client"><show>dnd</show><status>My custom status</status><priority>0</priority>`+ .toBe(`<presence xmlns="jabber:client"><show>dnd</show><status>My custom status</status><priority>0</priority>`+
`<c hash="sha-1" node="https://conversejs.org" ver="K7kn/M6VtmdMyo61pgn/jkZlax8=" xmlns="http://jabber.org/protocol/caps"/>`+ `<c hash="sha-1" node="https://conversejs.org" ver="Hxbsr5fazs62i+O0GxIXf2OEDNs=" xmlns="http://jabber.org/protocol/caps"/>`+
`</presence>`) `</presence>`)
done(); done();
}); });
......
...@@ -32,6 +32,7 @@ Strophe.addNamespace('DELAY', 'urn:xmpp:delay'); ...@@ -32,6 +32,7 @@ Strophe.addNamespace('DELAY', 'urn:xmpp:delay');
Strophe.addNamespace('FORWARD', 'urn:xmpp:forward:0'); Strophe.addNamespace('FORWARD', 'urn:xmpp:forward:0');
Strophe.addNamespace('HINTS', 'urn:xmpp:hints'); Strophe.addNamespace('HINTS', 'urn:xmpp:hints');
Strophe.addNamespace('HTTPUPLOAD', 'urn:xmpp:http:upload:0'); Strophe.addNamespace('HTTPUPLOAD', 'urn:xmpp:http:upload:0');
Strophe.addNamespace('IDLE', 'urn:xmpp:idle:1');
Strophe.addNamespace('MAM', 'urn:xmpp:mam:2'); Strophe.addNamespace('MAM', 'urn:xmpp:mam:2');
Strophe.addNamespace('NICK', 'http://jabber.org/protocol/nick'); Strophe.addNamespace('NICK', 'http://jabber.org/protocol/nick');
Strophe.addNamespace('OMEMO', "eu.siacs.conversations.axolotl"); Strophe.addNamespace('OMEMO', "eu.siacs.conversations.axolotl");
...@@ -197,6 +198,7 @@ _converse.default_settings = { ...@@ -197,6 +198,7 @@ _converse.default_settings = {
expose_rid_and_sid: false, expose_rid_and_sid: false,
geouri_regex: /https:\/\/www.openstreetmap.org\/.*#map=[0-9]+\/([\-0-9.]+)\/([\-0-9.]+)\S*/g, geouri_regex: /https:\/\/www.openstreetmap.org\/.*#map=[0-9]+\/([\-0-9.]+)\/([\-0-9.]+)\S*/g,
geouri_replacement: 'https://www.openstreetmap.org/?mlat=$1&mlon=$2#map=18/$1/$2', geouri_replacement: 'https://www.openstreetmap.org/?mlat=$1&mlon=$2#map=18/$1/$2',
idle_presence_timeout: 300, // Seconds after which an idle presence is sent
jid: undefined, jid: undefined,
keepalive: true, keepalive: true,
locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json', locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
...@@ -416,6 +418,10 @@ _converse.initialize = function (settings, callback) { ...@@ -416,6 +418,10 @@ _converse.initialize = function (settings, callback) {
if (_converse.inactive) { if (_converse.inactive) {
_converse.sendCSI(_converse.ACTIVE); _converse.sendCSI(_converse.ACTIVE);
} }
if (_converse.idle) {
_converse.idle = false;
_converse.xmppstatus.sendPresence();
}
if (_converse.auto_changed_status === true) { if (_converse.auto_changed_status === true) {
_converse.auto_changed_status = false; _converse.auto_changed_status = false;
// XXX: we should really remember the original state here, and // XXX: we should really remember the original state here, and
...@@ -440,6 +446,12 @@ _converse.initialize = function (settings, callback) { ...@@ -440,6 +446,12 @@ _converse.initialize = function (settings, callback) {
!_converse.inactive) { !_converse.inactive) {
_converse.sendCSI(_converse.INACTIVE); _converse.sendCSI(_converse.INACTIVE);
} }
if (_converse.idle_presence_timeout > 0 &&
_converse.idle_seconds > _converse.idle_presence_timeout &&
!_converse.idle) {
_converse.idle = true;
_converse.xmppstatus.sendPresence();
}
if (_converse.auto_away > 0 && if (_converse.auto_away > 0 &&
_converse.idle_seconds > _converse.auto_away && _converse.idle_seconds > _converse.auto_away &&
stat !== 'away' && stat !== 'xa' && stat !== 'dnd') { stat !== 'away' && stat !== 'xa' && stat !== 'dnd') {
...@@ -457,7 +469,7 @@ _converse.initialize = function (settings, callback) { ...@@ -457,7 +469,7 @@ _converse.initialize = function (settings, callback) {
/* Set an interval of one second and register a handler for it. /* Set an interval of one second and register a handler for it.
* Required for the auto_away, auto_xa and csi_waiting_time features. * Required for the auto_away, auto_xa and csi_waiting_time features.
*/ */
if (_converse.auto_away < 1 && _converse.auto_xa < 1 && _converse.csi_waiting_time < 1) { if (_converse.auto_away < 1 && _converse.auto_xa < 1 && _converse.csi_waiting_time < 1 && _converse.idle_presence_timeout < 1) {
// Waiting time of less then one second means features aren't used. // Waiting time of less then one second means features aren't used.
return; return;
} }
...@@ -888,7 +900,12 @@ _converse.initialize = function (settings, callback) { ...@@ -888,7 +900,12 @@ _converse.initialize = function (settings, callback) {
} }
presence.c('priority').t( presence.c('priority').t(
_.isNaN(Number(_converse.priority)) ? 0 : _converse.priority _.isNaN(Number(_converse.priority)) ? 0 : _converse.priority
); ).up();
if (_converse.idle) {
const idle_since = new Date();
idle_since.setSeconds(idle_since.getSeconds() - _converse.idle_seconds);
presence.c('idle', {xmlns: Strophe.NS.IDLE, since: idle_since.toISOString()});
}
return presence; return presence;
}, },
...@@ -1187,6 +1204,12 @@ _converse.initialize = function (settings, callback) { ...@@ -1187,6 +1204,12 @@ _converse.initialize = function (settings, callback) {
if (!Backbone.history.started) { if (!Backbone.history.started) {
Backbone.history.start(); Backbone.history.start();
} }
if (_converse.idle_presence_timeout > 0) {
_converse.on('addClientFeatures', () => {
_converse.api.disco.own.features.add(Strophe.NS.IDLE);
});
}
} }
if (!_.isUndefined(_converse.connection) && if (!_.isUndefined(_converse.connection) &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment