mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00

* feat: add riverpod based favorite album provider * feat: add album is saved, new releases and tracks providers * feat: add artist related providers * feat: add all categories providers * feat: add lyrics provider * feat: add playlist related providers * feat: add search provider * feat: add view and spotify friends provider * feat: add playlist create and update and favorite handlers * feat: use providers in home screen * chore: fix dart lint issues * feat: use new providers for playlist and albums screen * feat: use providers in artist page * feat: use providers on library page * feat: use provider for playlist and album card and heart button * feat: use provider in search page * feat: use providers in generate playlist * feat: use provider in lyrics screen * feat: use provider for create playlist * feat: use provider in add track dialog * feat: use providers in remaining pages and remove fl_query * fix: remove direct access to provider.value * fix: glitching when loading * fix: user album loading next page indicator * feat: make many provider autoDispose after 5 minutes of no usage * fix: ignore episodes in tracks
109 lines
3.0 KiB
Dart
109 lines
3.0 KiB
Dart
import 'package:collection/collection.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:spotify/spotify.dart';
|
|
import 'package:spotube/models/current_playlist.dart';
|
|
import 'package:spotube/utils/persisted_state_notifier.dart';
|
|
|
|
enum BlacklistedType {
|
|
artist,
|
|
track;
|
|
|
|
static BlacklistedType fromName(String name) =>
|
|
BlacklistedType.values.firstWhere((e) => e.name == name);
|
|
}
|
|
|
|
class BlacklistedElement {
|
|
final String id;
|
|
final String name;
|
|
final BlacklistedType type;
|
|
|
|
BlacklistedElement.artist(this.id, this.name) : type = BlacklistedType.artist;
|
|
|
|
BlacklistedElement.track(this.id, this.name) : type = BlacklistedType.track;
|
|
|
|
BlacklistedElement.fromJson(Map<String, dynamic> json)
|
|
: id = json['id'],
|
|
name = json['name'],
|
|
type = BlacklistedType.fromName(json['type']);
|
|
|
|
Map<String, dynamic> toJson() => {'id': id, 'type': type.name, 'name': name};
|
|
|
|
@override
|
|
operator ==(other) =>
|
|
other is BlacklistedElement &&
|
|
other.id == id &&
|
|
other.type == type &&
|
|
other.name == name;
|
|
|
|
@override
|
|
int get hashCode => id.hashCode ^ type.hashCode ^ name.hashCode;
|
|
}
|
|
|
|
class BlackListNotifier
|
|
extends PersistedStateNotifier<Set<BlacklistedElement>> {
|
|
BlackListNotifier() : super({}, "blacklist");
|
|
|
|
static final provider =
|
|
StateNotifierProvider<BlackListNotifier, Set<BlacklistedElement>>(
|
|
(ref) => BlackListNotifier(),
|
|
);
|
|
|
|
void add(BlacklistedElement element) {
|
|
state = state.union({element});
|
|
}
|
|
|
|
void remove(BlacklistedElement element) {
|
|
state = state.difference({element});
|
|
}
|
|
|
|
bool contains(TrackSimple track) {
|
|
final containsTrack =
|
|
state.contains(BlacklistedElement.track(track.id!, track.name!));
|
|
|
|
final containsTrackArtists = track.artists?.any(
|
|
(artist) => state.contains(
|
|
BlacklistedElement.artist(artist.id!, artist.name ?? "Spotify"),
|
|
),
|
|
) ??
|
|
false;
|
|
|
|
return containsTrack || containsTrackArtists;
|
|
}
|
|
|
|
/// Filters the non blacklisted tracks from the given [tracks]
|
|
Iterable<TrackSimple> filter(Iterable<TrackSimple> tracks) {
|
|
return tracks.whereNot(contains).toList();
|
|
}
|
|
|
|
CurrentPlaylist filterPlaylist(CurrentPlaylist playlist) {
|
|
return CurrentPlaylist(
|
|
id: playlist.id,
|
|
name: playlist.name,
|
|
thumbnail: playlist.thumbnail,
|
|
tracks: playlist.tracks.where(
|
|
(track) {
|
|
return !state
|
|
.contains(BlacklistedElement.track(track.id!, track.name!)) &&
|
|
!(track.artists ?? []).any(
|
|
(artist) => state.contains(
|
|
BlacklistedElement.artist(artist.id!, artist.name!),
|
|
),
|
|
);
|
|
},
|
|
).toList(),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Set<BlacklistedElement> fromJson(Map<String, dynamic> json) {
|
|
return json['blacklist']
|
|
.map<BlacklistedElement>((e) => BlacklistedElement.fromJson(e))
|
|
.toSet();
|
|
}
|
|
|
|
@override
|
|
Map<String, dynamic> toJson() {
|
|
return {'blacklist': state.map((e) => e.toJson()).toList()};
|
|
}
|
|
}
|