mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-12-10 09:07:29 +00:00
feat: add stream money calculation
This commit is contained in:
parent
858bbbb20d
commit
dcb4c0a018
@ -1,3 +1,8 @@
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
final compactNumberFormatter = NumberFormat.compact();
|
final compactNumberFormatter = NumberFormat.compact();
|
||||||
|
final usdFormatter = NumberFormat.compactCurrency(
|
||||||
|
locale: 'en-US',
|
||||||
|
symbol: r"$",
|
||||||
|
decimalDigits: 2,
|
||||||
|
);
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.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/components/stats/summary/summary_card.dart';
|
||||||
import 'package:spotube/extensions/constrains.dart';
|
import 'package:spotube/extensions/constrains.dart';
|
||||||
import 'package:spotube/provider/history/summary.dart';
|
import 'package:spotube/provider/history/summary.dart';
|
||||||
@ -32,7 +33,7 @@ class StatsPageSummarySection extends HookConsumerWidget {
|
|||||||
title: summary.duration.inMinutes.toDouble(),
|
title: summary.duration.inMinutes.toDouble(),
|
||||||
unit: "minutes",
|
unit: "minutes",
|
||||||
description: 'Listened to music',
|
description: 'Listened to music',
|
||||||
color: Colors.green,
|
color: Colors.purple,
|
||||||
),
|
),
|
||||||
SummaryCard(
|
SummaryCard(
|
||||||
title: summary.tracks.toDouble(),
|
title: summary.tracks.toDouble(),
|
||||||
@ -40,6 +41,12 @@ class StatsPageSummarySection extends HookConsumerWidget {
|
|||||||
description: 'Streamed overall',
|
description: 'Streamed overall',
|
||||||
color: Colors.lightBlue,
|
color: Colors.lightBlue,
|
||||||
),
|
),
|
||||||
|
SummaryCard.unformatted(
|
||||||
|
title: usdFormatter.format(summary.fees.toDouble()),
|
||||||
|
unit: "",
|
||||||
|
description: 'Worth of streams',
|
||||||
|
color: Colors.green,
|
||||||
|
),
|
||||||
SummaryCard(
|
SummaryCard(
|
||||||
title: summary.artists.toDouble(),
|
title: summary.artists.toDouble(),
|
||||||
unit: "artist's",
|
unit: "artist's",
|
||||||
|
|||||||
@ -4,13 +4,21 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:spotube/collections/formatters.dart';
|
import 'package:spotube/collections/formatters.dart';
|
||||||
|
|
||||||
class SummaryCard extends StatelessWidget {
|
class SummaryCard extends StatelessWidget {
|
||||||
final double title;
|
final String title;
|
||||||
final String unit;
|
final String unit;
|
||||||
final String description;
|
final String description;
|
||||||
|
|
||||||
final MaterialColor color;
|
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,
|
super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.unit,
|
required this.unit,
|
||||||
@ -35,7 +43,7 @@ class SummaryCard extends StatelessWidget {
|
|||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: compactNumberFormatter.format(title),
|
text: title,
|
||||||
style: textTheme.headlineLarge?.copyWith(
|
style: textTheme.headlineLarge?.copyWith(
|
||||||
color: color.shade900,
|
color: color.shade900,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
import 'package:spotube/extensions/track.dart';
|
|
||||||
import 'package:spotube/provider/proxy_playlist/proxy_playlist.dart';
|
import 'package:spotube/provider/proxy_playlist/proxy_playlist.dart';
|
||||||
import 'package:spotube/services/audio_player/loop_mode.dart';
|
import 'package:spotube/services/audio_player/loop_mode.dart';
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
import 'package:spotube/extensions/track.dart';
|
|
||||||
import 'package:spotube/services/sourced_track/sourced_track.dart';
|
import 'package:spotube/services/sourced_track/sourced_track.dart';
|
||||||
|
|
||||||
class CurrentPlaylist {
|
class CurrentPlaylist {
|
||||||
|
|||||||
@ -82,7 +82,7 @@ final connectServerProvider = FutureProvider((ref) async {
|
|||||||
.toJson(),
|
.toJson(),
|
||||||
);
|
);
|
||||||
channel.sink.add(
|
channel.sink.add(
|
||||||
WebSocketShuffleEvent(await audioPlayer.isShuffled).toJson(),
|
WebSocketShuffleEvent(audioPlayer.isShuffled).toJson(),
|
||||||
);
|
);
|
||||||
channel.sink.add(
|
channel.sink.add(
|
||||||
WebSocketLoopEvent(audioPlayer.loopMode).toJson(),
|
WebSocketLoopEvent(audioPlayer.loopMode).toJson(),
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:spotube/provider/history/history.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 playbackHistorySummaryProvider = Provider((ref) {
|
||||||
final (:tracks, :albums, :playlists) =
|
final (:tracks, :albums, :playlists) =
|
||||||
@ -43,10 +45,17 @@ final playbackHistorySummaryProvider = Provider((ref) {
|
|||||||
)
|
)
|
||||||
.length;
|
.length;
|
||||||
|
|
||||||
|
final tracksThisMonth = ref.watch(
|
||||||
|
playbackHistoryTopProvider(HistoryDuration.days30).select((s) => s.tracks),
|
||||||
|
);
|
||||||
|
|
||||||
|
final streams = tracksThisMonth.fold(0, (acc, el) => acc + el.count);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
duration: totalDurationListened,
|
duration: totalDurationListened,
|
||||||
tracks: totalTracksListened,
|
tracks: totalTracksListened,
|
||||||
artists: totalArtistsListened,
|
artists: totalArtistsListened,
|
||||||
|
fees: streams * 0.005, // Spotify pays $0.003 to $0.005
|
||||||
albums: totalAlbumsListened,
|
albums: totalAlbumsListened,
|
||||||
playlists: totalPlaylistsListened,
|
playlists: totalPlaylistsListened,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import 'package:spotube/provider/history/state.dart';
|
|||||||
|
|
||||||
final playbackHistoryTopDurationProvider =
|
final playbackHistoryTopDurationProvider =
|
||||||
StateProvider((ref) => HistoryDuration.days7);
|
StateProvider((ref) => HistoryDuration.days7);
|
||||||
|
|
||||||
final playbackHistoryTopProvider =
|
final playbackHistoryTopProvider =
|
||||||
Provider.family((ref, HistoryDuration durationState) {
|
Provider.family((ref, HistoryDuration durationState) {
|
||||||
final grouped = ref.watch(playbackHistoryGroupedProvider);
|
final grouped = ref.watch(playbackHistoryGroupedProvider);
|
||||||
|
|||||||
@ -11,7 +11,7 @@ class MobileAudioService extends BaseAudioHandler {
|
|||||||
AudioSession? session;
|
AudioSession? session;
|
||||||
final ProxyPlaylistNotifier playlistNotifier;
|
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;
|
ProxyPlaylist get playlist => playlistNotifier.state;
|
||||||
|
|
||||||
MobileAudioService(this.playlistNotifier) {
|
MobileAudioService(this.playlistNotifier) {
|
||||||
@ -135,7 +135,7 @@ class MobileAudioService extends BaseAudioHandler {
|
|||||||
playing: audioPlayer.isPlaying,
|
playing: audioPlayer.isPlaying,
|
||||||
updatePosition: position,
|
updatePosition: position,
|
||||||
bufferedPosition: await audioPlayer.bufferedPosition ?? Duration.zero,
|
bufferedPosition: await audioPlayer.bufferedPosition ?? Duration.zero,
|
||||||
shuffleMode: await audioPlayer.isShuffled == true
|
shuffleMode: audioPlayer.isShuffled == true
|
||||||
? AudioServiceShuffleMode.all
|
? AudioServiceShuffleMode.all
|
||||||
: AudioServiceShuffleMode.none,
|
: AudioServiceShuffleMode.none,
|
||||||
repeatMode: (audioPlayer.loopMode).toAudioServiceRepeatMode(),
|
repeatMode: (audioPlayer.loopMode).toAudioServiceRepeatMode(),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user