From e7244ad8e3e0eef793857cc4d1faec5e965620be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr> Date: Sat, 11 Nov 2023 23:30:17 +0100 Subject: [PATCH] Clean/move/rename/refactor code --- android/gradle.properties | 4 +- assets/translations/en.json | 8 +-- assets/translations/fr.json | 8 +-- .../metadata/android/en-US/changelogs/28.txt | 1 + .../metadata/android/fr-FR/changelogs/28.txt | 1 + lib/main.dart | 5 +- lib/models/counts_by_day.dart | 8 +-- lib/models/counts_by_hour.dart | 6 +- lib/models/discoveries.dart | 10 +-- lib/models/statistics_global.dart | 8 +-- lib/models/statistics_recent.dart | 16 +++-- lib/models/timeline.dart | 10 +-- lib/models/topartists.dart | 10 +-- .../{scrobbles_api.dart => scrobbles.dart} | 14 ++-- ...scoveries_screen.dart => discoveries.dart} | 12 ++-- lib/ui/screens/home.dart | 37 +++++++++++ lib/ui/screens/home_screen.dart | 37 ----------- ...statistics_screen.dart => statistics.dart} | 16 ++--- .../skeleton_screen.dart => skeleton.dart} | 19 +++--- .../custom_bar_chart.dart | 5 +- .../custom_line_chart.dart | 3 +- lib/ui/widgets/app_bar.dart | 4 +- lib/ui/widgets/bottom_nav_bar.dart | 2 +- lib/ui/widgets/card_content.dart | 43 ++++++++++++ lib/ui/widgets/cards/counts_by_day.dart | 44 +++++++++++++ lib/ui/widgets/cards/counts_by_hour.dart | 44 +++++++++++++ lib/ui/widgets/cards/discoveries.dart | 66 +++++++++++++++++++ lib/ui/widgets/cards/statistics_global.dart | 39 +++++++++++ lib/ui/widgets/cards/statistics_recent.dart | 45 +++++++++++++ lib/ui/widgets/cards/timeline.dart | 51 ++++++++++++++ lib/ui/widgets/cards/top_artists.dart | 44 +++++++++++++ .../counts_by_day.dart} | 30 +++++---- .../counts_by_hour.dart} | 32 +++++---- .../discoveries_artists.dart} | 30 +++++---- .../discoveries_tracks.dart} | 30 +++++---- .../timeline_counts.dart} | 28 +++++--- .../timeline_eclecticism.dart} | 41 ++++++------ .../top_artists.dart} | 49 +++++++------- .../statistics_global.dart} | 13 ++-- .../statistics_recent.dart} | 22 ++----- .../widgets/{header.dart => header_app.dart} | 4 +- .../main_screen/counts_by_day_card.dart | 48 -------------- .../main_screen/counts_by_day_content.dart | 43 ------------ .../main_screen/counts_by_hour_card.dart | 49 -------------- .../main_screen/counts_by_hour_content.dart | 43 ------------ .../widgets/main_screen/discoveries_card.dart | 61 ----------------- .../discoveries_content_artists.dart | 43 ------------ .../discoveries_content_tracks.dart | 43 ------------ .../main_screen/statistics_global_card.dart | 46 ------------- .../main_screen/statistics_recent_card.dart | 48 -------------- lib/ui/widgets/main_screen/timeline_card.dart | 48 -------------- .../widgets/main_screen/timeline_content.dart | 51 -------------- .../widgets/main_screen/topartists_card.dart | 48 -------------- .../main_screen/topartists_content.dart | 43 ------------ pubspec.yaml | 2 +- 55 files changed, 655 insertions(+), 860 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/28.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/28.txt rename lib/network/{scrobbles_api.dart => scrobbles.dart} (89%) rename lib/ui/screens/{discoveries_screen.dart => discoveries.dart} (59%) create mode 100644 lib/ui/screens/home.dart delete mode 100644 lib/ui/screens/home_screen.dart rename lib/ui/screens/{statistics_screen.dart => statistics.dart} (54%) rename lib/ui/{screens/skeleton_screen.dart => skeleton.dart} (80%) rename lib/ui/widgets/{charts => abstracts}/custom_bar_chart.dart (97%) rename lib/ui/widgets/{charts => abstracts}/custom_line_chart.dart (95%) create mode 100644 lib/ui/widgets/card_content.dart create mode 100644 lib/ui/widgets/cards/counts_by_day.dart create mode 100644 lib/ui/widgets/cards/counts_by_hour.dart create mode 100644 lib/ui/widgets/cards/discoveries.dart create mode 100644 lib/ui/widgets/cards/statistics_global.dart create mode 100644 lib/ui/widgets/cards/statistics_recent.dart create mode 100644 lib/ui/widgets/cards/timeline.dart create mode 100644 lib/ui/widgets/cards/top_artists.dart rename lib/ui/widgets/{main_screen/counts_by_day_chart.dart => charts/counts_by_day.dart} (76%) rename lib/ui/widgets/{main_screen/counts_by_hour_chart.dart => charts/counts_by_hour.dart} (63%) rename lib/ui/widgets/{main_screen/discoveries_chart_artists.dart => charts/discoveries_artists.dart} (61%) rename lib/ui/widgets/{main_screen/discoveries_chart_tracks.dart => charts/discoveries_tracks.dart} (61%) rename lib/ui/widgets/{main_screen/timeline_chart_counts.dart => charts/timeline_counts.dart} (62%) rename lib/ui/widgets/{main_screen/timeline_chart_eclecticism.dart => charts/timeline_eclecticism.dart} (66%) rename lib/ui/widgets/{main_screen/topartists_chart.dart => charts/top_artists.dart} (71%) rename lib/ui/widgets/{main_screen/statistics_global_content.dart => content/statistics_global.dart} (77%) rename lib/ui/widgets/{main_screen/statistics_recent_content.dart => content/statistics_recent.dart} (64%) rename lib/ui/widgets/{header.dart => header_app.dart} (78%) delete mode 100644 lib/ui/widgets/main_screen/counts_by_day_card.dart delete mode 100644 lib/ui/widgets/main_screen/counts_by_day_content.dart delete mode 100644 lib/ui/widgets/main_screen/counts_by_hour_card.dart delete mode 100644 lib/ui/widgets/main_screen/counts_by_hour_content.dart delete mode 100644 lib/ui/widgets/main_screen/discoveries_card.dart delete mode 100644 lib/ui/widgets/main_screen/discoveries_content_artists.dart delete mode 100644 lib/ui/widgets/main_screen/discoveries_content_tracks.dart delete mode 100644 lib/ui/widgets/main_screen/statistics_global_card.dart delete mode 100644 lib/ui/widgets/main_screen/statistics_recent_card.dart delete mode 100644 lib/ui/widgets/main_screen/timeline_card.dart delete mode 100644 lib/ui/widgets/main_screen/timeline_content.dart delete mode 100644 lib/ui/widgets/main_screen/topartists_card.dart delete mode 100644 lib/ui/widgets/main_screen/topartists_content.dart diff --git a/android/gradle.properties b/android/gradle.properties index 408253c..e644338 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.27 -app.versionCode=27 +app.versionName=0.0.28 +app.versionCode=28 diff --git a/assets/translations/en.json b/assets/translations/en.json index a2823eb..3f4f688 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -9,16 +9,16 @@ "statistics_total_scrobbles_count": "Total scrobbles count: {count}", "statistics_last_scrobble": "Last scrobble: {datetime}", - "recent_statistics": "Recent statistics", - "statistics_selected_period": "On last {daysCount} days:", + "recent_statistics": "Recent statistics ({daysCount} days)", "statistics_recent_scrobbles_count_and_discoveries": "{count} scrobbles and {artistsCount} artists / {tracksCount} tracks discovered.", "timeline_title": "Recent scrobbles ({daysCount} days)", "counts_by_day": "Counts by day ({daysCount} days)", "counts_by_hour": "Counts by hour ({daysCount} days)", - "discoveries_artists_title": "Artists discoveries ({daysCount} days)", - "discoveries_tracks_title": "Tracks discoveries ({daysCount} days)", + "discoveries_title": "Discoveries ({daysCount} days)", + "discoveries_artists_title": "Artists", + "discoveries_tracks_title": "Tracks", "top_artists_title": "Top artists ({daysCount} days)", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 67d019d..2f2fb63 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -9,16 +9,16 @@ "statistics_total_scrobbles_count": "Nombre total d'écoutes : {count}", "statistics_last_scrobble": "Dernière écoute : {datetime}", - "recent_statistics": "Statistiques récentes", - "statistics_selected_period": "Sur les {daysCount} derniers jours :", + "recent_statistics": "Statistiques récentes ({daysCount} jours)", "statistics_recent_scrobbles_count_and_discoveries": "{count} écoutes et {artistsCount} artistes / {tracksCount} morceaux découverts.", "timeline_title": "Écoutes récentes ({daysCount} jours)", "counts_by_day": "Écoutes par jour ({daysCount} jours)", "counts_by_hour": "Écoutes par heure ({daysCount} jours)", - "discoveries_artists_title": "Artistes découverts ({daysCount} jours)", - "discoveries_tracks_title": "Morceaux découverts ({daysCount} jours)", + "discoveries_title": "Découvertes ({daysCount} jours)", + "discoveries_artists_title": "Artistes", + "discoveries_tracks_title": "Morceaux", "top_artists_title": "Top artistes ({daysCount} jours)", diff --git a/fastlane/metadata/android/en-US/changelogs/28.txt b/fastlane/metadata/android/en-US/changelogs/28.txt new file mode 100644 index 0000000..b2da89f --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/28.txt @@ -0,0 +1 @@ +Clean/improve/refactor code. diff --git a/fastlane/metadata/android/fr-FR/changelogs/28.txt b/fastlane/metadata/android/fr-FR/changelogs/28.txt new file mode 100644 index 0000000..92d90dd --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/28.txt @@ -0,0 +1 @@ +Nettoyage/améliorations/refactorisations de code. diff --git a/lib/main.dart b/lib/main.dart index c6ec2e7..da465fa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,9 +6,8 @@ import 'package:hive/hive.dart'; import 'package:hydrated_bloc/hydrated_bloc.dart'; import 'package:path_provider/path_provider.dart'; -import 'config/theme.dart'; - -import 'ui/screens/skeleton_screen.dart'; +import 'package:scrobbles/config/theme.dart'; +import 'package:scrobbles/ui/skeleton.dart'; void main() async { /// Initialize packages diff --git a/lib/models/counts_by_day.dart b/lib/models/counts_by_day.dart index cff1d53..fcb4551 100644 --- a/lib/models/counts_by_day.dart +++ b/lib/models/counts_by_day.dart @@ -7,11 +7,11 @@ class CountsByDayData { required this.data, }); - factory CountsByDayData.fromJson(Map<String, dynamic> json) { + factory CountsByDayData.fromJson(Map<String, dynamic>? json) { Map<int, double> data = {}; - if (json['counts-by-day'] != null) { - json['counts-by-day'].keys.forEach((day) { + if (json?['counts-by-day'] != null) { + json?['counts-by-day'].keys.forEach((day) { data[int.parse(day)] = double.parse(json['counts-by-day'][day].toString()); }); } @@ -20,7 +20,7 @@ class CountsByDayData { } factory CountsByDayData.createEmpty() { - return CountsByDayData.fromJson({}); + return CountsByDayData.fromJson({'counts-by-day': {}}); } String toString() { diff --git a/lib/models/counts_by_hour.dart b/lib/models/counts_by_hour.dart index 1285752..f0c6d50 100644 --- a/lib/models/counts_by_hour.dart +++ b/lib/models/counts_by_hour.dart @@ -7,11 +7,11 @@ class CountsByHourData { required this.data, }); - factory CountsByHourData.fromJson(Map<String, dynamic> json) { + factory CountsByHourData.fromJson(Map<String, dynamic>? json) { Map<int, double> data = {}; - if (json['counts-by-hour'] != null) { - json['counts-by-hour'].keys.forEach((day) { + if (json?['counts-by-hour'] != null) { + json?['counts-by-hour'].keys.forEach((day) { if (int.parse(day) != 24) { data[int.parse(day)] = double.parse(json['counts-by-hour'][day].toString()); } diff --git a/lib/models/discoveries.dart b/lib/models/discoveries.dart index 3e67649..14f5819 100644 --- a/lib/models/discoveries.dart +++ b/lib/models/discoveries.dart @@ -6,10 +6,10 @@ class DiscoveriesDataValue { const DiscoveriesDataValue({required this.newArtistsCount, required this.newTracksCount}); - factory DiscoveriesDataValue.fromJson(Map<String, dynamic> json) { + factory DiscoveriesDataValue.fromJson(Map<String, dynamic>? json) { return DiscoveriesDataValue( - newArtistsCount: json['new-artists'] as int, - newTracksCount: json['new-tracks'] as int, + newArtistsCount: json?['new-artists'] as int, + newTracksCount: json?['new-tracks'] as int, ); } } @@ -21,10 +21,10 @@ class DiscoveriesData { required this.data, }); - factory DiscoveriesData.fromJson(Map<String, dynamic> json) { + factory DiscoveriesData.fromJson(Map<String, dynamic>? json) { Map<String, DiscoveriesDataValue> data = {}; - json.keys.forEach((date) { + json?.keys.forEach((date) { DiscoveriesDataValue value = DiscoveriesDataValue( newArtistsCount: json[date]['new-artists'] as int, newTracksCount: json[date]['new-tracks'] as int, diff --git a/lib/models/statistics_global.dart b/lib/models/statistics_global.dart index 0610e27..4eb90fc 100644 --- a/lib/models/statistics_global.dart +++ b/lib/models/statistics_global.dart @@ -9,12 +9,12 @@ class StatisticsGlobalData { required this.lastScrobble, }); - factory StatisticsGlobalData.fromJson(Map<String, dynamic> json) { + factory StatisticsGlobalData.fromJson(Map<String, dynamic>? json) { return StatisticsGlobalData( - totalCount: json['totalCount'] != null ? json['totalCount'] as int : 0, - lastScrobble: (json['lastScrobble'] != null && json['lastScrobble']['date'] != null) + totalCount: (json?['totalCount'] != null) ? (json?['totalCount'] as int) : 0, + lastScrobble: (json?['lastScrobble'] != null && json?['lastScrobble']['date'] != null) ? DateTime.parse( - json['lastScrobble']['date'], + json?['lastScrobble']['date'], ) : DateTime.now(), ); diff --git a/lib/models/statistics_recent.dart b/lib/models/statistics_recent.dart index 218dd1f..d72173f 100644 --- a/lib/models/statistics_recent.dart +++ b/lib/models/statistics_recent.dart @@ -13,14 +13,16 @@ class StatisticsRecentData { required this.selectedPeriod, }); - factory StatisticsRecentData.fromJson(Map<String, dynamic> json) { + factory StatisticsRecentData.fromJson(Map<String, dynamic>? json) { return StatisticsRecentData( - 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, + 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, ); } diff --git a/lib/models/timeline.dart b/lib/models/timeline.dart index 1504233..b52a546 100644 --- a/lib/models/timeline.dart +++ b/lib/models/timeline.dart @@ -6,10 +6,10 @@ class TimelineDataValue { const TimelineDataValue({required this.counts, required this.eclecticism}); - factory TimelineDataValue.fromJson(Map<String, dynamic> json) { + factory TimelineDataValue.fromJson(Map<String, dynamic>? json) { return TimelineDataValue( - counts: json['counts'] as int, - eclecticism: json['eclecticism'] as int, + counts: json?['counts'] as int, + eclecticism: json?['eclecticism'] as int, ); } } @@ -21,10 +21,10 @@ class TimelineData { required this.data, }); - factory TimelineData.fromJson(Map<String, dynamic> json) { + factory TimelineData.fromJson(Map<String, dynamic>? json) { Map<String, TimelineDataValue> data = {}; - json.keys.forEach((date) { + json?.keys.forEach((date) { TimelineDataValue value = TimelineDataValue( counts: json[date]['counts'] as int, eclecticism: json[date]['eclecticism'] as int, diff --git a/lib/models/topartists.dart b/lib/models/topartists.dart index 52c06f2..9a7b418 100644 --- a/lib/models/topartists.dart +++ b/lib/models/topartists.dart @@ -6,10 +6,10 @@ class TopArtistsDataValue { const TopArtistsDataValue({required this.artistName, required this.count}); - factory TopArtistsDataValue.fromJson(Map<String, dynamic> json) { + factory TopArtistsDataValue.fromJson(Map<String, dynamic>? json) { return TopArtistsDataValue( - artistName: json['artistName'] as String, - count: json['count'] as int, + artistName: json?['artistName'] as String, + count: json?['count'] as int, ); } } @@ -21,10 +21,10 @@ class TopArtistsData { required this.topArtists, }); - factory TopArtistsData.fromJson(Map<String, dynamic> json) { + factory TopArtistsData.fromJson(Map<String, dynamic>? json) { List<TopArtistsDataValue> topArtists = []; - json['top-artists'].forEach((element) { + json?['top-artists'].forEach((element) { TopArtistsDataValue value = TopArtistsDataValue( artistName: element['artistName'] as String, count: element['count'] as int, diff --git a/lib/network/scrobbles_api.dart b/lib/network/scrobbles.dart similarity index 89% rename from lib/network/scrobbles_api.dart rename to lib/network/scrobbles.dart index 3efb3f6..ebfca8a 100644 --- a/lib/network/scrobbles_api.dart +++ b/lib/network/scrobbles.dart @@ -1,13 +1,13 @@ import 'dart:convert'; import 'package:http/http.dart' as http; -import '../models/counts_by_day.dart'; -import '../models/counts_by_hour.dart'; -import '../models/discoveries.dart'; -import '../models/statistics_global.dart'; -import '../models/statistics_recent.dart'; -import '../models/timeline.dart'; -import '../models/topartists.dart'; +import 'package:scrobbles/models/counts_by_day.dart'; +import 'package:scrobbles/models/counts_by_hour.dart'; +import 'package:scrobbles/models/discoveries.dart'; +import 'package:scrobbles/models/statistics_global.dart'; +import 'package:scrobbles/models/statistics_recent.dart'; +import 'package:scrobbles/models/timeline.dart'; +import 'package:scrobbles/models/topartists.dart'; class ScrobblesApi { static String baseUrl = 'https://scrobble.harrault.fr'; diff --git a/lib/ui/screens/discoveries_screen.dart b/lib/ui/screens/discoveries.dart similarity index 59% rename from lib/ui/screens/discoveries_screen.dart rename to lib/ui/screens/discoveries.dart index ca590c7..fd5f836 100644 --- a/lib/ui/screens/discoveries_screen.dart +++ b/lib/ui/screens/discoveries.dart @@ -1,15 +1,15 @@ import 'package:flutter/material.dart'; -import '../widgets/main_screen/discoveries_card.dart'; +import 'package:scrobbles/ui/widgets/cards/discoveries.dart'; -class DiscoveriesScreen extends StatefulWidget { - const DiscoveriesScreen({super.key}); +class ScreenDiscoveries extends StatefulWidget { + const ScreenDiscoveries({super.key}); @override - State<DiscoveriesScreen> createState() => _DiscoveriesScreenState(); + State<ScreenDiscoveries> createState() => _ScreenDiscoveriesState(); } -class _DiscoveriesScreenState extends State<DiscoveriesScreen> { +class _ScreenDiscoveriesState extends State<ScreenDiscoveries> { @override Widget build(BuildContext context) { return Material( @@ -19,7 +19,7 @@ class _DiscoveriesScreenState extends State<DiscoveriesScreen> { physics: const BouncingScrollPhysics(), children: <Widget>[ const SizedBox(height: 8), - const ChartDiscoveriesCard(), + const CardDiscoveries(), const SizedBox(height: 36), ], ), diff --git a/lib/ui/screens/home.dart b/lib/ui/screens/home.dart new file mode 100644 index 0000000..c2acc00 --- /dev/null +++ b/lib/ui/screens/home.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; + +import 'package:scrobbles/ui/widgets/cards/statistics_global.dart'; +import 'package:scrobbles/ui/widgets/cards/statistics_recent.dart'; +import 'package:scrobbles/ui/widgets/cards/timeline.dart'; +import 'package:scrobbles/ui/widgets/cards/top_artists.dart'; + +class ScreenHome extends StatefulWidget { + const ScreenHome({super.key}); + + @override + State<ScreenHome> createState() => _ScreenHomeState(); +} + +class _ScreenHomeState extends State<ScreenHome> { + @override + Widget build(BuildContext context) { + return Material( + color: Theme.of(context).colorScheme.background, + child: ListView( + padding: const EdgeInsets.symmetric(horizontal: 4), + physics: const BouncingScrollPhysics(), + children: <Widget>[ + const SizedBox(height: 8), + const CardStatisticsGlobal(), + const SizedBox(height: 6), + const CardStatisticsRecent(), + const SizedBox(height: 6), + const CardTimeline(), + const SizedBox(height: 6), + const CardTopArtists(), + const SizedBox(height: 36), + ], + ), + ); + } +} diff --git a/lib/ui/screens/home_screen.dart b/lib/ui/screens/home_screen.dart deleted file mode 100644 index 5af4a2d..0000000 --- a/lib/ui/screens/home_screen.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../widgets/main_screen/statistics_global_card.dart'; -import '../widgets/main_screen/statistics_recent_card.dart'; -import '../widgets/main_screen/timeline_card.dart'; -import '../widgets/main_screen/topartists_card.dart'; - -class HomeScreen extends StatefulWidget { - const HomeScreen({super.key}); - - @override - State<HomeScreen> createState() => _HomeScreenState(); -} - -class _HomeScreenState extends State<HomeScreen> { - @override - Widget build(BuildContext context) { - return Material( - color: Theme.of(context).colorScheme.background, - child: ListView( - padding: const EdgeInsets.symmetric(horizontal: 4), - physics: const BouncingScrollPhysics(), - children: <Widget>[ - const SizedBox(height: 8), - const StatisticsGlobalCard(), - const SizedBox(height: 6), - const StatisticsRecentCard(), - const SizedBox(height: 6), - const ChartTimelineCard(), - const SizedBox(height: 6), - const ChartTopArtistsCard(), - const SizedBox(height: 36), - ], - ), - ); - } -} diff --git a/lib/ui/screens/statistics_screen.dart b/lib/ui/screens/statistics.dart similarity index 54% rename from lib/ui/screens/statistics_screen.dart rename to lib/ui/screens/statistics.dart index c3f9e46..b719361 100644 --- a/lib/ui/screens/statistics_screen.dart +++ b/lib/ui/screens/statistics.dart @@ -1,16 +1,16 @@ import 'package:flutter/material.dart'; -import '../widgets/main_screen/counts_by_day_card.dart'; -import '../widgets/main_screen/counts_by_hour_card.dart'; +import 'package:scrobbles/ui/widgets/cards/counts_by_day.dart'; +import 'package:scrobbles/ui/widgets/cards/counts_by_hour.dart'; -class StatisticsScreen extends StatefulWidget { - const StatisticsScreen({super.key}); +class ScreenStatistics extends StatefulWidget { + const ScreenStatistics({super.key}); @override - State<StatisticsScreen> createState() => _StatisticsScreenState(); + State<ScreenStatistics> createState() => _ScreenStatisticsState(); } -class _StatisticsScreenState extends State<StatisticsScreen> { +class _ScreenStatisticsState extends State<ScreenStatistics> { @override Widget build(BuildContext context) { return Material( @@ -20,9 +20,9 @@ class _StatisticsScreenState extends State<StatisticsScreen> { physics: const BouncingScrollPhysics(), children: <Widget>[ const SizedBox(height: 8), - const ChartCountsByDayCard(), + const CardCountsByDay(), const SizedBox(height: 6), - const ChartCountsByHourCard(), + const CardCountsByHour(), const SizedBox(height: 36), ], ), diff --git a/lib/ui/screens/skeleton_screen.dart b/lib/ui/skeleton.dart similarity index 80% rename from lib/ui/screens/skeleton_screen.dart rename to lib/ui/skeleton.dart index 9a10a78..ad00a7b 100644 --- a/lib/ui/screens/skeleton_screen.dart +++ b/lib/ui/skeleton.dart @@ -1,13 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import '../../cubit/bottom_nav_cubit.dart'; -import '../widgets/app_bar.dart'; -import '../widgets/bottom_nav_bar.dart'; - -import 'discoveries_screen.dart'; -import 'home_screen.dart'; -import 'statistics_screen.dart'; +import 'package:scrobbles/cubit/bottom_nav_cubit.dart'; +import 'package:scrobbles/ui/screens/discoveries.dart'; +import 'package:scrobbles/ui/screens/home.dart'; +import 'package:scrobbles/ui/screens/statistics.dart'; +import 'package:scrobbles/ui/widgets/app_bar.dart'; +import 'package:scrobbles/ui/widgets/bottom_nav_bar.dart'; class SkeletonScreen extends StatefulWidget { const SkeletonScreen({super.key}); @@ -20,9 +19,9 @@ class _SkeletonScreenState extends State<SkeletonScreen> { @override Widget build(BuildContext context) { const List<Widget> pageNavigation = <Widget>[ - const HomeScreen(), - const DiscoveriesScreen(), - const StatisticsScreen(), + const ScreenHome(), + const ScreenDiscoveries(), + const ScreenStatistics(), ]; return BlocProvider<BottomNavCubit>( diff --git a/lib/ui/widgets/charts/custom_bar_chart.dart b/lib/ui/widgets/abstracts/custom_bar_chart.dart similarity index 97% rename from lib/ui/widgets/charts/custom_bar_chart.dart rename to lib/ui/widgets/abstracts/custom_bar_chart.dart index 8cdd32d..1ccfafb 100644 --- a/lib/ui/widgets/charts/custom_bar_chart.dart +++ b/lib/ui/widgets/abstracts/custom_bar_chart.dart @@ -2,12 +2,13 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; -import '../../../config/app_colors.dart'; -import '../../../utils/color_extensions.dart'; +import 'package:scrobbles/config/app_colors.dart'; +import 'package:scrobbles/utils/color_extensions.dart'; class CustomBarChart extends StatelessWidget { CustomBarChart({super.key}); + final Widget placeholder = Text('â³'); final double chartHeight = 150.0; final double verticalTicksInterval = 10; final String verticalAxisTitleSuffix = ''; diff --git a/lib/ui/widgets/charts/custom_line_chart.dart b/lib/ui/widgets/abstracts/custom_line_chart.dart similarity index 95% rename from lib/ui/widgets/charts/custom_line_chart.dart rename to lib/ui/widgets/abstracts/custom_line_chart.dart index fadf283..5e1a90c 100644 --- a/lib/ui/widgets/charts/custom_line_chart.dart +++ b/lib/ui/widgets/abstracts/custom_line_chart.dart @@ -1,11 +1,12 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; -import '../../../config/app_colors.dart'; +import 'package:scrobbles/config/app_colors.dart'; class CustomLineChart extends StatelessWidget { CustomLineChart({super.key}); + final Widget placeholder = Text('â³'); final double chartHeight = 150.0; final double titleFontSize = 10; diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart index 3313e59..6db981e 100644 --- a/lib/ui/widgets/app_bar.dart +++ b/lib/ui/widgets/app_bar.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:unicons/unicons.dart'; -import '../widgets/header.dart'; +import 'package:scrobbles/ui/widgets/header_app.dart'; class StandardAppBar extends StatelessWidget implements PreferredSizeWidget { final Function() notifyParent; @@ -11,7 +11,7 @@ class StandardAppBar extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { return AppBar( - title: const Header(text: 'app_name'), + title: const AppHeader(text: 'app_name'), actions: [ IconButton( onPressed: () { diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart index 02aa39a..3d2fb30 100644 --- a/lib/ui/widgets/bottom_nav_bar.dart +++ b/lib/ui/widgets/bottom_nav_bar.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:ionicons/ionicons.dart'; -import '../../cubit/bottom_nav_cubit.dart'; +import 'package:scrobbles/cubit/bottom_nav_cubit.dart'; class BottomNavBar extends StatelessWidget { const BottomNavBar({super.key}); diff --git a/lib/ui/widgets/card_content.dart b/lib/ui/widgets/card_content.dart new file mode 100644 index 0000000..2694475 --- /dev/null +++ b/lib/ui/widgets/card_content.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; + +class CardContent extends StatelessWidget { + const CardContent({ + super.key, + required this.title, + required this.color, + required this.content, + }); + + final String title; + final Color color; + final Widget content; + + @override + Widget build(BuildContext context) { + return Card( + elevation: 2, + shadowColor: Theme.of(context).colorScheme.shadow, + color: this.color, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Text( + this.title, + style: Theme.of(context).primaryTextTheme.titleLarge!.apply(fontWeightDelta: 2), + ), + const SizedBox(height: 8), + this.content, + ], + ), + ), + ); + } +} diff --git a/lib/ui/widgets/cards/counts_by_day.dart b/lib/ui/widgets/cards/counts_by_day.dart new file mode 100644 index 0000000..59d80cb --- /dev/null +++ b/lib/ui/widgets/cards/counts_by_day.dart @@ -0,0 +1,44 @@ +import 'dart:convert'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +import 'package:scrobbles/models/counts_by_day.dart'; +import 'package:scrobbles/network/scrobbles.dart'; +import 'package:scrobbles/ui/widgets/card_content.dart'; +import 'package:scrobbles/ui/widgets/charts/counts_by_day.dart'; +import 'package:scrobbles/ui/widgets/error.dart'; + +class CardCountsByDay extends StatelessWidget { + const CardCountsByDay({super.key}); + + @override + Widget build(BuildContext context) { + final int daysCount = 21; + late Future<CountsByDayData> future = ScrobblesApi.fetchCountsByDay(daysCount); + + return FutureBuilder<CountsByDayData>( + future: future, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + return CardContent( + color: Theme.of(context).colorScheme.surface, + title: 'counts_by_day'.tr( + namedArgs: { + 'daysCount': daysCount.toString(), + }, + ), + content: ChartCountsByDay( + chartData: snapshot.hasData + ? CountsByDayData.fromJson(jsonDecode(snapshot.data.toString())) + : CountsByDayData.createEmpty(), + isLoading: !snapshot.hasData, + ), + ); + }, + ); + } +} diff --git a/lib/ui/widgets/cards/counts_by_hour.dart b/lib/ui/widgets/cards/counts_by_hour.dart new file mode 100644 index 0000000..6c0d91f --- /dev/null +++ b/lib/ui/widgets/cards/counts_by_hour.dart @@ -0,0 +1,44 @@ +import 'dart:convert'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +import 'package:scrobbles/models/counts_by_hour.dart'; +import 'package:scrobbles/network/scrobbles.dart'; +import 'package:scrobbles/ui/widgets/card_content.dart'; +import 'package:scrobbles/ui/widgets/charts/counts_by_hour.dart'; +import 'package:scrobbles/ui/widgets/error.dart'; + +class CardCountsByHour extends StatelessWidget { + const CardCountsByHour({super.key}); + + @override + Widget build(BuildContext context) { + final int daysCount = 21; + late Future<CountsByHourData> future = ScrobblesApi.fetchCountsByHour(daysCount); + + return FutureBuilder<CountsByHourData>( + future: future, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + return CardContent( + color: Theme.of(context).colorScheme.surface, + title: 'counts_by_hour'.tr( + namedArgs: { + 'daysCount': daysCount.toString(), + }, + ), + content: ChartCountsByHour( + chartData: snapshot.hasData + ? CountsByHourData.fromJson(jsonDecode(snapshot.data.toString())) + : CountsByHourData.createEmpty(), + isLoading: !snapshot.hasData, + ), + ); + }, + ); + } +} diff --git a/lib/ui/widgets/cards/discoveries.dart b/lib/ui/widgets/cards/discoveries.dart new file mode 100644 index 0000000..f0cd96d --- /dev/null +++ b/lib/ui/widgets/cards/discoveries.dart @@ -0,0 +1,66 @@ +import 'dart:convert'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +import 'package:scrobbles/models/discoveries.dart'; +import 'package:scrobbles/network/scrobbles.dart'; +import 'package:scrobbles/ui/widgets/card_content.dart'; +import 'package:scrobbles/ui/widgets/charts/discoveries_artists.dart'; +import 'package:scrobbles/ui/widgets/charts/discoveries_tracks.dart'; +import 'package:scrobbles/ui/widgets/error.dart'; + +class CardDiscoveries extends StatelessWidget { + const CardDiscoveries({super.key}); + + @override + Widget build(BuildContext context) { + final int daysCount = 14; + late Future<DiscoveriesData> future = ScrobblesApi.fetchDiscoveries(daysCount); + + return FutureBuilder<DiscoveriesData>( + future: future, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + final TextTheme textTheme = Theme.of(context).primaryTextTheme; + + return CardContent( + color: Theme.of(context).colorScheme.surface, + title: 'discoveries_title'.tr( + namedArgs: { + 'daysCount': daysCount.toString(), + }, + ), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'discoveries_artists_title', + style: textTheme.titleMedium!.apply(fontWeightDelta: 2), + ).tr(), + const SizedBox(height: 8), + ChartDiscoveriesArtists( + chartData: DiscoveriesData.fromJson(jsonDecode(snapshot.data.toString())), + isLoading: !snapshot.hasData, + ), + const SizedBox(height: 8), + Text( + 'discoveries_tracks_title', + style: textTheme.titleMedium!.apply(fontWeightDelta: 2), + ).tr(), + const SizedBox(height: 8), + ChartDiscoveriesTracks( + chartData: DiscoveriesData.fromJson(jsonDecode(snapshot.data.toString())), + isLoading: !snapshot.hasData, + ), + ], + ), + ); + }, + ); + } +} diff --git a/lib/ui/widgets/cards/statistics_global.dart b/lib/ui/widgets/cards/statistics_global.dart new file mode 100644 index 0000000..0d8feb8 --- /dev/null +++ b/lib/ui/widgets/cards/statistics_global.dart @@ -0,0 +1,39 @@ +import 'dart:convert'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +import 'package:scrobbles/models/statistics_global.dart'; +import 'package:scrobbles/network/scrobbles.dart'; +import 'package:scrobbles/ui/widgets/card_content.dart'; +import 'package:scrobbles/ui/widgets/content/statistics_global.dart'; +import 'package:scrobbles/ui/widgets/error.dart'; + +class CardStatisticsGlobal extends StatelessWidget { + const CardStatisticsGlobal({super.key}); + + @override + Widget build(BuildContext context) { + late Future<StatisticsGlobalData> future = ScrobblesApi.fetchGlobalStatistics(); + + return FutureBuilder<StatisticsGlobalData>( + future: future, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + return CardContent( + color: Theme.of(context).colorScheme.primary, + title: 'global_statistics'.tr(), + content: ContentStatisticsGlobal( + statistics: snapshot.hasData + ? StatisticsGlobalData.fromJson(jsonDecode(snapshot.data.toString())) + : StatisticsGlobalData.createEmpty(), + isLoading: !snapshot.hasData, + ), + ); + }, + ); + } +} diff --git a/lib/ui/widgets/cards/statistics_recent.dart b/lib/ui/widgets/cards/statistics_recent.dart new file mode 100644 index 0000000..0925c42 --- /dev/null +++ b/lib/ui/widgets/cards/statistics_recent.dart @@ -0,0 +1,45 @@ +import 'dart:convert'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +import 'package:scrobbles/models/statistics_recent.dart'; +import 'package:scrobbles/network/scrobbles.dart'; +import 'package:scrobbles/ui/widgets/card_content.dart'; +import 'package:scrobbles/ui/widgets/content/statistics_recent.dart'; +import 'package:scrobbles/ui/widgets/error.dart'; + +class CardStatisticsRecent extends StatelessWidget { + const CardStatisticsRecent({super.key}); + + @override + Widget build(BuildContext context) { + final int daysCount = 21; + + late Future<StatisticsRecentData> future = ScrobblesApi.fetchRecentStatistics(daysCount); + + return FutureBuilder<StatisticsRecentData>( + future: future, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + return CardContent( + color: Theme.of(context).colorScheme.primary, + title: 'recent_statistics'.tr( + namedArgs: { + 'daysCount': daysCount.toString(), + }, + ), + content: ContentStatisticsRecent( + statistics: snapshot.hasData + ? StatisticsRecentData.fromJson(jsonDecode(snapshot.data.toString())) + : StatisticsRecentData.createEmpty(), + isLoading: !snapshot.hasData, + ), + ); + }, + ); + } +} diff --git a/lib/ui/widgets/cards/timeline.dart b/lib/ui/widgets/cards/timeline.dart new file mode 100644 index 0000000..a7ea95d --- /dev/null +++ b/lib/ui/widgets/cards/timeline.dart @@ -0,0 +1,51 @@ +import 'dart:convert'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +import 'package:scrobbles/models/timeline.dart'; +import 'package:scrobbles/network/scrobbles.dart'; +import 'package:scrobbles/ui/widgets/card_content.dart'; +import 'package:scrobbles/ui/widgets/charts/timeline_counts.dart'; +import 'package:scrobbles/ui/widgets/charts/timeline_eclecticism.dart'; +import 'package:scrobbles/ui/widgets/error.dart'; + +class CardTimeline extends StatelessWidget { + const CardTimeline({super.key}); + + @override + Widget build(BuildContext context) { + final int daysCount = 14; + late Future<TimelineData> future = ScrobblesApi.fetchTimeline(daysCount); + + return FutureBuilder<TimelineData>( + future: future, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + return CardContent( + color: Theme.of(context).colorScheme.surface, + title: 'timeline_title'.tr( + namedArgs: { + 'daysCount': daysCount.toString(), + }, + ), + content: Stack( + children: [ + ChartTimelineCounts( + chartData: TimelineData.fromJson(jsonDecode(snapshot.data.toString())), + isLoading: !snapshot.hasData, + ), + ChartTimelineEclecticism( + chartData: TimelineData.fromJson(jsonDecode(snapshot.data.toString())), + isLoading: !snapshot.hasData, + ), + ], + ), + ); + }, + ); + } +} diff --git a/lib/ui/widgets/cards/top_artists.dart b/lib/ui/widgets/cards/top_artists.dart new file mode 100644 index 0000000..d589518 --- /dev/null +++ b/lib/ui/widgets/cards/top_artists.dart @@ -0,0 +1,44 @@ +import 'dart:convert'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +import 'package:scrobbles/models/topartists.dart'; +import 'package:scrobbles/network/scrobbles.dart'; +import 'package:scrobbles/ui/widgets/card_content.dart'; +import 'package:scrobbles/ui/widgets/charts/top_artists.dart'; +import 'package:scrobbles/ui/widgets/error.dart'; + +class CardTopArtists extends StatelessWidget { + const CardTopArtists({super.key}); + + @override + Widget build(BuildContext context) { + final int daysCount = 14; + late Future<TopArtistsData> future = ScrobblesApi.fetchTopArtists(daysCount); + + return FutureBuilder<TopArtistsData>( + future: future, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + return CardContent( + color: Theme.of(context).colorScheme.surface, + title: 'top_artists_title'.tr( + namedArgs: { + 'daysCount': daysCount.toString(), + }, + ), + content: ChartTopArtists( + chartData: snapshot.hasData + ? TopArtistsData.fromJson(jsonDecode(snapshot.data.toString())) + : TopArtistsData.createEmpty(), + isLoading: !snapshot.hasData, + ), + ); + }, + ); + } +} diff --git a/lib/ui/widgets/main_screen/counts_by_day_chart.dart b/lib/ui/widgets/charts/counts_by_day.dart similarity index 76% rename from lib/ui/widgets/main_screen/counts_by_day_chart.dart rename to lib/ui/widgets/charts/counts_by_day.dart index 360dcc1..19492b4 100644 --- a/lib/ui/widgets/main_screen/counts_by_day_chart.dart +++ b/lib/ui/widgets/charts/counts_by_day.dart @@ -2,14 +2,15 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; -import '../../../config/app_colors.dart'; -import '../../../models/counts_by_day.dart'; -import '../../../ui/widgets/charts/custom_bar_chart.dart'; +import 'package:scrobbles/config/app_colors.dart'; +import 'package:scrobbles/models/counts_by_day.dart'; +import 'package:scrobbles/ui/widgets/abstracts/custom_bar_chart.dart'; -class CountsByDayCardContentChart extends CustomBarChart { +class ChartCountsByDay extends CustomBarChart { final CountsByDayData chartData; + final bool isLoading; - CountsByDayCardContentChart({super.key, required this.chartData}); + ChartCountsByDay({super.key, required this.chartData, required this.isLoading}); final double verticalTicksInterval = 5; final String verticalAxisTitleSuffix = '%'; @@ -18,12 +19,19 @@ class CountsByDayCardContentChart extends CustomBarChart { Widget build(BuildContext context) { return Container( height: this.chartHeight, - child: LayoutBuilder(builder: (context, constraints) { - return getBarChart( - barWidth: this.getBarWidth(constraints.maxWidth, this.chartData.data.keys.length), - backgroundColor: Theme.of(context).colorScheme.onSurface, - ); - }), + child: this.isLoading + ? this.placeholder + : LayoutBuilder( + builder: (context, constraints) { + final double maxWidth = constraints.maxWidth; + final int barsCount = this.chartData.data.keys.length; + + return getBarChart( + barWidth: this.getBarWidth(maxWidth, barsCount), + backgroundColor: Theme.of(context).colorScheme.onSurface, + ); + }, + ), ); } diff --git a/lib/ui/widgets/main_screen/counts_by_hour_chart.dart b/lib/ui/widgets/charts/counts_by_hour.dart similarity index 63% rename from lib/ui/widgets/main_screen/counts_by_hour_chart.dart rename to lib/ui/widgets/charts/counts_by_hour.dart index ec5766a..79c8167 100644 --- a/lib/ui/widgets/main_screen/counts_by_hour_chart.dart +++ b/lib/ui/widgets/charts/counts_by_hour.dart @@ -1,15 +1,16 @@ import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; -import '../../../config/app_colors.dart'; -import '../../../models/counts_by_hour.dart'; -import '../../../ui/widgets/charts/custom_bar_chart.dart'; -import '../../../utils/color_extensions.dart'; +import 'package:scrobbles/config/app_colors.dart'; +import 'package:scrobbles/models/counts_by_hour.dart'; +import 'package:scrobbles/ui/widgets/abstracts/custom_bar_chart.dart'; +import 'package:scrobbles/utils/color_extensions.dart'; -class CountsByHourCardContentChart extends CustomBarChart { +class ChartCountsByHour extends CustomBarChart { final CountsByHourData chartData; + final bool isLoading; - CountsByHourCardContentChart({super.key, required this.chartData}); + ChartCountsByHour({super.key, required this.chartData, required this.isLoading}); final double verticalTicksInterval = 5; final String verticalAxisTitleSuffix = '%'; @@ -18,12 +19,19 @@ class CountsByHourCardContentChart extends CustomBarChart { Widget build(BuildContext context) { return Container( height: this.chartHeight, - child: LayoutBuilder(builder: (context, constraints) { - return getBarChart( - barWidth: this.getBarWidth(constraints.maxWidth, this.chartData.data.keys.length), - backgroundColor: Theme.of(context).colorScheme.onSurface, - ); - }), + child: this.isLoading + ? this.placeholder + : LayoutBuilder( + builder: (context, constraints) { + final double maxWidth = constraints.maxWidth; + final int barsCount = this.chartData.data.keys.length; + + return getBarChart( + barWidth: this.getBarWidth(maxWidth, barsCount), + backgroundColor: Theme.of(context).colorScheme.onSurface, + ); + }, + ), ); } diff --git a/lib/ui/widgets/main_screen/discoveries_chart_artists.dart b/lib/ui/widgets/charts/discoveries_artists.dart similarity index 61% rename from lib/ui/widgets/main_screen/discoveries_chart_artists.dart rename to lib/ui/widgets/charts/discoveries_artists.dart index eb76c31..d441c27 100644 --- a/lib/ui/widgets/main_screen/discoveries_chart_artists.dart +++ b/lib/ui/widgets/charts/discoveries_artists.dart @@ -1,26 +1,34 @@ import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; -import '../../../config/app_colors.dart'; -import '../../../models/discoveries.dart'; -import '../../../utils/color_extensions.dart'; -import '../../../ui/widgets/charts/custom_bar_chart.dart'; +import 'package:scrobbles/config/app_colors.dart'; +import 'package:scrobbles/models/discoveries.dart'; +import 'package:scrobbles/ui/widgets/abstracts/custom_bar_chart.dart'; +import 'package:scrobbles/utils/color_extensions.dart'; class ChartDiscoveriesArtists extends CustomBarChart { final DiscoveriesData chartData; + final bool isLoading; - ChartDiscoveriesArtists({super.key, required this.chartData}); + ChartDiscoveriesArtists({super.key, required this.chartData, required this.isLoading}); @override Widget build(BuildContext context) { return Container( height: this.chartHeight, - child: LayoutBuilder(builder: (context, constraints) { - return getBarChart( - barWidth: this.getBarWidth(constraints.maxWidth, this.chartData.data.keys.length), - backgroundColor: Theme.of(context).colorScheme.onSurface, - ); - }), + child: this.isLoading + ? this.placeholder + : LayoutBuilder( + builder: (context, constraints) { + final double maxWidth = constraints.maxWidth; + final int barsCount = this.chartData.data.keys.length; + + return getBarChart( + barWidth: this.getBarWidth(maxWidth, barsCount), + backgroundColor: Theme.of(context).colorScheme.onSurface, + ); + }, + ), ); } diff --git a/lib/ui/widgets/main_screen/discoveries_chart_tracks.dart b/lib/ui/widgets/charts/discoveries_tracks.dart similarity index 61% rename from lib/ui/widgets/main_screen/discoveries_chart_tracks.dart rename to lib/ui/widgets/charts/discoveries_tracks.dart index 622911d..343c02d 100644 --- a/lib/ui/widgets/main_screen/discoveries_chart_tracks.dart +++ b/lib/ui/widgets/charts/discoveries_tracks.dart @@ -1,26 +1,34 @@ import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; -import '../../../config/app_colors.dart'; -import '../../../models/discoveries.dart'; -import '../../../utils/color_extensions.dart'; -import '../../../ui/widgets/charts/custom_bar_chart.dart'; +import 'package:scrobbles/config/app_colors.dart'; +import 'package:scrobbles/models/discoveries.dart'; +import 'package:scrobbles/ui/widgets/abstracts/custom_bar_chart.dart'; +import 'package:scrobbles/utils/color_extensions.dart'; class ChartDiscoveriesTracks extends CustomBarChart { final DiscoveriesData chartData; + final bool isLoading; - ChartDiscoveriesTracks({super.key, required this.chartData}); + ChartDiscoveriesTracks({super.key, required this.chartData, required this.isLoading}); @override Widget build(BuildContext context) { return Container( height: this.chartHeight, - child: LayoutBuilder(builder: (context, constraints) { - return getBarChart( - barWidth: this.getBarWidth(constraints.maxWidth, this.chartData.data.keys.length), - backgroundColor: Theme.of(context).colorScheme.onSurface, - ); - }), + child: this.isLoading + ? this.placeholder + : LayoutBuilder( + builder: (context, constraints) { + final double maxWidth = constraints.maxWidth; + final int barsCount = this.chartData.data.keys.length; + + return getBarChart( + barWidth: this.getBarWidth(maxWidth, barsCount), + backgroundColor: Theme.of(context).colorScheme.onSurface, + ); + }, + ), ); } diff --git a/lib/ui/widgets/main_screen/timeline_chart_counts.dart b/lib/ui/widgets/charts/timeline_counts.dart similarity index 62% rename from lib/ui/widgets/main_screen/timeline_chart_counts.dart rename to lib/ui/widgets/charts/timeline_counts.dart index bdfa0c5..8e5fec0 100644 --- a/lib/ui/widgets/main_screen/timeline_chart_counts.dart +++ b/lib/ui/widgets/charts/timeline_counts.dart @@ -1,14 +1,15 @@ import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; -import '../../../config/app_colors.dart'; -import '../../../models/timeline.dart'; -import '../../../ui/widgets/charts/custom_bar_chart.dart'; +import 'package:scrobbles/config/app_colors.dart'; +import 'package:scrobbles/models/timeline.dart'; +import 'package:scrobbles/ui/widgets/abstracts/custom_bar_chart.dart'; class ChartTimelineCounts extends CustomBarChart { final TimelineData chartData; + final bool isLoading; - ChartTimelineCounts({super.key, required this.chartData}); + ChartTimelineCounts({super.key, required this.chartData, required this.isLoading}); final double verticalTicksInterval = 50; @@ -16,12 +17,19 @@ class ChartTimelineCounts extends CustomBarChart { Widget build(BuildContext context) { return Container( height: this.chartHeight, - child: LayoutBuilder(builder: (context, constraints) { - return getBarChart( - barWidth: this.getBarWidth(constraints.maxWidth, this.chartData.data.keys.length), - backgroundColor: Theme.of(context).colorScheme.onSurface, - ); - }), + child: this.isLoading + ? this.placeholder + : LayoutBuilder( + builder: (context, constraints) { + final double maxWidth = constraints.maxWidth; + final int barsCount = this.chartData.data.keys.length; + + return getBarChart( + barWidth: this.getBarWidth(maxWidth, barsCount), + backgroundColor: Theme.of(context).colorScheme.onSurface, + ); + }, + ), ); } diff --git a/lib/ui/widgets/main_screen/timeline_chart_eclecticism.dart b/lib/ui/widgets/charts/timeline_eclecticism.dart similarity index 66% rename from lib/ui/widgets/main_screen/timeline_chart_eclecticism.dart rename to lib/ui/widgets/charts/timeline_eclecticism.dart index 71e358e..f5ddd96 100644 --- a/lib/ui/widgets/main_screen/timeline_chart_eclecticism.dart +++ b/lib/ui/widgets/charts/timeline_eclecticism.dart @@ -1,15 +1,16 @@ import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; -import '../../../config/app_colors.dart'; -import '../../../models/timeline.dart'; -import '../../../ui/widgets/charts/custom_line_chart.dart'; -import '../../../utils/color_extensions.dart'; +import 'package:scrobbles/config/app_colors.dart'; +import 'package:scrobbles/models/timeline.dart'; +import 'package:scrobbles/ui/widgets/abstracts/custom_line_chart.dart'; +import 'package:scrobbles/utils/color_extensions.dart'; class ChartTimelineEclecticism extends CustomLineChart { final TimelineData chartData; + final bool isLoading; - ChartTimelineEclecticism({super.key, required this.chartData}); + ChartTimelineEclecticism({super.key, required this.chartData, required this.isLoading}); @override Widget build(BuildContext context) { @@ -17,20 +18,22 @@ class ChartTimelineEclecticism extends CustomLineChart { return Container( height: this.chartHeight, - child: LineChart( - LineChartData( - lineBarsData: getDataEclecticism(), - borderData: getBorderData(), - gridData: getGridData(), - titlesData: getTitlesData(), - lineTouchData: const LineTouchData(enabled: false), - minX: horizontalScale['min'], - maxX: horizontalScale['max'], - maxY: 100, - minY: 0, - ), - duration: const Duration(milliseconds: 250), - ), + child: this.isLoading + ? this.placeholder + : LineChart( + LineChartData( + lineBarsData: getDataEclecticism(), + borderData: getBorderData(), + gridData: getGridData(), + titlesData: getTitlesData(), + lineTouchData: const LineTouchData(enabled: false), + minX: horizontalScale['min'], + maxX: horizontalScale['max'], + maxY: 100, + minY: 0, + ), + duration: const Duration(milliseconds: 250), + ), ); } diff --git a/lib/ui/widgets/main_screen/topartists_chart.dart b/lib/ui/widgets/charts/top_artists.dart similarity index 71% rename from lib/ui/widgets/main_screen/topartists_chart.dart rename to lib/ui/widgets/charts/top_artists.dart index 0a6bcd8..5b0de9c 100644 --- a/lib/ui/widgets/main_screen/topartists_chart.dart +++ b/lib/ui/widgets/charts/top_artists.dart @@ -1,39 +1,44 @@ import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; -import '../../../config/app_colors.dart'; -import '../../../models/topartists.dart'; -import '../../../utils/color_extensions.dart'; +import 'package:scrobbles/config/app_colors.dart'; +import 'package:scrobbles/models/topartists.dart'; +import 'package:scrobbles/utils/color_extensions.dart'; class ChartTopArtists extends StatelessWidget { final TopArtistsData chartData; + final bool isLoading; - ChartTopArtists({super.key, required this.chartData}); + ChartTopArtists({super.key, required this.chartData, required this.isLoading}); + + final Widget placeholder = Text('â³'); @override Widget build(BuildContext context) { return AspectRatio( aspectRatio: 2.1, - child: Row( - children: <Widget>[ - Expanded( - child: AspectRatio( - aspectRatio: 1, - child: PieChart( - PieChartData( - sections: getPieChartData(), - sectionsSpace: 2, - centerSpaceRadius: 40, - startDegreeOffset: -45, - pieTouchData: PieTouchData(enabled: false), - borderData: FlBorderData(show: false), + child: this.isLoading + ? this.placeholder + : Row( + children: <Widget>[ + Expanded( + child: AspectRatio( + aspectRatio: 1, + child: PieChart( + PieChartData( + sections: getPieChartData(), + sectionsSpace: 2, + centerSpaceRadius: 40, + startDegreeOffset: -45, + pieTouchData: PieTouchData(enabled: false), + borderData: FlBorderData(show: false), + ), + ), + ), ), - ), + buildLegendWidget(), + ], ), - ), - buildLegendWidget(), - ], - ), ); } diff --git a/lib/ui/widgets/main_screen/statistics_global_content.dart b/lib/ui/widgets/content/statistics_global.dart similarity index 77% rename from lib/ui/widgets/main_screen/statistics_global_content.dart rename to lib/ui/widgets/content/statistics_global.dart index 4459347..d171441 100644 --- a/lib/ui/widgets/main_screen/statistics_global_content.dart +++ b/lib/ui/widgets/content/statistics_global.dart @@ -1,29 +1,24 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import '../../../models/statistics_global.dart'; +import 'package:scrobbles/models/statistics_global.dart'; -class StatisticsGlobalContent extends StatelessWidget { +class ContentStatisticsGlobal extends StatelessWidget { final StatisticsGlobalData statistics; final bool isLoading; - const StatisticsGlobalContent( + const ContentStatisticsGlobal( {super.key, required this.statistics, required this.isLoading}); @override Widget build(BuildContext context) { final TextTheme textTheme = Theme.of(context).primaryTextTheme; - - final String placeholder = 'â³'; + const 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, diff --git a/lib/ui/widgets/main_screen/statistics_recent_content.dart b/lib/ui/widgets/content/statistics_recent.dart similarity index 64% rename from lib/ui/widgets/main_screen/statistics_recent_content.dart rename to lib/ui/widgets/content/statistics_recent.dart index cd95b00..01f04ac 100644 --- a/lib/ui/widgets/main_screen/statistics_recent_content.dart +++ b/lib/ui/widgets/content/statistics_recent.dart @@ -1,38 +1,24 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import '../../../models/statistics_recent.dart'; +import 'package:scrobbles/models/statistics_recent.dart'; -class StatisticsRecentContent extends StatelessWidget { +class ContentStatisticsRecent extends StatelessWidget { final StatisticsRecentData statistics; final bool isLoading; - const StatisticsRecentContent( + const ContentStatisticsRecent( {super.key, required this.statistics, required this.isLoading}); @override Widget build(BuildContext context) { final TextTheme textTheme = Theme.of(context).primaryTextTheme; - - final String placeholder = 'â³'; + const String placeholder = 'â³'; return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ - Text( - 'recent_statistics', - style: textTheme.titleLarge!.apply(fontWeightDelta: 2), - ).tr(), - Text( - 'statistics_selected_period', - style: textTheme.bodyMedium!.apply(fontWeightDelta: 2), - ).tr( - namedArgs: { - 'daysCount': - this.isLoading ? placeholder : this.statistics.selectedPeriod.toString(), - }, - ), Text( 'statistics_recent_scrobbles_count_and_discoveries', style: textTheme.bodyMedium, diff --git a/lib/ui/widgets/header.dart b/lib/ui/widgets/header_app.dart similarity index 78% rename from lib/ui/widgets/header.dart rename to lib/ui/widgets/header_app.dart index 2187ef8..77b015b 100644 --- a/lib/ui/widgets/header.dart +++ b/lib/ui/widgets/header_app.dart @@ -1,8 +1,8 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -class Header extends StatelessWidget { - const Header({super.key, required this.text}); +class AppHeader extends StatelessWidget { + const AppHeader({super.key, required this.text}); final String text; diff --git a/lib/ui/widgets/main_screen/counts_by_day_card.dart b/lib/ui/widgets/main_screen/counts_by_day_card.dart deleted file mode 100644 index 7f46132..0000000 --- a/lib/ui/widgets/main_screen/counts_by_day_card.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; - -import '../../../models/counts_by_day.dart'; -import '../../../network/scrobbles_api.dart'; -import '../../../ui/widgets/error.dart'; -import '../../../ui/widgets/main_screen/counts_by_day_content.dart'; - -class ChartCountsByDayCard extends StatelessWidget { - const ChartCountsByDayCard({super.key}); - - @override - Widget build(BuildContext context) { - final int daysCount = 21; - late Future<CountsByDayData> futureCountsByDay = ScrobblesApi.fetchCountsByDay(daysCount); - - return FutureBuilder<CountsByDayData>( - future: futureCountsByDay, - 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.surface, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(8), - ), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: ChartCountsByDayCardContent( - daysCount: daysCount, - chartData: snapshot.hasData - ? CountsByDayData.fromJson(jsonDecode(snapshot.data.toString())) - : CountsByDayData.createEmpty(), - isLoading: !snapshot.hasData, - ), - ), - ); - }, - ); - } -} diff --git a/lib/ui/widgets/main_screen/counts_by_day_content.dart b/lib/ui/widgets/main_screen/counts_by_day_content.dart deleted file mode 100644 index 3e31962..0000000 --- a/lib/ui/widgets/main_screen/counts_by_day_content.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'dart:convert'; - -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; - -import '../../../models/counts_by_day.dart'; -import '../../../ui/widgets/main_screen/counts_by_day_chart.dart'; - -class ChartCountsByDayCardContent extends StatelessWidget { - final int daysCount; - final CountsByDayData chartData; - final bool isLoading; - - const ChartCountsByDayCardContent( - {super.key, required this.daysCount, required this.chartData, 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( - 'counts_by_day', - style: textTheme.titleLarge!.apply(fontWeightDelta: 2), - ).tr( - namedArgs: { - 'daysCount': this.daysCount.toString(), - }, - ), - const SizedBox(height: 8), - this.isLoading - ? Text(placeholder) - : CountsByDayCardContentChart( - chartData: CountsByDayData.fromJson(jsonDecode(this.chartData.toString())), - ), - ], - ); - } -} diff --git a/lib/ui/widgets/main_screen/counts_by_hour_card.dart b/lib/ui/widgets/main_screen/counts_by_hour_card.dart deleted file mode 100644 index 8060aed..0000000 --- a/lib/ui/widgets/main_screen/counts_by_hour_card.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; - -import '../../../models/counts_by_hour.dart'; -import '../../../network/scrobbles_api.dart'; -import '../../../ui/widgets/error.dart'; -import '../../../ui/widgets/main_screen/counts_by_hour_content.dart'; - -class ChartCountsByHourCard extends StatelessWidget { - const ChartCountsByHourCard({super.key}); - - @override - Widget build(BuildContext context) { - final int daysCount = 21; - late Future<CountsByHourData> futureCountsByHour = - ScrobblesApi.fetchCountsByHour(daysCount); - - return FutureBuilder<CountsByHourData>( - future: futureCountsByHour, - 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.surface, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(8), - ), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: ChartCountsByHourCardContent( - daysCount: daysCount, - chartData: snapshot.hasData - ? CountsByHourData.fromJson(jsonDecode(snapshot.data.toString())) - : CountsByHourData.createEmpty(), - isLoading: !snapshot.hasData, - ), - ), - ); - }, - ); - } -} diff --git a/lib/ui/widgets/main_screen/counts_by_hour_content.dart b/lib/ui/widgets/main_screen/counts_by_hour_content.dart deleted file mode 100644 index d53c34f..0000000 --- a/lib/ui/widgets/main_screen/counts_by_hour_content.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'dart:convert'; - -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; - -import '../../../models/counts_by_hour.dart'; -import '../../../ui/widgets/main_screen/counts_by_hour_chart.dart'; - -class ChartCountsByHourCardContent extends StatelessWidget { - final int daysCount; - final CountsByHourData chartData; - final bool isLoading; - - const ChartCountsByHourCardContent( - {super.key, required this.daysCount, required this.chartData, 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( - 'counts_by_hour', - style: textTheme.titleLarge!.apply(fontWeightDelta: 2), - ).tr( - namedArgs: { - 'daysCount': this.daysCount.toString(), - }, - ), - const SizedBox(height: 8), - this.isLoading - ? Text(placeholder) - : CountsByHourCardContentChart( - chartData: CountsByHourData.fromJson(jsonDecode(this.chartData.toString())), - ), - ], - ); - } -} diff --git a/lib/ui/widgets/main_screen/discoveries_card.dart b/lib/ui/widgets/main_screen/discoveries_card.dart deleted file mode 100644 index 57f0d04..0000000 --- a/lib/ui/widgets/main_screen/discoveries_card.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; - -import '../../../models/discoveries.dart'; -import '../../../network/scrobbles_api.dart'; -import '../../../ui/widgets/error.dart'; -import 'discoveries_content_artists.dart'; -import 'discoveries_content_tracks.dart'; - -class ChartDiscoveriesCard extends StatelessWidget { - const ChartDiscoveriesCard({super.key}); - - @override - Widget build(BuildContext context) { - final int daysCount = 14; - late Future<DiscoveriesData> futureTimeline = ScrobblesApi.fetchDiscoveries(daysCount); - - return FutureBuilder<DiscoveriesData>( - future: futureTimeline, - 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.surface, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(8), - ), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - ChartDiscoveriesArtistsCardContent( - daysCount: daysCount, - chartData: snapshot.hasData - ? DiscoveriesData.fromJson(jsonDecode(snapshot.data.toString())) - : DiscoveriesData.createEmpty(), - isLoading: !snapshot.hasData, - ), - const SizedBox(height: 8), - ChartDiscoveriesTracksCardContent( - daysCount: daysCount, - chartData: snapshot.hasData - ? DiscoveriesData.fromJson(jsonDecode(snapshot.data.toString())) - : DiscoveriesData.createEmpty(), - isLoading: !snapshot.hasData, - ), - ], - ), - ), - ); - }, - ); - } -} diff --git a/lib/ui/widgets/main_screen/discoveries_content_artists.dart b/lib/ui/widgets/main_screen/discoveries_content_artists.dart deleted file mode 100644 index b608e9d..0000000 --- a/lib/ui/widgets/main_screen/discoveries_content_artists.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'dart:convert'; - -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; - -import '../../../models/discoveries.dart'; -import 'discoveries_chart_artists.dart'; - -class ChartDiscoveriesArtistsCardContent extends StatelessWidget { - final int daysCount; - final DiscoveriesData chartData; - final bool isLoading; - - const ChartDiscoveriesArtistsCardContent( - {super.key, required this.daysCount, required this.chartData, 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( - 'discoveries_artists_title', - style: textTheme.titleLarge!.apply(fontWeightDelta: 2), - ).tr( - namedArgs: { - 'daysCount': this.daysCount.toString(), - }, - ), - const SizedBox(height: 8), - this.isLoading - ? Text(placeholder) - : ChartDiscoveriesArtists( - chartData: DiscoveriesData.fromJson(jsonDecode(this.chartData.toString())), - ), - ], - ); - } -} diff --git a/lib/ui/widgets/main_screen/discoveries_content_tracks.dart b/lib/ui/widgets/main_screen/discoveries_content_tracks.dart deleted file mode 100644 index 9ca8ff1..0000000 --- a/lib/ui/widgets/main_screen/discoveries_content_tracks.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'dart:convert'; - -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; - -import '../../../models/discoveries.dart'; -import 'discoveries_chart_tracks.dart'; - -class ChartDiscoveriesTracksCardContent extends StatelessWidget { - final int daysCount; - final DiscoveriesData chartData; - final bool isLoading; - - const ChartDiscoveriesTracksCardContent( - {super.key, required this.daysCount, required this.chartData, 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( - 'discoveries_tracks_title', - style: textTheme.titleLarge!.apply(fontWeightDelta: 2), - ).tr( - namedArgs: { - 'daysCount': this.daysCount.toString(), - }, - ), - const SizedBox(height: 8), - this.isLoading - ? Text(placeholder) - : ChartDiscoveriesTracks( - chartData: DiscoveriesData.fromJson(jsonDecode(this.chartData.toString())), - ), - ], - ); - } -} diff --git a/lib/ui/widgets/main_screen/statistics_global_card.dart b/lib/ui/widgets/main_screen/statistics_global_card.dart deleted file mode 100644 index 1a7474c..0000000 --- a/lib/ui/widgets/main_screen/statistics_global_card.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; - -import '../../../models/statistics_global.dart'; -import '../../../network/scrobbles_api.dart'; -import '../../../ui/widgets/error.dart'; -import 'statistics_global_content.dart'; - -class StatisticsGlobalCard extends StatelessWidget { - const StatisticsGlobalCard({super.key}); - - @override - Widget build(BuildContext context) { - late Future<StatisticsGlobalData> future = ScrobblesApi.fetchGlobalStatistics(); - - return FutureBuilder<StatisticsGlobalData>( - future: future, - 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(8), - ), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: StatisticsGlobalContent( - statistics: snapshot.hasData - ? StatisticsGlobalData.fromJson(jsonDecode(snapshot.data.toString())) - : StatisticsGlobalData.createEmpty(), - isLoading: !snapshot.hasData, - ), - ), - ); - }, - ); - } -} diff --git a/lib/ui/widgets/main_screen/statistics_recent_card.dart b/lib/ui/widgets/main_screen/statistics_recent_card.dart deleted file mode 100644 index 5f12d27..0000000 --- a/lib/ui/widgets/main_screen/statistics_recent_card.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; - -import '../../../models/statistics_recent.dart'; -import '../../../network/scrobbles_api.dart'; -import '../../../ui/widgets/error.dart'; -import 'statistics_recent_content.dart'; - -class StatisticsRecentCard extends StatelessWidget { - const StatisticsRecentCard({super.key}); - - @override - Widget build(BuildContext context) { - final int daysCount = 21; - - late Future<StatisticsRecentData> future = ScrobblesApi.fetchRecentStatistics(daysCount); - - return FutureBuilder<StatisticsRecentData>( - future: future, - 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(8), - ), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: StatisticsRecentContent( - statistics: snapshot.hasData - ? StatisticsRecentData.fromJson(jsonDecode(snapshot.data.toString())) - : StatisticsRecentData.createEmpty(), - isLoading: !snapshot.hasData, - ), - ), - ); - }, - ); - } -} diff --git a/lib/ui/widgets/main_screen/timeline_card.dart b/lib/ui/widgets/main_screen/timeline_card.dart deleted file mode 100644 index 931ea22..0000000 --- a/lib/ui/widgets/main_screen/timeline_card.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; - -import '../../../models/timeline.dart'; -import '../../../network/scrobbles_api.dart'; -import '../../../ui/widgets/error.dart'; -import '../../../ui/widgets/main_screen/timeline_content.dart'; - -class ChartTimelineCard extends StatelessWidget { - const ChartTimelineCard({super.key}); - - @override - Widget build(BuildContext context) { - final int daysCount = 14; - late Future<TimelineData> futureTimeline = ScrobblesApi.fetchTimeline(daysCount); - - return FutureBuilder<TimelineData>( - future: futureTimeline, - 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.surface, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(8), - ), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: ChartTimelineCardContent( - daysCount: daysCount, - chartData: snapshot.hasData - ? TimelineData.fromJson(jsonDecode(snapshot.data.toString())) - : TimelineData.createEmpty(), - isLoading: !snapshot.hasData, - ), - ), - ); - }, - ); - } -} diff --git a/lib/ui/widgets/main_screen/timeline_content.dart b/lib/ui/widgets/main_screen/timeline_content.dart deleted file mode 100644 index 1533ee1..0000000 --- a/lib/ui/widgets/main_screen/timeline_content.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'dart:convert'; - -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; - -import '../../../models/timeline.dart'; -import 'timeline_chart_counts.dart'; -import 'timeline_chart_eclecticism.dart'; - -class ChartTimelineCardContent extends StatelessWidget { - final int daysCount; - final TimelineData chartData; - final bool isLoading; - - const ChartTimelineCardContent( - {super.key, required this.daysCount, required this.chartData, 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( - 'timeline_title', - style: textTheme.titleLarge!.apply(fontWeightDelta: 2), - ).tr( - namedArgs: { - 'daysCount': this.daysCount.toString(), - }, - ), - const SizedBox(height: 8), - this.isLoading - ? Text(placeholder) - : Stack( - children: [ - ChartTimelineCounts( - chartData: TimelineData.fromJson(jsonDecode(this.chartData.toString())), - ), - ChartTimelineEclecticism( - chartData: TimelineData.fromJson(jsonDecode(this.chartData.toString())), - ), - ], - ), - ], - ); - } -} diff --git a/lib/ui/widgets/main_screen/topartists_card.dart b/lib/ui/widgets/main_screen/topartists_card.dart deleted file mode 100644 index e26de07..0000000 --- a/lib/ui/widgets/main_screen/topartists_card.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; - -import '../../../models/topartists.dart'; -import '../../../network/scrobbles_api.dart'; -import '../../../ui/widgets/error.dart'; -import '../../../ui/widgets/main_screen/topartists_content.dart'; - -class ChartTopArtistsCard extends StatelessWidget { - const ChartTopArtistsCard({super.key}); - - @override - Widget build(BuildContext context) { - final int daysCount = 14; - late Future<TopArtistsData> futureTimeline = ScrobblesApi.fetchTopArtists(daysCount); - - return FutureBuilder<TopArtistsData>( - future: futureTimeline, - 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.surface, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(8), - ), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: ChartTopArtistsCardContent( - daysCount: daysCount, - chartData: snapshot.hasData - ? TopArtistsData.fromJson(jsonDecode(snapshot.data.toString())) - : TopArtistsData.createEmpty(), - isLoading: !snapshot.hasData, - ), - ), - ); - }, - ); - } -} diff --git a/lib/ui/widgets/main_screen/topartists_content.dart b/lib/ui/widgets/main_screen/topartists_content.dart deleted file mode 100644 index 00d41e8..0000000 --- a/lib/ui/widgets/main_screen/topartists_content.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'dart:convert'; - -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; - -import '../../../models/topartists.dart'; -import '../../../ui/widgets/main_screen/topartists_chart.dart'; - -class ChartTopArtistsCardContent extends StatelessWidget { - final int daysCount; - final TopArtistsData chartData; - final bool isLoading; - - const ChartTopArtistsCardContent( - {super.key, required this.daysCount, required this.chartData, 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( - 'top_artists_title', - style: textTheme.titleLarge!.apply(fontWeightDelta: 2), - ).tr( - namedArgs: { - 'daysCount': this.daysCount.toString(), - }, - ), - const SizedBox(height: 8), - this.isLoading - ? Text(placeholder) - : ChartTopArtists( - chartData: TopArtistsData.fromJson(jsonDecode(this.chartData.toString())), - ), - ], - ); - } -} diff --git a/pubspec.yaml b/pubspec.yaml index ad3eda2..33d49a5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: Display scrobbles data and charts publish_to: 'none' -version: 0.0.27+27 +version: 0.0.28+28 environment: sdk: '^3.0.0' -- GitLab