EventChannel.of constructor

EventChannel.of({
  1. required List<Map<String, Object?>> base,
  2. required List<Map<String, Object?>> head,
})

Implementation

factory EventChannel.of({
  required List<Map<String, Object?>> base,
  required List<Map<String, Object?>> head,
}) {
  var deltas = <EventDelta>[];
  var unpairedBase = <(int, Map<String, Object?>)>[];
  var unpairedHead = <(int, Map<String, Object?>)>[];

  for (var (left, right) in _fuse(_align(base, head))) {
    if (left != null && right != null) {
      deltas.addAll(_diffPair(left.$2, right.$2));
    } else if (left != null) {
      unpairedBase.add(left);
    } else if (right != null) {
      unpairedHead.add(right);
    }
  }

  // What is left over and appears on *both* sides did not come or go — it
  // moved. FakeAsync makes a transition's ordering deterministic, so an auth
  // call that now happens after a data fetch is a real finding rather than a
  // flake, and reporting it as one removal plus one addition of the same
  // string is the nonsense the alignment exists to avoid. An event fed by
  // real I/O is not under FakeAsync, and its order can be the host's; `fw
  // compare` asks a second replay before believing a step that only moved.
  var stillBase = <(int, Map<String, Object?>)>[];
  var byKey = <String, List<(int, Map<String, Object?>)>>{};
  for (var entry in unpairedHead) {
    byKey.putIfAbsent(_key(entry.$2), () => []).add(entry);
  }
  var moved = <(int, Map<String, Object?>)>{};
  for (var entry in unpairedBase) {
    var twins = byKey[_key(entry.$2)];
    if (twins == null || twins.isEmpty) {
      stillBase.add(entry);
      continue;
    }
    var twin = twins.removeAt(0);
    moved.add(twin);
    deltas.add(
      EventDelta(
        kind: EventDeltaKind.moved,
        subchannel: _subchannel(entry.$2),
        title: _title(entry.$2),
        property: 'order',
        base: '#${entry.$1}',
        head: '#${twin.$1}',
        origin: _origin(twin.$2),
      ),
    );
  }

  // `system` after everything else before the cap bites. The doc on
  // [maxEventDeltas] promised the allowance to the channels that earn it,
  // and a plain `take` broke that promise *within* events: a step whose
  // system chatter produced its deltas first evicted the one network delta
  // the step was worth reading for. Order inside each half is preserved —
  // this is a partition, not a sort.
  var ranked = [
    for (var delta in deltas)
      if (delta.subchannel != systemSubchannel) delta,
    for (var delta in deltas)
      if (delta.subchannel == systemSubchannel) delta,
  ];
  return EventChannel(
    added: [
      for (var entry in unpairedHead)
        if (!moved.contains(entry)) mask(entry.$2),
    ],
    removed: [for (var entry in stillBase) mask(entry.$2)],
    deltas: ranked.take(maxEventDeltas).toList(),
    deltasDropped: ranked.length > maxEventDeltas
        ? ranked.length - maxEventDeltas
        : 0,
  );
}