diff --git a/android/gradle.properties b/android/gradle.properties index 408253ceb04c0c7c49b3b9daf597f35b66ce16c1..e6443382b31fab5fc027b99dc079154f78f27d0b 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 a2823ebf4473cf48e61d66216dc8b759dee922ed..3f4f688426c83324af070f6d7dba37ed2c91edc8 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 67d019d1490f2a0f5793ee643a021a717b6a1a08..2f2fb63737d1b841a51acf6acdfef26d9d77639f 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 0000000000000000000000000000000000000000..b2da89ffc123cff8c927d474778de6ab41d91e33 --- /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 0000000000000000000000000000000000000000..92d90dd777f068ad336c365bacc5a1bd4da13e42 --- /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 c6ec2e707dc448f423707a8dcd1d8127de97db4b..da465fa5d11fcbbec47fef771ca38e6d50b72ff6 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 cff1d538da42f276efbc49788e68ae4f6090380a..fcb455165b86a7274fc7d83302e8223dc7101a2b 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 12857528cec1ac7a6dc8af6141a349b9cba11db8..f0c6d50f782af10472ae25db85bf8275e8762c40 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 3e67649b1eab4e2acb7133fab1e243052afcaefb..14f5819e5b095d4c493c9cc5d6b5c29eb66c5617 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 0610e274f22ada6b9981745d18c656d5f28c96a1..4eb90fcfaa7d5a5b03aac17c610f3619f215a028 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 218dd1ff5c4d2eda5d545bf045d554aa0070e837..d72173fd0464c428ef27769e11f2c2eba8fa410d 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 15042338609249c93bf68f395d11f0bba4c68838..b52a546b5ac6834b5ab50a05d92db31ec1d92bb8 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 52c06f2373298b9a57a88f9d1e295f751db3ae0e..9a7b4188c7d654de2c9395abcd94810cc36cd87e 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 3efb3f6a8e22fa2b3f6570a6675016f2c61e495d..ebfca8a82d63272abfa6df82ae1a6f2c8771d840 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 ca590c79bcc0cc864a305b2f56b86a6ba367b10b..fd5f836b9b929f9867fc570ebf15228ca4eef630 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 0000000000000000000000000000000000000000..c2acc00607c83b8dec1f39f13ee7168557689c3e --- /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 5af4a2d9022c41fbdcf7227dc376eae935bf7ffe..0000000000000000000000000000000000000000 --- 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 c3f9e460c514f460c36b112a067e728b196b69fc..b71936138f78c8d054d70ccb5f3754da48a9c90d 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 9a10a7827f39bc45905c938200862c827bf707c2..ad00a7b0684aeebd6b7ee724f968f81de8211bec 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 8cdd32dc37b03b528ee28f90868880fb98547666..1ccfafb6d54f624b69aea11c3c15339a4fbae8e9 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 fadf283d5001e3a1e03f79698871b3590022c387..5e1a90cdad353c448667b23ddaa5c86baf2a9813 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 3313e5967d296917875d853516a3bfcaa749f711..6db981e1ee2ba1a0c98cb52e6f5605586a6ff371 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 02aa39a6ee1af8d7891ff29850ff13866db409fa..3d2fb30aef2cad40d0b7170087e45749bbb45d09 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 0000000000000000000000000000000000000000..26944757b9a9508c72dd25632952485cda5be510 --- /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 0000000000000000000000000000000000000000..59d80cbad962cb17e27ddef50dbfd5fc44d5a718 --- /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 0000000000000000000000000000000000000000..6c0d91f615dea75d57ecedd23ef85feaad4e6ee2 --- /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 0000000000000000000000000000000000000000..f0cd96d77d3486b895001617f8c02052b81a7d9f --- /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 0000000000000000000000000000000000000000..0d8feb802d1f440b600e925322d64c813c9233d7 --- /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 0000000000000000000000000000000000000000..0925c42fc4f50c4b1cc048681148749ba3d0dfee --- /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 0000000000000000000000000000000000000000..a7ea95df17ed99169f442080cae763e0ecfbe68e --- /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 0000000000000000000000000000000000000000..d5895181a75d9d6cc1a27ccb8b5b5f5be5e36a02 --- /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 360dcc16406f687b4d4b179c34d6999a54189f78..19492b4a201c9d5b25aa90c6b89c3921c6fa2b28 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 ec5766a96a978a05b31baeafddde8527d5a456a5..79c8167f87e2ff45e96c14cfd10743a88e4d79ff 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 eb76c31397de32750c029a150efef7cb24e36e30..d441c275cf80edbc67a28fd60eb95de7f525a044 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 622911d660fb4632236f1e096bee45a111cdf898..343c02d29f62b7691d6167773f1465c8d2be27d7 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 bdfa0c575b3785bd8e2fe0930ebe927d45532f73..8e5fec0b82c53f51065acb6e55fe813fab104a3f 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 71e358e478067c805203df528b190593e12e67c0..f5ddd96261d04c600a75e6516991a6fa51f40a70 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 0a6bcd87d72b992e9e0341c8cc995eb96835f788..5b0de9c0b7508904d5684e96b3fe3b89269d0423 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 4459347a97511be5e656be7bc026d81dbfef2b93..d1714413244128c4c9882458fb08db6d4e57509b 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 cd95b00e940d1d98ec8809e11b47003fccb02ff1..01f04aca04f52195a4c1b9b509210ac88d784a84 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 2187ef84a2dbad4dd0cfa7986bdb4473b0af0462..77b015bc6cb8712734f5383ca58cd818e0a51f0f 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 7f46132a55df0a5de49633525d777d4dfa900ceb..0000000000000000000000000000000000000000 --- 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 3e3196205964131e6f7d75fa73b74fcad3fb0b22..0000000000000000000000000000000000000000 --- 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 8060aed27bcb37e41b52fa9261f3a535c5511957..0000000000000000000000000000000000000000 --- 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 d53c34fcd8a3f0ecd994296d559564bbb63df351..0000000000000000000000000000000000000000 --- 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 57f0d046398e94079a882f691c8edc3c9b0a27c7..0000000000000000000000000000000000000000 --- 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 b608e9dd2dffc1ecf6693f5803d164d40b20f2d9..0000000000000000000000000000000000000000 --- 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 9ca8ff1f5137065662141cd8f479271eba929330..0000000000000000000000000000000000000000 --- 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 1a7474c5ebd78ee2c98eec9eb5c4855ca766bc55..0000000000000000000000000000000000000000 --- 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 5f12d27b2145aa2d8265e6a62acea3aa25256538..0000000000000000000000000000000000000000 --- 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 931ea2292fe3cbbaed5f44c03f88771a4961eaa3..0000000000000000000000000000000000000000 --- 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 1533ee1740202592639c273ef2c6a667b2219091..0000000000000000000000000000000000000000 --- 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 e26de073de48ec1862749d77da6d776bd8518506..0000000000000000000000000000000000000000 --- 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 00d41e804a75c0410a43cc18e739a55fed707b38..0000000000000000000000000000000000000000 --- 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 ad3eda281acecdf67b7bb555ab1604836e9c0f78..33d49a5ca6245f447ac76bf60cc8d7e6dd46e73d 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'