feat(flutter): discover screen — search Lidarr + create requests
- models/lidarr.dart (LidarrSearchResult + LidarrRequestKind) - api/endpoints/discover.dart (search + createRequest) - discover/discover_screen.dart with TextField, kind toggle (Artists/Albums), results list with in_library / requested pills - /discover route + explore icon on home AppBar (5 actions now: Library, Playlists, Search, Discover, Settings)
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import '../../models/lidarr.dart';
|
||||
|
||||
class DiscoverApi {
|
||||
DiscoverApi(this._dio);
|
||||
final Dio _dio;
|
||||
|
||||
/// GET /api/lidarr/search?q=...&kind=artist|album|track. Server has a
|
||||
/// 60s LRU cache for repeat queries so re-typing the same string in
|
||||
/// quick succession is cheap.
|
||||
Future<List<LidarrSearchResult>> search(
|
||||
String query,
|
||||
LidarrRequestKind kind,
|
||||
) async {
|
||||
final r = await _dio.get<List<dynamic>>(
|
||||
'/api/lidarr/search',
|
||||
queryParameters: {'q': query, 'kind': kind.wire},
|
||||
);
|
||||
final raw = r.data ?? const [];
|
||||
return raw
|
||||
.map((e) =>
|
||||
LidarrSearchResult.fromJson((e as Map).cast<String, dynamic>()))
|
||||
.toList(growable: false);
|
||||
}
|
||||
|
||||
/// POST /api/requests. Returns the newly-created LidarrRequest body
|
||||
/// — we don't expose a typed wrapper for that yet on mobile (admin
|
||||
/// reviews requests; user just kicks them off), so we discard the
|
||||
/// response and surface success/failure to the caller.
|
||||
Future<void> createRequest({
|
||||
required LidarrRequestKind kind,
|
||||
required String artistMbid,
|
||||
required String artistName,
|
||||
String? albumMbid,
|
||||
String? albumTitle,
|
||||
String? trackMbid,
|
||||
String? trackTitle,
|
||||
}) async {
|
||||
final body = <String, dynamic>{
|
||||
'kind': kind.wire,
|
||||
'lidarr_artist_mbid': artistMbid,
|
||||
'artist_name': artistName,
|
||||
};
|
||||
if (albumMbid != null && albumMbid.isNotEmpty) {
|
||||
body['lidarr_album_mbid'] = albumMbid;
|
||||
}
|
||||
if (trackMbid != null && trackMbid.isNotEmpty) {
|
||||
body['lidarr_track_mbid'] = trackMbid;
|
||||
}
|
||||
if (albumTitle != null && albumTitle.isNotEmpty) {
|
||||
body['album_title'] = albumTitle;
|
||||
}
|
||||
if (trackTitle != null && trackTitle.isNotEmpty) {
|
||||
body['track_title'] = trackTitle;
|
||||
}
|
||||
await _dio.post<Map<String, dynamic>>('/api/requests', data: body);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user