search method

  1. @override
Future<SearchResult> search(
  1. String query, {
  2. int limit = 20,
  3. int offset = 0,
  4. CancellationToken? cancellationToken,
})
override

Performs a search operation.

Returns a SearchResult containing items matching the query. The optional limit parameter controls the maximum number of results to return. The offset parameter enables pagination.

The cancellationToken parameter allows cancelling long-running searches when the user types a new query. This prevents memory leaks and race conditions. If cancelled, implementations should return an empty result or throw CancelledException.

This method is called when the user submits a search query. It should perform the actual search logic and return matching items.

Implementation

@override
Future<SearchResult> search(
  String query, {
  int limit = 20,
  int offset = 0,
  CancellationToken? cancellationToken,
}) async {
  final stopwatch = Stopwatch()..start();

  if (query.isEmpty) {
    return SearchResult.empty(query);
  }

  // Check cancellation before starting expensive operation
  cancellationToken?.throwIfCancelled();

  final normalizedQuery = query.toLowerCase();
  final matches = _indexed
      .where((indexed) {
        return indexed.normalizedTitle.contains(normalizedQuery) ||
            indexed.normalizedSubtitle.contains(normalizedQuery) ||
            (indexed.normalizedDescription?.contains(normalizedQuery) ??
                false);
      })
      .map((e) => e.item)
      .toList();

  // Check cancellation after search but before pagination
  cancellationToken?.throwIfCancelled();

  final paginatedMatches = matches.skip(offset).take(limit).toList();

  stopwatch.stop();

  return SearchResult(
    query: query,
    items: paginatedMatches,
    totalCount: matches.length,
    executionTimeMs: stopwatch.elapsedMilliseconds,
    hasMore: offset + limit < matches.length,
    nextPage: offset + limit < matches.length
        ? (offset + limit).toString()
        : null,
  );
}