diff --git a/android/gradle.properties b/android/gradle.properties index bc2d95e8567abcfd41c26ebeb95fced48f43e773..818e87b23b224ced309ae5c147e5ed827826e237 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.1 -app.versionCode=1 +app.versionName=0.0.2 +app.versionCode=2 diff --git a/assets/translations/en.json b/assets/translations/en.json index 022a5ae9c107342dd3ab1c3bfab8e8ffcb9dee49..1ec64c12eb29a3f1441a24c8ed7ab6bad0ab25e8 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -1,5 +1,11 @@ { "app_name": "Scrobbles", - "sample_content": "Fake sample content" -} \ No newline at end of file + "global_statistics": "Global statistics", + "statistics_total_scrobbles_count": "Total scrobbles count:", + "statistics_selected_period": "On last {daysCount} days:", + "statistics_recent_scrobbles_count": "Scrobbles:", + "statistics_discoveries": "Discoveries:", + "statistics_discoveries_artists": "artists", + "statistics_discoveries_tracks": "tracks" +} diff --git a/assets/translations/fr.json b/assets/translations/fr.json index e533058a68046c5cf1df341e3ade1b8b2e76f11a..9800cee1185a367e6228019a778cd86b6d6b0052 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -1,5 +1,11 @@ { "app_name": "Scrobbles", - "sample_content": "Contenu provisoire " -} \ No newline at end of file + "global_statistics": "Statistiques globales d'écoutes", + "statistics_total_scrobbles_count": "Nombre total d'écoutes :", + "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" +} diff --git a/fastlane/metadata/android/en-US/changelogs/2.txt b/fastlane/metadata/android/en-US/changelogs/2.txt new file mode 100644 index 0000000000000000000000000000000000000000..04186cbbed874d38789b310c002307f657ae1939 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/2.txt @@ -0,0 +1 @@ +Get and display simple statistics data from API diff --git a/fastlane/metadata/android/fr-FR/changelogs/2.txt b/fastlane/metadata/android/fr-FR/changelogs/2.txt new file mode 100644 index 0000000000000000000000000000000000000000..00d3e35cd0d47e719e7a99710fb64c0ff137bbb1 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/2.txt @@ -0,0 +1 @@ +Récupère et affiche des statistiques simples depuis l'API diff --git a/lib/models/statistics.dart b/lib/models/statistics.dart new file mode 100644 index 0000000000000000000000000000000000000000..70ff49df216d68db8a170b77921e72f04b1d9477 --- /dev/null +++ b/lib/models/statistics.dart @@ -0,0 +1,25 @@ +class StatisticsData { + final int totalCount; + final int recentCount; + final int firstPlayedArtistsCount; + final int firstPlayedTracksCount; + final int selectedPeriod; + + const StatisticsData({ + required this.totalCount, + required this.recentCount, + required this.firstPlayedArtistsCount, + required this.firstPlayedTracksCount, + required this.selectedPeriod, + }); + + 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, + ); + } +} diff --git a/lib/network/scrobbles_api.dart b/lib/network/scrobbles_api.dart new file mode 100644 index 0000000000000000000000000000000000000000..102a8175f7436126cbc1c1e6a8860482ec363b21 --- /dev/null +++ b/lib/network/scrobbles_api.dart @@ -0,0 +1,18 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +import '../models/statistics.dart'; + +class ScrobblesApi { + static String baseUrl = 'https://scrobble.harrault.fr'; + + static Future<StatisticsData> fetchStatistics() async { + final response = await http.get(Uri.parse(baseUrl + '/stats')); + + if (response.statusCode == 200) { + return StatisticsData.fromJson(jsonDecode(response.body) as Map<String, dynamic>); + } else { + throw Exception('Failed to get data from API.'); + } + } +} diff --git a/lib/ui/screens/main_screen.dart b/lib/ui/screens/main_screen.dart index 7c6a8f9fa236aa7de79c3f174d45ce5803366ca3..04f8d90c1ed6fb27cffc45a8d9bb9c57339bd93b 100644 --- a/lib/ui/screens/main_screen.dart +++ b/lib/ui/screens/main_screen.dart @@ -1,7 +1,7 @@ -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import '../widgets/header.dart'; +import '../widgets/main_screen/statistics.dart'; class MainScreen extends StatelessWidget { const MainScreen({super.key}); @@ -15,8 +15,7 @@ class MainScreen extends StatelessWidget { physics: const BouncingScrollPhysics(), children: <Widget>[ const Header(text: 'app_name'), - const SizedBox(height: 8), - Text(tr('sample_content')), + const Statistics(), const SizedBox(height: 36), ], ), diff --git a/lib/ui/widgets/main_screen/statistics.dart b/lib/ui/widgets/main_screen/statistics.dart new file mode 100644 index 0000000000000000000000000000000000000000..fbe556a257dbf1200ac5b50621576582f7e44b87 --- /dev/null +++ b/lib/ui/widgets/main_screen/statistics.dart @@ -0,0 +1,76 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +import '../../../models/statistics.dart'; +import '../../../network/scrobbles_api.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( + '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 Text('${snapshot.error}'); + } + + return const CircularProgressIndicator(); + }, + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 307e7a3551b7bb03020b135cef2c6e8494646455..b999423b57d2df0826c5e29ad20d24a920e6bd85 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.2" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" characters: dependency: transitive description: @@ -80,6 +88,22 @@ packages: description: flutter source: sdk version: "0.0.0" + http: + dependency: "direct main" + description: + name: http + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" intl: dependency: transitive description: @@ -213,6 +237,38 @@ packages: description: flutter source: sdk version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 28d225f1067732da4a690727ca8dbec8ee15210a..f163219625e00802a92540f50901ef76a0d87d41 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: Display scrobbles data and charts publish_to: 'none' -version: 0.0.1+1 +version: 0.0.2+2 environment: sdk: '^3.0.0' @@ -13,6 +13,7 @@ dependencies: sdk: flutter easy_localization: ^3.0.1 + http: ^1.1.0 flutter: uses-material-design: false