feat: add top date based filtering

This commit is contained in:
Kingkor Roy Tirtho 2024-05-04 23:00:08 +06:00
parent c9bd42c847
commit 1500fff9ce
7 changed files with 106 additions and 25 deletions

View File

@ -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(
title: summary.duration.inMinutes.toDouble(),
unit: "minutes",
description: 'Listened to music',
color: Colors.green,
),
},
SummaryCard(
title: summary.duration.inMinutes.toDouble(),
unit: "minutes",
description: 'Listened to music',
color: Colors.green,
),
SummaryCard(
title: summary.tracks.toDouble(),
unit: "songs",

View File

@ -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,

View File

@ -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,

View File

@ -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, _) {

View File

@ -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,

View File

@ -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({

View File

@ -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);