routePres method

  1. @override
void routePres(
  1. PresMessage pres
)
override

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);
}