From 66edad8fbf40734dd4adebe9e007c615694a5613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr> Date: Thu, 26 Oct 2023 13:32:25 +0200 Subject: [PATCH] Improve global statistics widget --- android/gradle.properties | 4 +- assets/translations/en.json | 10 +-- assets/translations/fr.json | 10 +-- .../metadata/android/en-US/changelogs/6.txt | 1 + .../metadata/android/fr-FR/changelogs/6.txt | 1 + lib/models/statistics.dart | 41 +++++++-- lib/ui/screens/main_screen.dart | 4 +- lib/ui/widgets/main_screen/statistics.dart | 83 ------------------- .../widgets/main_screen/statistics_card.dart | 46 ++++++++++ .../main_screen/statistics_content.dart | 77 +++++++++++++++++ pubspec.yaml | 2 +- 11 files changed, 171 insertions(+), 108 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/6.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/6.txt delete mode 100644 lib/ui/widgets/main_screen/statistics.dart create mode 100644 lib/ui/widgets/main_screen/statistics_card.dart create mode 100644 lib/ui/widgets/main_screen/statistics_content.dart diff --git a/android/gradle.properties b/android/gradle.properties index aa51064..135006f 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -app.versionName=0.0.5 -app.versionCode=5 +app.versionName=0.0.6 +app.versionCode=6 diff --git a/assets/translations/en.json b/assets/translations/en.json index d829a40..31c1591 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -2,11 +2,9 @@ "app_name": "Scrobbles", "global_statistics": "Global statistics", - "statistics_total_scrobbles_count": "Total scrobbles count:", - "statistics_last_scrobble": "Last scrobble: ", + "statistics_total_scrobbles_count": "Total scrobbles count: {count}", + "statistics_last_scrobble": "Last scrobble: {datetime}", "statistics_selected_period": "On last {daysCount} days:", - "statistics_recent_scrobbles_count": "Scrobbles:", - "statistics_discoveries": "Discoveries:", - "statistics_discoveries_artists": "artists", - "statistics_discoveries_tracks": "tracks" + "statistics_recent_scrobbles_count": "Scrobbles: {count}", + "statistics_discoveries": "Discoveries: {artistsCount} artists / {tracksCount} tracks" } diff --git a/assets/translations/fr.json b/assets/translations/fr.json index d6bb8b0..e1594f2 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -2,11 +2,9 @@ "app_name": "Scrobbles", "global_statistics": "Statistiques globales d'écoutes", - "statistics_total_scrobbles_count": "Nombre total d'écoutes :", - "statistics_last_scrobble": "Dernière écoute :", + "statistics_total_scrobbles_count": "Nombre total d'écoutes : {count}", + "statistics_last_scrobble": "Dernière écoute : {datetime}", "statistics_selected_period": "Sur les {daysCount} derniers jours:", - "statistics_recent_scrobbles_count": "Écoutes :", - "statistics_discoveries": "Découvertes :", - "statistics_discoveries_artists": "artistes", - "statistics_discoveries_tracks": "morceaux" + "statistics_recent_scrobbles_count": "Écoutes : {count}", + "statistics_discoveries": "Découvertes : {artistsCount} artistes / {tracksCount} morceaux" } diff --git a/fastlane/metadata/android/en-US/changelogs/6.txt b/fastlane/metadata/android/en-US/changelogs/6.txt new file mode 100644 index 0000000..0205c6b --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/6.txt @@ -0,0 +1 @@ +Improve global statistic bloc diff --git a/fastlane/metadata/android/fr-FR/changelogs/6.txt b/fastlane/metadata/android/fr-FR/changelogs/6.txt new file mode 100644 index 0000000..e2050cd --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/6.txt @@ -0,0 +1 @@ +Amélioration du bloc de statistiques globales diff --git a/lib/models/statistics.dart b/lib/models/statistics.dart index aebb596..0654213 100644 --- a/lib/models/statistics.dart +++ b/lib/models/statistics.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + class StatisticsData { final int totalCount; final int recentCount; @@ -17,14 +19,37 @@ class StatisticsData { factory StatisticsData.fromJson(Map<String, dynamic> json) { return StatisticsData( - totalCount: json['totalCount'] as int, - recentCount: json['recentCount'] as int, - firstPlayedArtistsCount: json['firstPlayedArtistsCount'] as int, - firstPlayedTracksCount: json['firstPlayedTracksCount'] as int, - selectedPeriod: json['selectedPeriod'] as int, - lastScrobble: DateTime.parse( - json['lastScrobble']['date'], - ), + totalCount: json['totalCount'] != null ? json['totalCount'] as int : 0, + recentCount: json['recentCount'] != null ? json['recentCount'] as int : 0, + firstPlayedArtistsCount: + json['firstPlayedArtistsCount'] != null ? json['firstPlayedArtistsCount'] as int : 0, + firstPlayedTracksCount: + json['firstPlayedTracksCount'] != null ? json['firstPlayedTracksCount'] as int : 0, + selectedPeriod: json['selectedPeriod'] != null ? json['selectedPeriod'] as int : 0, + lastScrobble: (json['lastScrobble'] != null && json['lastScrobble']['date'] != null) + ? DateTime.parse( + json['lastScrobble']['date'], + ) + : DateTime.now(), ); } + + factory StatisticsData.createEmpty() { + return StatisticsData.fromJson({}); + } + + String toString() { + Map<String, dynamic> map = { + 'totalCount': this.totalCount, + 'recentCount': this.recentCount, + 'firstPlayedArtistsCount': this.firstPlayedArtistsCount, + 'firstPlayedTracksCount': this.firstPlayedTracksCount, + 'selectedPeriod': this.selectedPeriod, + 'lastScrobble': { + 'date': this.lastScrobble.toString(), + }, + }; + + return jsonEncode(map); + } } diff --git a/lib/ui/screens/main_screen.dart b/lib/ui/screens/main_screen.dart index 04f8d90..94275ca 100644 --- a/lib/ui/screens/main_screen.dart +++ b/lib/ui/screens/main_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import '../widgets/header.dart'; -import '../widgets/main_screen/statistics.dart'; +import '../widgets/main_screen/statistics_card.dart'; class MainScreen extends StatelessWidget { const MainScreen({super.key}); @@ -15,7 +15,7 @@ class MainScreen extends StatelessWidget { physics: const BouncingScrollPhysics(), children: <Widget>[ const Header(text: 'app_name'), - const Statistics(), + const StatisticsCard(), const SizedBox(height: 36), ], ), diff --git a/lib/ui/widgets/main_screen/statistics.dart b/lib/ui/widgets/main_screen/statistics.dart deleted file mode 100644 index 0dd1aeb..0000000 --- a/lib/ui/widgets/main_screen/statistics.dart +++ /dev/null @@ -1,83 +0,0 @@ -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; - -import '../../../models/statistics.dart'; -import '../../../network/scrobbles_api.dart'; -import '../../../ui/widgets/error.dart'; - -class Statistics extends StatelessWidget { - const Statistics({super.key}); - - @override - Widget build(BuildContext context) { - late Future<StatisticsData> futureAlbum = ScrobblesApi.fetchStatistics(); - - return FutureBuilder<StatisticsData>( - future: futureAlbum, - builder: (context, snapshot) { - if (snapshot.hasData) { - final TextTheme textTheme = Theme.of(context).primaryTextTheme; - - return Card( - elevation: 2, - shadowColor: Theme.of(context).colorScheme.shadow, - color: Theme.of(context).colorScheme.primary, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(12))), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: <Widget>[ - Text( - tr('global_statistics'), - style: textTheme.titleLarge!.apply(fontWeightDelta: 2), - ), - Text( - tr('statistics_total_scrobbles_count') + - ' ' + - snapshot.data!.totalCount.toString(), - style: textTheme.bodyMedium, - ), - Text( - tr('statistics_last_scrobble') + - ' ' + - DateFormat().format(snapshot.data!.lastScrobble), - style: textTheme.bodyMedium, - ), - Text( - 'statistics_selected_period', - style: textTheme.bodyMedium, - ).tr(namedArgs: {'daysCount': snapshot.data!.selectedPeriod.toString()}), - Text( - tr('statistics_recent_scrobbles_count') + - ' ' + - snapshot.data!.recentCount.toString(), - style: textTheme.bodyMedium, - ), - Text( - tr('statistics_discoveries') + - ' ' + - snapshot.data!.firstPlayedArtistsCount.toString() + - ' ' + - tr('statistics_discoveries_artists') + - ' / ' + - snapshot.data!.firstPlayedTracksCount.toString() + - ' ' + - tr('statistics_discoveries_tracks'), - style: textTheme.bodyMedium, - ), - ], - ), - ), - ); - } else if (snapshot.hasError) { - return ShowErrorWidget(message: '${snapshot.error}'); - } - - return const CircularProgressIndicator(); - }, - ); - } -} diff --git a/lib/ui/widgets/main_screen/statistics_card.dart b/lib/ui/widgets/main_screen/statistics_card.dart new file mode 100644 index 0000000..ae0a4e9 --- /dev/null +++ b/lib/ui/widgets/main_screen/statistics_card.dart @@ -0,0 +1,46 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; + +import '../../../models/statistics.dart'; +import '../../../network/scrobbles_api.dart'; +import '../../../ui/widgets/error.dart'; +import '../../../ui/widgets/main_screen/statistics_content.dart'; + +class StatisticsCard extends StatelessWidget { + const StatisticsCard({super.key}); + + @override + Widget build(BuildContext context) { + late Future<StatisticsData> futureAlbum = ScrobblesApi.fetchStatistics(); + + return FutureBuilder<StatisticsData>( + future: futureAlbum, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + return Card( + elevation: 2, + shadowColor: Theme.of(context).colorScheme.shadow, + color: Theme.of(context).colorScheme.primary, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: StatisticsContent( + statistics: snapshot.hasData + ? StatisticsData.fromJson(jsonDecode(snapshot.data.toString())) + : StatisticsData.createEmpty(), + isLoading: !snapshot.hasData, + ), + ), + ); + }, + ); + } +} diff --git a/lib/ui/widgets/main_screen/statistics_content.dart b/lib/ui/widgets/main_screen/statistics_content.dart new file mode 100644 index 0000000..c4659e4 --- /dev/null +++ b/lib/ui/widgets/main_screen/statistics_content.dart @@ -0,0 +1,77 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +import '../../../models/statistics.dart'; + +class StatisticsContent extends StatelessWidget { + final StatisticsData statistics; + final bool isLoading; + + const StatisticsContent({super.key, required this.statistics, required this.isLoading}); + + @override + Widget build(BuildContext context) { + final TextTheme textTheme = Theme.of(context).primaryTextTheme; + + final String placeholder = '⏳'; + + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Text( + 'global_statistics', + style: textTheme.titleLarge!.apply(fontWeightDelta: 2), + ).tr(), + Text( + 'statistics_total_scrobbles_count', + style: textTheme.bodyMedium, + ).tr( + namedArgs: { + 'count': this.isLoading ? placeholder : this.statistics.totalCount.toString(), + }, + ), + Text( + 'statistics_last_scrobble', + style: textTheme.bodyMedium, + ).tr( + namedArgs: { + 'datetime': this.isLoading + ? placeholder + : DateFormat().format(this.statistics.lastScrobble), + }, + ), + Text( + 'statistics_selected_period', + style: textTheme.bodyMedium, + ).tr( + namedArgs: { + 'daysCount': + this.isLoading ? placeholder : this.statistics.selectedPeriod.toString(), + }, + ), + Text( + 'statistics_recent_scrobbles_count', + style: textTheme.bodyMedium, + ).tr( + namedArgs: { + 'count': this.isLoading ? placeholder : this.statistics.recentCount.toString(), + }, + ), + Text( + 'statistics_discoveries', + style: textTheme.bodyMedium, + ).tr( + namedArgs: { + 'artistsCount': this.isLoading + ? placeholder + : this.statistics.firstPlayedArtistsCount.toString(), + 'tracksCount': this.isLoading + ? placeholder + : this.statistics.firstPlayedTracksCount.toString(), + }, + ), + ], + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index e80d1d1..3443b82 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: Display scrobbles data and charts publish_to: 'none' -version: 0.0.5+5 +version: 0.0.6+6 environment: sdk: '^3.0.0' -- GitLab