import 'package:freezer/api/definitions.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:json_annotation/json_annotation.dart'; import 'dart:async'; part 'cache.g.dart'; late Cache cache; //Cache for miscellaneous things @HiveType(typeId: 22) @JsonSerializable() class Cache { static Future> get _box => Hive.openLazyBox('metacache'); //ID's of tracks that are in library @HiveField(0) List? libraryTracks = []; //Track ID of logged track, to prevent duplicates @HiveField(1) @JsonKey(includeToJson: false, includeFromJson: false) String? loggedTrackId; @HiveField(2) @JsonKey(defaultValue: []) List history = []; //All sorting cached @HiveField(3) @JsonKey(defaultValue: []) List sorts = []; //Sleep timer @JsonKey(includeToJson: false, includeFromJson: false) DateTime? sleepTimerTime; @JsonKey(includeToJson: false, includeFromJson: false) // ignore: cancel_subscriptions StreamSubscription? sleepTimer; //Search history @HiveField(4) @JsonKey(name: 'searchHistory2', defaultValue: []) List searchHistory = []; //If download threads warning was shown @HiveField(5) @JsonKey(defaultValue: false) bool threadsWarning = false; //Last time update check @HiveField(6) DateTime? lastUpdateCheck; @HiveField(7) String? favoritesPlaylistId; @JsonKey(includeToJson: false, includeFromJson: false) 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!.isEmpty) return false; return libraryTracks!.contains(t.id); } //Add to history void addToSearchHistory(DeezerMediaItem item) async { // 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 wipe() async { await (await _box).clear(); } // TODO: improve static Future load([int tryN = 0]) async { final box = await _box; if (tryN > 2) { // recursion error, something's wrong throw new Exception("can't load cache"); } //Doesn't exist, create new if (box.isEmpty) { final c = Cache(); await c.save(); return c; } try { return (await box.get(0))!; } catch (e) { // invalidate cache on error await box.clear(); return await load(tryN + 1); } } Future save() async { final box = await _box; await box.clear(); await box.put(0, this); } //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); // } } @HiveType(typeId: 20) @JsonSerializable() class SearchHistoryItem { @HiveField(0) @JsonKey( toJson: _searchHistoryItemTypeToJson, fromJson: _searchHistoryItemTypeFromJson) SearchHistoryItemType type; @HiveField(1) // TODO: make this type-safe dynamic data; 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]; } @HiveType(typeId: 21) enum SearchHistoryItemType { @HiveField(0) TRACK, @HiveField(1) ALBUM, @HiveField(2) ARTIST, @HiveField(3) PLAYLIST }