feat: add stream money calculation

This commit is contained in:
Kingkor Roy Tirtho 2024-05-09 21:46:40 +06:00
parent 858bbbb20d
commit dcb4c0a018
9 changed files with 37 additions and 9 deletions

View File

@ -1,3 +1,8 @@
import 'package:intl/intl.dart';
final compactNumberFormatter = NumberFormat.compact();
final usdFormatter = NumberFormat.compactCurrency(
locale: 'en-US',
symbol: r"$",
decimalDigits: 2,
);

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/collections/formatters.dart';
import 'package:spotube/components/stats/summary/summary_card.dart';
import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/provider/history/summary.dart';
@ -32,7 +33,7 @@ class StatsPageSummarySection extends HookConsumerWidget {
title: summary.duration.inMinutes.toDouble(),
unit: "minutes",
description: 'Listened to music',
color: Colors.green,
color: Colors.purple,
),
SummaryCard(
title: summary.tracks.toDouble(),
@ -40,6 +41,12 @@ class StatsPageSummarySection extends HookConsumerWidget {
description: 'Streamed overall',
color: Colors.lightBlue,
),
SummaryCard.unformatted(
title: usdFormatter.format(summary.fees.toDouble()),
unit: "",
description: 'Worth of streams',
color: Colors.green,
),
SummaryCard(
title: summary.artists.toDouble(),
unit: "artist's",

View File

@ -4,13 +4,21 @@ import 'package:gap/gap.dart';
import 'package:spotube/collections/formatters.dart';
class SummaryCard extends StatelessWidget {
final double title;
final String title;
final String unit;
final String description;
final MaterialColor color;
const SummaryCard({
SummaryCard({
super.key,
required double title,
required this.unit,
required this.description,
required this.color,
}) : title = compactNumberFormatter.format(title);
const SummaryCard.unformatted({
super.key,
required this.title,
required this.unit,
@ -35,7 +43,7 @@ class SummaryCard extends StatelessWidget {
TextSpan(
children: [
TextSpan(
text: compactNumberFormatter.format(title),
text: title,
style: textTheme.headlineLarge?.copyWith(
color: color.shade900,
),

View File

@ -5,7 +5,6 @@ import 'dart:convert';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/extensions/track.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist.dart';
import 'package:spotube/services/audio_player/loop_mode.dart';

View File

@ -1,6 +1,5 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/extensions/track.dart';
import 'package:spotube/services/sourced_track/sourced_track.dart';
class CurrentPlaylist {

View File

@ -82,7 +82,7 @@ final connectServerProvider = FutureProvider((ref) async {
.toJson(),
);
channel.sink.add(
WebSocketShuffleEvent(await audioPlayer.isShuffled).toJson(),
WebSocketShuffleEvent(audioPlayer.isShuffled).toJson(),
);
channel.sink.add(
WebSocketLoopEvent(audioPlayer.loopMode).toJson(),

View File

@ -1,6 +1,8 @@
import 'package:collection/collection.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/provider/history/history.dart';
import 'package:spotube/provider/history/state.dart';
import 'package:spotube/provider/history/top.dart';
final playbackHistorySummaryProvider = Provider((ref) {
final (:tracks, :albums, :playlists) =
@ -43,10 +45,17 @@ final playbackHistorySummaryProvider = Provider((ref) {
)
.length;
final tracksThisMonth = ref.watch(
playbackHistoryTopProvider(HistoryDuration.days30).select((s) => s.tracks),
);
final streams = tracksThisMonth.fold(0, (acc, el) => acc + el.count);
return (
duration: totalDurationListened,
tracks: totalTracksListened,
artists: totalArtistsListened,
fees: streams * 0.005, // Spotify pays $0.003 to $0.005
albums: totalAlbumsListened,
playlists: totalPlaylistsListened,
);

View File

@ -6,6 +6,7 @@ import 'package:spotube/provider/history/state.dart';
final playbackHistoryTopDurationProvider =
StateProvider((ref) => HistoryDuration.days7);
final playbackHistoryTopProvider =
Provider.family((ref, HistoryDuration durationState) {
final grouped = ref.watch(playbackHistoryGroupedProvider);

View File

@ -11,7 +11,7 @@ class MobileAudioService extends BaseAudioHandler {
AudioSession? session;
final ProxyPlaylistNotifier playlistNotifier;
// ignore: invalid_use_of_protected_member
// ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member
ProxyPlaylist get playlist => playlistNotifier.state;
MobileAudioService(this.playlistNotifier) {
@ -135,7 +135,7 @@ class MobileAudioService extends BaseAudioHandler {
playing: audioPlayer.isPlaying,
updatePosition: position,
bufferedPosition: await audioPlayer.bufferedPosition ?? Duration.zero,
shuffleMode: await audioPlayer.isShuffled == true
shuffleMode: audioPlayer.isShuffled == true
? AudioServiceShuffleMode.all
: AudioServiceShuffleMode.none,
repeatMode: (audioPlayer.loopMode).toAudioServiceRepeatMode(),