147d6e280e
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
30 lines
824 B
Dart
30 lines
824 B
Dart
import 'package:dio/dio.dart';
|
|
|
|
import '../../models/search_response.dart';
|
|
|
|
/// SearchApi wraps GET /api/search. The server runs three facets (artists,
|
|
/// albums, tracks) sharing one limit/offset pair. Each facet returns its
|
|
/// own total reflecting the full match count.
|
|
class SearchApi {
|
|
SearchApi(this._dio);
|
|
final Dio _dio;
|
|
|
|
/// Empty / whitespace-only query is the caller's responsibility to
|
|
/// guard against — the server returns 400 bad_request for it.
|
|
Future<SearchResponse> search(
|
|
String query, {
|
|
int limit = 20,
|
|
int offset = 0,
|
|
}) async {
|
|
final r = await _dio.get<Map<String, dynamic>>(
|
|
'/api/search',
|
|
queryParameters: {
|
|
'q': query,
|
|
'limit': limit,
|
|
'offset': offset,
|
|
},
|
|
);
|
|
return SearchResponse.fromJson(r.data ?? const {});
|
|
}
|
|
}
|