Commit 12b7687a authored by Christoph Scholz's avatar Christoph Scholz

Implement sending presences according to XEP-0319: Last User Interaction in Presence

parent da5ca0b5
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
- #1306 added option `notification_delay` - #1306 added option `notification_delay`
- #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
- #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