mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-14 08:25:16 +00:00

* feat: add playback history provider * feat: implement recently played section * refactor: use route names * feat: add stats summary and top tracks/artists/albums * feat: add top date based filtering * feat: add stream money calculation * refactor: place search in mobile navbar and settings in home appbar * feat: add individual minutes and streams page * feat(stats): add individual minutes and streams page * chore: default period to 1 month * feat: add text to explain user how hypothetical fees are calculated * chore: ensure usage of route names instead of direct paths * cd: add cache key * cd: remove media_kit_event_loop from git
96 lines
2.8 KiB
Dart
96 lines
2.8 KiB
Dart
import 'package:collection/collection.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:spotify/spotify.dart';
|
|
import 'package:spotube/provider/history/history.dart';
|
|
import 'package:spotube/provider/history/state.dart';
|
|
|
|
final playbackHistoryTopDurationProvider =
|
|
StateProvider((ref) => HistoryDuration.days30);
|
|
|
|
final playbackHistoryTopProvider =
|
|
Provider.family((ref, HistoryDuration durationState) {
|
|
final grouped = ref.watch(playbackHistoryGroupedProvider);
|
|
|
|
final duration = switch (durationState) {
|
|
HistoryDuration.allTime => const Duration(days: 365 * 2003),
|
|
HistoryDuration.days7 => const Duration(days: 7),
|
|
HistoryDuration.days30 => const Duration(days: 30),
|
|
HistoryDuration.months6 => const Duration(days: 30 * 6),
|
|
HistoryDuration.year => const Duration(days: 365),
|
|
HistoryDuration.years2 => const Duration(days: 365 * 2),
|
|
};
|
|
final tracks = grouped.tracks
|
|
.where(
|
|
(item) => item.date.isAfter(
|
|
DateTime.now().subtract(duration),
|
|
),
|
|
)
|
|
.toList();
|
|
final albums = grouped.albums
|
|
.where(
|
|
(item) => item.date.isAfter(
|
|
DateTime.now().subtract(duration),
|
|
),
|
|
)
|
|
.toList();
|
|
|
|
final playlists = grouped.playlists
|
|
.where(
|
|
(item) => item.date.isAfter(
|
|
DateTime.now().subtract(duration),
|
|
),
|
|
)
|
|
.toList();
|
|
|
|
final tracksWithCount = groupBy(
|
|
tracks,
|
|
(track) => track.track.id!,
|
|
)
|
|
.entries
|
|
.map((entry) {
|
|
return (count: entry.value.length, track: entry.value.first.track);
|
|
})
|
|
.sorted((a, b) => b.count.compareTo(a.count))
|
|
.toList();
|
|
|
|
final albumsWithTrackAlbums = [
|
|
for (final historicAlbum in albums) historicAlbum.album,
|
|
for (final track in tracks) track.track.album!
|
|
];
|
|
|
|
final albumsWithCount = groupBy(albumsWithTrackAlbums, (album) => album.id!)
|
|
.entries
|
|
.map((entry) {
|
|
return (count: entry.value.length, album: entry.value.first);
|
|
})
|
|
.sorted((a, b) => b.count.compareTo(a.count))
|
|
.toList();
|
|
|
|
final artists =
|
|
tracks.map((track) => track.track.artists).expand((e) => e ?? <Artist>[]);
|
|
|
|
final artistsWithCount = groupBy(artists, (artist) => artist.id!)
|
|
.entries
|
|
.map((entry) {
|
|
return (count: entry.value.length, artist: entry.value.first);
|
|
})
|
|
.sorted((a, b) => b.count.compareTo(a.count))
|
|
.toList();
|
|
|
|
final playlistsWithCount =
|
|
groupBy(playlists, (playlist) => playlist.playlist.id!)
|
|
.entries
|
|
.map((entry) {
|
|
return (count: entry.value.length, playlist: entry.value.first);
|
|
})
|
|
.sorted((a, b) => b.count.compareTo(a.count))
|
|
.toList();
|
|
|
|
return (
|
|
tracks: tracksWithCount,
|
|
albums: albumsWithCount,
|
|
artists: artistsWithCount,
|
|
playlists: playlistsWithCount,
|
|
);
|
|
});
|