Files
bvandeusen 147d6e280e feat(flutter): bump deps to latest + Search screen slice
Major version bumps (riverpod 2->3, go_router 14->17, just_audio 0.9->0.10,
flutter_secure_storage 9->10, google_fonts 6->8, flutter_lints 4->6).
package_info_plus held at 8.x due to win32 conflict with secure_storage 10.x.

Riverpod 3 breaks: AsyncValue.valueOrNull -> .value, StateProvider replaced
with Notifier subclass. just_audio 0.10: ConcatenatingAudioSource -> setAudioSources.

Search slice:
- models/page.dart (generic Page<T> envelope)
- models/search_response.dart (3-facet wrapper)
- api/endpoints/search.dart
- search/search_provider.dart (debounced 250ms)
- search/search_screen.dart (TextField + 3 horizontal/vertical sections)
- Wired /search route + search button on home AppBar
2026-05-08 14:30:01 -04:00

38 lines
1.5 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../api/endpoints/search.dart';
import '../library/library_providers.dart' show dioProvider;
import '../models/search_response.dart';
final searchApiProvider = FutureProvider<SearchApi>((ref) async {
return SearchApi(await ref.watch(dioProvider.future));
});
/// Current search query text. The screen's TextField writes here on
/// every keystroke; the resultsProvider below debounces.
class SearchQueryNotifier extends Notifier<String> {
@override
String build() => '';
void set(String q) => state = q;
}
final searchQueryProvider =
NotifierProvider<SearchQueryNotifier, String>(SearchQueryNotifier.new);
/// Debounced search results. Returns null for empty queries so the
/// screen can show a neutral empty state instead of "0 results."
///
/// Debounce: 250ms. After the wait, re-reads the live query — if the
/// user has typed more in that window, this attempt is silently
/// abandoned (returns null) and a newer attempt fires on the next
/// rebuild. No request hits the server while the user is mid-typing.
final searchResultsProvider = FutureProvider<SearchResponse?>((ref) async {
final q = ref.watch(searchQueryProvider).trim();
if (q.isEmpty) return null;
await Future<void>.delayed(const Duration(milliseconds: 250));
// Re-read the (possibly newer) query; if the user typed more, bail.
if (ref.read(searchQueryProvider).trim() != q) return null;
final api = await ref.watch(searchApiProvider.future);
return api.search(q);
});