import 'package:collection/collection.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/extensions/track.dart'; import 'package:spotube/models/local_track.dart'; import 'package:spotube/services/sourced_track/sourced_track.dart'; class ProxyPlaylist { final Set tracks; final Set collections; final int? active; ProxyPlaylist(this.tracks, [this.active, this.collections = const {}]); factory ProxyPlaylist.fromJson( Map json, Ref ref, ) { return ProxyPlaylist( List.castFrom>( json['tracks'] ?? >[], ).map((t) => _makeAppropriateTrack(t, ref)).toSet(), json['active'] as int?, json['collections'] == null ? {} : (json['collections'] as List).toSet().cast(), ); } factory ProxyPlaylist.fromJsonRaw(Map json) => ProxyPlaylist( json['tracks'] == null ? {} : (json['tracks'] as List).map((t) => Track.fromJson(t)).toSet(), json['active'] as int?, json['collections'] == null ? {} : (json['collections'] as List).toSet().cast(), ); Track? get activeTrack => active == null || active == -1 ? null : tracks.elementAtOrNull(active!); bool get isFetching => activeTrack != null && activeTrack is! SourcedTrack && activeTrack is! LocalTrack; bool containsCollection(String collection) { return collections.contains(collection); } bool containsTrack(TrackSimple track) { return tracks.firstWhereOrNull((element) => element.id == track.id) != null; } bool containsTracks(Iterable tracks) { if (tracks.isEmpty) return false; return tracks.every(containsTrack); } static Track _makeAppropriateTrack(Map track, Ref ref) { if (track.containsKey("ytUri")) { return SourcedTrack.fromJson(track, ref: ref); } else if (track.containsKey("path")) { return LocalTrack.fromJson(track); } else { return Track.fromJson(track); } } /// To make sure proper instance method is used for JSON serialization /// Otherwise default super.toJson() is used static Map _makeAppropriateTrackJson(Track track) { return switch (track.runtimeType) { LocalTrack() => track.toJson(), SourcedTrack() => track.toJson(), _ => track.toJson(), }; } Map toJson() { return { 'tracks': tracks.map(_makeAppropriateTrackJson).toList(), 'active': active, 'collections': collections.toList(), }; } ProxyPlaylist copyWith({ Set? tracks, int? active, Set? collections, }) { return ProxyPlaylist( tracks ?? this.tracks, active ?? this.active, collections ?? this.collections, ); } }