Files
minstrel/flutter_client/lib/api/endpoints/me.dart
T
bvandeusen 66545bf8c3 feat(flutter): library screen with 5 tabs (Artists/Albums/History/Liked/Hidden)
Models:
- history_event.dart (HistoryEvent + HistoryPage envelope)
- quarantine_mine.dart (QuarantineMineRow for /api/quarantine/mine)
- Renamed Page<T> -> Paged<T> to avoid collision with Material's Page

Endpoints:
- library_lists.dart: listArtists / listAlbums (paged)
- me.dart: history + quarantineMine
- likes.dart: extended with listTracks/Albums/Artists (paged)

UI:
- library_screen.dart: TabBar over 5 tabs
- Artists tab: 3-col grid
- Albums tab: 2-col grid
- History tab: list with relative-time formatting (matches HistoryRow.svelte)
- Liked tab: 3 stacked sections (artists scroll-row, albums scroll-row, tracks list)
- Hidden tab: list of quarantined tracks with reason pill
- /library route + library_music icon on home AppBar

First page only for v1 (limit 50). Infinite scroll deferred.
2026-05-08 14:40:26 -04:00

31 lines
1.0 KiB
Dart

import 'package:dio/dio.dart';
import '../../models/history_event.dart';
import '../../models/quarantine_mine.dart';
/// /api/me/* endpoints — caller-scoped data (history, profile, etc.).
class MeApi {
MeApi(this._dio);
final Dio _dio;
/// GET /api/me/history. Paginated via offset/limit; server emits
/// `{events, has_more}` rather than the standard `Page<T>` envelope.
Future<HistoryPage> history({int limit = 50, int offset = 0}) async {
final r = await _dio.get<Map<String, dynamic>>(
'/api/me/history',
queryParameters: {'limit': limit, 'offset': offset},
);
return HistoryPage.fromJson(r.data ?? const {});
}
/// GET /api/quarantine/mine — flat list (no envelope).
Future<List<QuarantineMineRow>> quarantineMine() async {
final r = await _dio.get<List<dynamic>>('/api/quarantine/mine');
final raw = r.data ?? const [];
return raw
.map((e) =>
QuarantineMineRow.fromJson((e as Map).cast<String, dynamic>()))
.toList(growable: false);
}
}