import 'package:dio/dio.dart'; import '../../models/playlist.dart'; /// Wire shape for GET /api/playlists. Server splits owned vs. public so /// the UI can present them as different sections; we preserve that split /// to give the integrations page room to grow. class PlaylistsList { const PlaylistsList({required this.owned, required this.public}); final List owned; final List public; factory PlaylistsList.empty() => const PlaylistsList(owned: [], public: []); /// Concatenated view for callers that don't care about the split. List get all => [...owned, ...public]; } class PlaylistsApi { PlaylistsApi(this._dio); final Dio _dio; /// GET /api/playlists?kind=user|system|all. Server returns /// `{"owned": [...], "public": [...]}`. Owned is the caller's own /// playlists, filtered by the kind param (default "user"). Public /// is other users' shared playlists; not filtered by kind. Future list({String kind = 'user'}) async { final r = await _dio.get>( '/api/playlists', queryParameters: {'kind': kind}, ); final body = r.data ?? const {}; List parse(String key) { final raw = (body[key] as List?) ?? const []; return raw .map((e) => Playlist.fromJson((e as Map).cast())) .toList(growable: false); } return PlaylistsList(owned: parse('owned'), public: parse('public')); } Future get(String id) async { final r = await _dio.get>('/api/playlists/$id'); return PlaylistDetail.fromJson(r.data ?? const {}); } /// POST /api/playlists/{id}/tracks. Owner only; server returns the /// playlist detail with the new rows. Future appendTracks(String playlistId, List trackIds) async { await _dio.post( '/api/playlists/$playlistId/tracks', data: {'track_ids': trackIds}, ); } }