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

This commit is contained in:
Christoph Scholz 2018-11-12 18:46:03 +01:00
parent da5ca0b585
commit 12b7687a89
5 changed files with 74 additions and 9 deletions

View File

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

35
dist/converse.js vendored
View File

@ -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 = {
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) {
_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) {
_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) {
/* 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) {
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) {
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') {

View File

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

View File

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

View File

@ -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 = {
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) {
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) {
!_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) {
/* 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) {
} }
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) {
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) &&