compute static method

List<GroupInfo> compute({
  1. required List<String> senderIds,
  2. List<DateTime>? timestamps,
  3. Duration threshold = const Duration(minutes: 1),
})

Computes grouping information for each message in the list.

senderIds — ordered list of sender identifiers (one per message).

timestamps — optional list of message timestamps (same length as senderIds). When provided, messages separated by more than threshold are placed in separate groups even if they share a sender.

threshold — maximum time gap within the same group. Defaults to 1 minute.

Returns a List<GroupInfo> of the same length as senderIds.

Implementation

static List<GroupInfo> compute({
  required List<String> senderIds,
  List<DateTime>? timestamps,
  Duration threshold = const Duration(minutes: 1),
}) {
  assert(
    timestamps == null || timestamps.length == senderIds.length,
    'timestamps must have the same length as senderIds',
  );

  final int count = senderIds.length;
  if (count == 0) return const [];

  final List<GroupInfo> result = List.filled(
    count,
    const GroupInfo(
      isGroupStart: true,
      isGroupEnd: true,
      isAlone: true,
      showTail: true,
      showAvatar: true,
    ),
  );

  for (int i = 0; i < count; i++) {
    final bool hasPrev = i > 0;
    final bool hasNext = i < count - 1;

    final bool sameAsPrev = hasPrev &&
        senderIds[i] == senderIds[i - 1] &&
        _withinThreshold(timestamps, i - 1, i, threshold);

    final bool sameAsNext = hasNext &&
        senderIds[i] == senderIds[i + 1] &&
        _withinThreshold(timestamps, i, i + 1, threshold);

    final bool isGroupStart = !sameAsPrev;
    final bool isGroupEnd = !sameAsNext;
    final bool isAlone = isGroupStart && isGroupEnd;

    result[i] = GroupInfo(
      isGroupStart: isGroupStart,
      isGroupEnd: isGroupEnd,
      isAlone: isAlone,
      showTail: isGroupEnd,
      showAvatar: isGroupEnd,
    );
  }

  return result;
}