routePres method
Process presence change message
Implementation
@override
void routePres(PresMessage pres) {
if (pres.what == 'term') {
// The 'me' topic itself is detached. Mark as unsubscribed.
resetSubscription();
return;
}
if (pres.what == 'upd' && pres.src == topic_names.TOPIC_ME) {
// Update to me description. Request updated value.
getMeta(startMetaQuery().withDesc(null).build());
return;
}
var cont = _contacts[pres.src];
if (cont != null) {
switch (pres.what) {
case 'on':
// topic came online
cont.online = true;
break;
case 'off':
// topic went offline
if (cont.online == true) {
cont.online = false;
if (cont.seen != null) {
cont.seen?.when = DateTime.now();
} else {
cont.seen = Seen(when: DateTime.now());
}
}
break;
case 'msg':
// new message received
cont.touched = DateTime.now();
cont.seq = (pres.seq ?? 0) | 0;
// Check if message is sent by the current user. If so it's been read already.
if (pres.act == null || _tinodeService.isMe(pres.act ?? '')) {
cont.read = cont.read != null && cont.read != 0
? max((cont.read ?? 0), (cont.seq ?? 0))
: cont.seq;
cont.recv = cont.recv != null && cont.recv != 0
? max((cont.read ?? 0), (cont.recv ?? 0))
: cont.read;
}
cont.unread = (cont.seq ?? 0) - ((cont.read ?? 0) | 0);
break;
case 'upd': // desc updated
// Request updated subscription.
getMeta(startMetaQuery().withLaterOneSub(pres.src).build());
break;
case 'acs':
// access mode changed
if (cont.acs != null) {
cont.acs?.updateAll(pres.dacs);
} else {
cont.acs = AccessMode(null).updateAll(pres.dacs);
}
cont.touched = DateTime.now();
break;
case 'ua':
// user agent changed
cont.seen = Seen(when: DateTime.now(), ua: pres.ua);
break;
case 'recv': // user's other session marked some messages as received
pres.seq = (pres.seq ?? 0) | 0;
cont.recv = cont.recv != null && cont.recv != 0
? max((cont.recv ?? 0), (pres.seq ?? 0))
: pres.seq;
break;
case 'read':
// user's other session marked some messages as read
pres.seq = (pres.seq ?? 0) | 0;
cont.read = cont.read != null && cont.read != 0
? max((cont.read ?? 0), (pres.seq ?? 0))
: pres.seq;
cont.recv = cont.recv != null && cont.recv != 0
? max((cont.read ?? 0), (cont.recv ?? 0))
: cont.recv;
cont.unread = (cont.seq ?? 0) - (cont.read ?? 0);
break;
case 'gone':
// topic deleted or unsubscribed from
_contacts.remove(pres.src);
_cacheManager.delete('topic', pres.src ?? '');
break;
case 'del':
// Update topic.del value.
break;
default:
_loggerService
.log("Unsupported presence update in 'me' " + (pres.what ?? ''));
}
onContactUpdate.add(ContactUpdateEvent(pres.what!, cont));
} else {
if (pres.what == 'acs') {
// New subscriptions and deleted/banned subscriptions have full
// access mode (no + or - in the dacs string). Changes to known subscriptions are sent as
// deltas, but they should not happen here.
AccessMode? acs = AccessMode(pres.dacs);
if (acs.mode == INVALID) {
_loggerService.error('Invalid access mode update ' +
(pres.src ?? '') +
' ' +
pres.dacs.toString());
return;
} else if (acs.mode == NONE) {
_loggerService.warn('Removing non-existent subscription ' +
(pres.src ?? '') +
' ' +
pres.dacs.toString());
} else {
// New subscription. Send request for the full description.
// Using .withOneSub (not .withLaterOneSub) to make sure IfModifiedSince is not set.
getMeta(startMetaQuery().withOneSub(null, pres.src).build());
// Create a dummy entry to catch online status update.
_contacts[pres.src ?? ''] = TopicSubscription(
touched: DateTime.now(),
topic: pres.src,
online: false,
acs: acs);
}
} else if (pres.what == 'tags') {
getMeta(startMetaQuery().withTags().build());
}
}
onPres.add(pres);
}