import 'package:freezer/api/definitions.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart' as p; import 'dart:io'; import 'dart:convert'; import 'dart:async'; part 'cache.g.dart'; late Cache cache; //Cache for miscellaneous things @JsonSerializable() class Cache { //ID's of tracks that are in library List? libraryTracks = []; //Track ID of logged track, to prevent duplicates @JsonKey(ignore: true) String? loggedTrackId; @JsonKey(defaultValue: []) List history = []; //All sorting cached @JsonKey(defaultValue: []) List sorts = []; //Sleep timer @JsonKey(ignore: true) DateTime? sleepTimerTime; @JsonKey(ignore: true) // ignore: cancel_subscriptions StreamSubscription? sleepTimer; //Search history @JsonKey(name: 'searchHistory2') List? searchHistory; //If download threads warning was shown @JsonKey(defaultValue: false) bool? threadsWarning; //Last time update check @JsonKey(defaultValue: 0) int? lastUpdateCheck; @JsonKey(ignore: true) bool wakelock = false; Cache({this.libraryTracks}); //Wrapper to test if track is favorite against cache bool checkTrackFavorite(Track t) { if (t.favorite != null && t.favorite!) return true; if (libraryTracks == null || libraryTracks!.length == 0) return false; return libraryTracks!.contains(t.id); } //Add to history void addToSearchHistory(dynamic item) async { if (searchHistory == null) searchHistory = []; // Remove duplicate int i = searchHistory!.indexWhere((e) => e.data.id == item.id); if (i != -1) { searchHistory!.removeAt(i); } if (item is Track) searchHistory!.add(SearchHistoryItem(item, SearchHistoryItemType.TRACK)); if (item is Album) searchHistory!.add(SearchHistoryItem(item, SearchHistoryItemType.ALBUM)); if (item is Artist) searchHistory!.add(SearchHistoryItem(item, SearchHistoryItemType.ARTIST)); if (item is Playlist) searchHistory! .add(SearchHistoryItem(item, SearchHistoryItemType.PLAYLIST)); await save(); } //Save, load static Future getPath() async { return p.join( (await getApplicationDocumentsDirectory()).path, 'metacache.json'); } static Future wipe() async { await File(await getPath()).delete(); } static Future load() async { File file = File(await Cache.getPath()); //Doesn't exist, create new if (!(await file.exists())) { Cache c = Cache(); await c.save(); return c; } return Cache.fromJson(jsonDecode(await file.readAsString())); } Future save() async { File file = File(await Cache.getPath()); file.writeAsString(jsonEncode(this.toJson())); } //JSON factory Cache.fromJson(Map json) => _$CacheFromJson(json); Map toJson() => _$CacheToJson(this); //Search History JSON // static List _searchHistoryFromJson(List? json) { // return (json ?? []) // .map((i) => _searchHistoryItemFromJson(i)) // .toList(); // } // static SearchHistoryItem _searchHistoryItemFromJson( // Map json) { // SearchHistoryItemType type = SearchHistoryItemType.values[json['type']]; // dynamic data; // switch (type) { // case SearchHistoryItemType.TRACK: // data = Track.fromJson(json['data']); // break; // case SearchHistoryItemType.ALBUM: // data = Album.fromJson(json['data']); // break; // case SearchHistoryItemType.ARTIST: // data = Artist.fromJson(json['data']); // break; // case SearchHistoryItemType.PLAYLIST: // data = Playlist.fromJson(json['data']); // break; // } // return SearchHistoryItem(data, type); // } } @JsonSerializable() class SearchHistoryItem { dynamic data; @JsonKey( toJson: _searchHistoryItemTypeToJson, fromJson: _searchHistoryItemTypeFromJson) SearchHistoryItemType type; SearchHistoryItem(this.data, this.type); Map toJson() => _$SearchHistoryItemToJson(this); factory SearchHistoryItem.fromJson(Map json) => _$SearchHistoryItemFromJson(json); static int _searchHistoryItemTypeToJson(SearchHistoryItemType type) => type.index; static SearchHistoryItemType _searchHistoryItemTypeFromJson(int index) => SearchHistoryItemType.values[index]; } enum SearchHistoryItemType { TRACK, ALBUM, ARTIST, PLAYLIST }