selectSeoCollection function

SeoCollectionSnapshot selectSeoCollection({
  1. required List<SeoCollectionRecord> records,
  2. required int categoryCount,
  3. required int pageSize,
  4. SeoCollectionState state = const SeoCollectionState(),
})

Computes the canonical result for state without mutating records.

Implementation

SeoCollectionSnapshot selectSeoCollection({
  required List<SeoCollectionRecord> records,
  required int categoryCount,
  required int pageSize,
  SeoCollectionState state = const SeoCollectionState(),
}) {
  final size = normalizeSeoCollectionPageSize(pageSize);
  final category = state.categoryIndex;
  final selectedCategory =
      category != null && category >= 0 && category < categoryCount
          ? category
          : null;
  final rawQuery = boundSeoCollectionQuery(state.query);
  final query = normalizeSeoCollectionText(rawQuery);
  final terms = query.isEmpty
      ? const <String>[]
      : query.split(' ').toSet().toList(growable: false);
  final ordered = <int>[];
  for (var index = 0; index < records.length; index++) {
    final record = records[index];
    if (selectedCategory != null &&
        !record.categoryIndexes.contains(selectedCategory)) {
      continue;
    }
    final corpus = record.normalizedSearchText;
    if (terms.any((term) => !corpus.contains(term))) continue;
    ordered.add(index);
  }

  ordered.sort((left, right) {
    final leftRecord = records[left];
    final rightRecord = records[right];
    final compared = switch (state.sort) {
      SeoCollectionSort.newest =>
        rightRecord.sortKey.compareTo(leftRecord.sortKey),
      SeoCollectionSort.oldest =>
        leftRecord.sortKey.compareTo(rightRecord.sortKey),
      SeoCollectionSort.title =>
        leftRecord.normalizedTitle.compareTo(rightRecord.normalizedTitle),
    };
    return compared == 0 ? left.compareTo(right) : compared;
  });

  final pageCount = (ordered.length + size - 1) ~/ size;
  final page = pageCount == 0 ? 0 : state.page.clamp(0, pageCount - 1);
  final start = page * size;
  final end = (start + size).clamp(0, ordered.length);
  final canonical = SeoCollectionState(
    query: rawQuery,
    categoryIndex: selectedCategory,
    sort: state.sort,
    page: page,
  );
  return SeoCollectionSnapshot(
    state: canonical,
    orderedIndices: List.unmodifiable(ordered),
    visibleIndices: List.unmodifiable(ordered.sublist(start, end)),
    matchCount: ordered.length,
    pageCount: pageCount,
  );
}