mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-12-08 16:27:31 +00:00
feat: add top date based filtering
This commit is contained in:
parent
c9bd42c847
commit
1500fff9ce
@ -28,20 +28,12 @@ class StatsPageSummarySection extends HookConsumerWidget {
|
||||
childAspectRatio: constrains.isXs ? 1.3 : 1.5,
|
||||
),
|
||||
delegate: SliverChildListDelegate([
|
||||
switch (summary.duration) {
|
||||
>= const Duration(hours: 1) => SummaryCard(
|
||||
title: summary.duration.inHours.toDouble(),
|
||||
unit: "hours",
|
||||
description: 'Listened to music',
|
||||
color: Colors.green,
|
||||
),
|
||||
_ => SummaryCard(
|
||||
SummaryCard(
|
||||
title: summary.duration.inMinutes.toDouble(),
|
||||
unit: "minutes",
|
||||
description: 'Listened to music',
|
||||
color: Colors.green,
|
||||
),
|
||||
},
|
||||
SummaryCard(
|
||||
title: summary.tracks.toDouble(),
|
||||
unit: "songs",
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotube/collections/formatters.dart';
|
||||
import 'package:spotube/components/album/album_card.dart';
|
||||
@ -15,8 +14,9 @@ class TopAlbums extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final albums =
|
||||
ref.watch(playbackHistoryTopProvider.select((value) => value.albums));
|
||||
final historyDuration = ref.watch(playbackHistoryTopDurationProvider);
|
||||
final albums = ref.watch(playbackHistoryTopProvider(historyDuration)
|
||||
.select((value) => value.albums));
|
||||
|
||||
return SliverList.builder(
|
||||
itemCount: albums.length,
|
||||
|
||||
@ -12,8 +12,9 @@ class TopArtists extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final artists =
|
||||
ref.watch(playbackHistoryTopProvider.select((value) => value.artists));
|
||||
final historyDuration = ref.watch(playbackHistoryTopDurationProvider);
|
||||
final artists = ref.watch(playbackHistoryTopProvider(historyDuration)
|
||||
.select((value) => value.artists));
|
||||
|
||||
return SliverList.builder(
|
||||
itemCount: artists.length,
|
||||
|
||||
@ -5,6 +5,8 @@ import 'package:spotube/components/shared/themed_button_tab_bar.dart';
|
||||
import 'package:spotube/components/stats/top/albums.dart';
|
||||
import 'package:spotube/components/stats/top/artists.dart';
|
||||
import 'package:spotube/components/stats/top/tracks.dart';
|
||||
import 'package:spotube/provider/history/state.dart';
|
||||
import 'package:spotube/provider/history/top.dart';
|
||||
|
||||
class StatsPageTopSection extends HookConsumerWidget {
|
||||
const StatsPageTopSection({super.key});
|
||||
@ -12,6 +14,9 @@ class StatsPageTopSection extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final tabController = useTabController(initialLength: 3);
|
||||
final historyDuration = ref.watch(playbackHistoryTopDurationProvider);
|
||||
final historyDurationNotifier =
|
||||
ref.watch(playbackHistoryTopDurationProvider.notifier);
|
||||
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
@ -41,6 +46,50 @@ class StatsPageTopSection extends HookConsumerWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: DropdownButton(
|
||||
style: Theme.of(context).textTheme.bodySmall!,
|
||||
isDense: true,
|
||||
padding: const EdgeInsets.all(4),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
underline: const SizedBox(),
|
||||
value: historyDuration,
|
||||
onChanged: (value) {
|
||||
if (value == null) return;
|
||||
historyDurationNotifier.update((_) => value);
|
||||
},
|
||||
icon: const Icon(Icons.arrow_drop_down),
|
||||
items: const [
|
||||
DropdownMenuItem(
|
||||
value: HistoryDuration.days7,
|
||||
child: Text("This week"),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: HistoryDuration.days30,
|
||||
child: Text("This month"),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: HistoryDuration.months6,
|
||||
child: Text("Last 6 months"),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: HistoryDuration.year,
|
||||
child: Text("This year"),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: HistoryDuration.years2,
|
||||
child: Text("Last 2 years"),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: HistoryDuration.allTime,
|
||||
child: Text("All time"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
ListenableBuilder(
|
||||
listenable: tabController,
|
||||
builder: (context, _) {
|
||||
|
||||
@ -13,8 +13,9 @@ class TopTracks extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final tracks =
|
||||
ref.watch(playbackHistoryTopProvider.select((value) => value.tracks));
|
||||
final historyDuration = ref.watch(playbackHistoryTopDurationProvider);
|
||||
final tracks = ref.watch(playbackHistoryTopProvider(historyDuration)
|
||||
.select((value) => value.tracks));
|
||||
|
||||
return SliverList.builder(
|
||||
itemCount: tracks.length,
|
||||
|
||||
@ -4,6 +4,15 @@ import 'package:spotify/spotify.dart';
|
||||
part 'state.freezed.dart';
|
||||
part 'state.g.dart';
|
||||
|
||||
enum HistoryDuration {
|
||||
allTime,
|
||||
days7,
|
||||
days30,
|
||||
months6,
|
||||
year,
|
||||
years2,
|
||||
}
|
||||
|
||||
@freezed
|
||||
class PlaybackHistoryItem with _$PlaybackHistoryItem {
|
||||
factory PlaybackHistoryItem.playlist({
|
||||
|
||||
@ -2,12 +2,41 @@ 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 playbackHistoryTopProvider = Provider((ref) {
|
||||
final (:tracks, :albums, playlists: _) =
|
||||
ref.watch(playbackHistoryGroupedProvider);
|
||||
final playbackHistoryTopDurationProvider =
|
||||
StateProvider((ref) => HistoryDuration.days7);
|
||||
final playbackHistoryTopProvider =
|
||||
Provider.family((ref, HistoryDuration durationState) {
|
||||
final grouped = ref.watch(playbackHistoryGroupedProvider);
|
||||
|
||||
final tracksWithCount = groupBy(tracks, (track) => track.track.id!)
|
||||
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 tracksWithCount = groupBy(
|
||||
tracks,
|
||||
(track) => track.track.id!,
|
||||
)
|
||||
.entries
|
||||
.map((entry) {
|
||||
return (count: entry.value.length, track: entry.value.first.track);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user