diff --git a/android/gradle.properties b/android/gradle.properties index e6443382b31fab5fc027b99dc079154f78f27d0b..d965699510bdf71e00b8f08fe1031cef79d05911 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.28 -app.versionCode=28 +app.versionName=0.0.29 +app.versionCode=29 diff --git a/assets/translations/en.json b/assets/translations/en.json index 3f4f688426c83324af070f6d7dba37ed2c91edc8..6b82e28719f34bf4b043f9414da9ef18fb13bd43 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -1,5 +1,6 @@ { "app_name": "Scrobbles", + "": "", "bottom_nav_home": "Home", "bottom_nav_discoveries": "Discoveries", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 2f2fb63737d1b841a51acf6acdfef26d9d77639f..84b42363ca5567aaae73d4e7a84fc84cf192d47e 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -1,5 +1,6 @@ { "app_name": "Scrobbles", + "": "", "bottom_nav_home": "Accueil", "bottom_nav_discoveries": "Découvertes", diff --git a/fastlane/metadata/android/en-US/changelogs/29.txt b/fastlane/metadata/android/en-US/changelogs/29.txt new file mode 100644 index 0000000000000000000000000000000000000000..78d96208b7c9b6eba8c890124797c02aa0364add --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/29.txt @@ -0,0 +1 @@ +Save scrobbles data from API. diff --git a/fastlane/metadata/android/fr-FR/changelogs/29.txt b/fastlane/metadata/android/fr-FR/changelogs/29.txt new file mode 100644 index 0000000000000000000000000000000000000000..b2519526d8b2d62e1404334f5d5c9419c802e957 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/29.txt @@ -0,0 +1 @@ +Sauvegarde des données d'écoutes de l'API. diff --git a/lib/cubit/data_counts_by_day_cubit.dart b/lib/cubit/data_counts_by_day_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..032aec8f184a3d43f7d0363b57048d08dee4e78b --- /dev/null +++ b/lib/cubit/data_counts_by_day_cubit.dart @@ -0,0 +1,39 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +import 'package:scrobbles/models/counts_by_day.dart'; + +part 'data_counts_by_day_state.dart'; + +class DataCountsByDayCubit extends HydratedCubit<DataCountsByDayState> { + DataCountsByDayCubit() : super(const DataCountsByDayState()); + + void getData(DataCountsByDayState state) { + emit(state); + } + + CountsByDayData? getValue() { + return state.countsByDay; + } + + void setValue(CountsByDayData? countsByDay) { + emit(DataCountsByDayState( + countsByDay: countsByDay, + )); + } + + @override + DataCountsByDayState? fromJson(Map<String, dynamic> json) { + return DataCountsByDayState( + countsByDay: CountsByDayData.fromJson(json['countsByDay']), + ); + } + + @override + Map<String, Object?>? toJson(DataCountsByDayState state) { + return <String, Object?>{ + 'countsByDay': state.countsByDay?.toJson(), + }; + } +} diff --git a/lib/cubit/data_counts_by_day_state.dart b/lib/cubit/data_counts_by_day_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..724bd73411f6c5f22caeab39a101ab92af376713 --- /dev/null +++ b/lib/cubit/data_counts_by_day_state.dart @@ -0,0 +1,15 @@ +part of 'data_counts_by_day_cubit.dart'; + +@immutable +class DataCountsByDayState extends Equatable { + const DataCountsByDayState({ + this.countsByDay, + }); + + final CountsByDayData? countsByDay; + + @override + List<Object?> get props => <Object?>[ + countsByDay, + ]; +} diff --git a/lib/cubit/data_counts_by_hour_cubit.dart b/lib/cubit/data_counts_by_hour_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..2184993239ab427e7417a420811fbc397b65451c --- /dev/null +++ b/lib/cubit/data_counts_by_hour_cubit.dart @@ -0,0 +1,39 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +import 'package:scrobbles/models/counts_by_hour.dart'; + +part 'data_counts_by_hour_state.dart'; + +class DataCountsByHourCubit extends HydratedCubit<DataCountsByHourState> { + DataCountsByHourCubit() : super(const DataCountsByHourState()); + + void getData(DataCountsByHourState state) { + emit(state); + } + + CountsByHourData? getValue() { + return state.countsByHour; + } + + void setValue(CountsByHourData? countsByHour) { + emit(DataCountsByHourState( + countsByHour: countsByHour, + )); + } + + @override + DataCountsByHourState? fromJson(Map<String, dynamic> json) { + return DataCountsByHourState( + countsByHour: CountsByHourData.fromJson(json['countsByHour']), + ); + } + + @override + Map<String, Object?>? toJson(DataCountsByHourState state) { + return <String, Object?>{ + 'countsByHour': state.countsByHour?.toJson(), + }; + } +} diff --git a/lib/cubit/data_counts_by_hour_state.dart b/lib/cubit/data_counts_by_hour_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..3fc9aef713e632d27dcb8b002f314cbd62ba578c --- /dev/null +++ b/lib/cubit/data_counts_by_hour_state.dart @@ -0,0 +1,15 @@ +part of 'data_counts_by_hour_cubit.dart'; + +@immutable +class DataCountsByHourState extends Equatable { + const DataCountsByHourState({ + this.countsByHour, + }); + + final CountsByHourData? countsByHour; + + @override + List<Object?> get props => <Object?>[ + countsByHour, + ]; +} diff --git a/lib/cubit/data_discoveries_cubit.dart b/lib/cubit/data_discoveries_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..1b9ff976d988edd3bd1b9f85237e8465ca5ed182 --- /dev/null +++ b/lib/cubit/data_discoveries_cubit.dart @@ -0,0 +1,39 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +import 'package:scrobbles/models/discoveries.dart'; + +part 'data_discoveries_state.dart'; + +class DataDiscoveriesCubit extends HydratedCubit<DataDiscoveriesState> { + DataDiscoveriesCubit() : super(const DataDiscoveriesState()); + + void getData(DataDiscoveriesState state) { + emit(state); + } + + DiscoveriesData? getValue() { + return state.discoveries; + } + + void setValue(DiscoveriesData? discoveries) { + emit(DataDiscoveriesState( + discoveries: discoveries, + )); + } + + @override + DataDiscoveriesState? fromJson(Map<String, dynamic> json) { + return DataDiscoveriesState( + discoveries: DiscoveriesData.fromJson(json['discoveries']), + ); + } + + @override + Map<String, Object?>? toJson(DataDiscoveriesState state) { + return <String, Object?>{ + 'discoveries': state.discoveries?.toJson(), + }; + } +} diff --git a/lib/cubit/data_discoveries_state.dart b/lib/cubit/data_discoveries_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..1d43883563ef73f81d0ce636c6977b5916d837e8 --- /dev/null +++ b/lib/cubit/data_discoveries_state.dart @@ -0,0 +1,15 @@ +part of 'data_discoveries_cubit.dart'; + +@immutable +class DataDiscoveriesState extends Equatable { + const DataDiscoveriesState({ + this.discoveries, + }); + + final DiscoveriesData? discoveries; + + @override + List<Object?> get props => <Object?>[ + discoveries, + ]; +} diff --git a/lib/cubit/data_statistics_global_cubit.dart b/lib/cubit/data_statistics_global_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..28e7e6b92790c8506cbe7064c5cd223776a96490 --- /dev/null +++ b/lib/cubit/data_statistics_global_cubit.dart @@ -0,0 +1,39 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +import 'package:scrobbles/models/statistics_global.dart'; + +part 'data_statistics_global_state.dart'; + +class DataStatisticsGlobalCubit extends HydratedCubit<DataStatisticsGlobalState> { + DataStatisticsGlobalCubit() : super(const DataStatisticsGlobalState()); + + void getData(DataStatisticsGlobalState state) { + emit(state); + } + + StatisticsGlobalData? getValue() { + return state.statisticsGlobal; + } + + void setValue(StatisticsGlobalData? statisticsGlobal) { + emit(DataStatisticsGlobalState( + statisticsGlobal: statisticsGlobal, + )); + } + + @override + DataStatisticsGlobalState? fromJson(Map<String, dynamic> json) { + return DataStatisticsGlobalState( + statisticsGlobal: StatisticsGlobalData.fromJson(json['statisticsGlobal']), + ); + } + + @override + Map<String, Object?>? toJson(DataStatisticsGlobalState state) { + return <String, Object?>{ + 'statisticsGlobal': state.statisticsGlobal?.toJson(), + }; + } +} diff --git a/lib/cubit/data_statistics_global_state.dart b/lib/cubit/data_statistics_global_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..89ef0fd2a136d43ad291d44fc5899296ae1bd9e8 --- /dev/null +++ b/lib/cubit/data_statistics_global_state.dart @@ -0,0 +1,15 @@ +part of 'data_statistics_global_cubit.dart'; + +@immutable +class DataStatisticsGlobalState extends Equatable { + const DataStatisticsGlobalState({ + this.statisticsGlobal, + }); + + final StatisticsGlobalData? statisticsGlobal; + + @override + List<Object?> get props => <Object?>[ + statisticsGlobal, + ]; +} diff --git a/lib/cubit/data_statistics_recent_cubit.dart b/lib/cubit/data_statistics_recent_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..d2bc4457c434fdfac1bd6a98e3b07ee0aa8d7db1 --- /dev/null +++ b/lib/cubit/data_statistics_recent_cubit.dart @@ -0,0 +1,39 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +import 'package:scrobbles/models/statistics_recent.dart'; + +part 'data_statistics_recent_state.dart'; + +class DataStatisticsRecentCubit extends HydratedCubit<DataStatisticsRecentState> { + DataStatisticsRecentCubit() : super(const DataStatisticsRecentState()); + + void getData(DataStatisticsRecentState state) { + emit(state); + } + + StatisticsRecentData? getValue() { + return state.statisticsRecent; + } + + void setValue(StatisticsRecentData? statisticsRecent) { + emit(DataStatisticsRecentState( + statisticsRecent: statisticsRecent, + )); + } + + @override + DataStatisticsRecentState? fromJson(Map<String, dynamic> json) { + return DataStatisticsRecentState( + statisticsRecent: StatisticsRecentData.fromJson(json['statisticsRecent']), + ); + } + + @override + Map<String, Object?>? toJson(DataStatisticsRecentState state) { + return <String, Object?>{ + 'statisticsRecent': state.statisticsRecent?.toJson(), + }; + } +} diff --git a/lib/cubit/data_statistics_recent_state.dart b/lib/cubit/data_statistics_recent_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..1bf9d2f846d7159d1e26151420beac984d7b69e2 --- /dev/null +++ b/lib/cubit/data_statistics_recent_state.dart @@ -0,0 +1,15 @@ +part of 'data_statistics_recent_cubit.dart'; + +@immutable +class DataStatisticsRecentState extends Equatable { + const DataStatisticsRecentState({ + this.statisticsRecent, + }); + + final StatisticsRecentData? statisticsRecent; + + @override + List<Object?> get props => <Object?>[ + statisticsRecent, + ]; +} diff --git a/lib/cubit/data_timeline_cubit.dart b/lib/cubit/data_timeline_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..597e59407f6ee53ee20d6afd7e3e98efe2fb93a2 --- /dev/null +++ b/lib/cubit/data_timeline_cubit.dart @@ -0,0 +1,39 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +import 'package:scrobbles/models/timeline.dart'; + +part 'data_timeline_state.dart'; + +class DataTimelineCubit extends HydratedCubit<DataTimelineState> { + DataTimelineCubit() : super(const DataTimelineState()); + + void getData(DataTimelineState state) { + emit(state); + } + + TimelineData? getValue() { + return state.timeline; + } + + void setValue(TimelineData? timeline) { + emit(DataTimelineState( + timeline: timeline, + )); + } + + @override + DataTimelineState? fromJson(Map<String, dynamic> json) { + return DataTimelineState( + timeline: TimelineData.fromJson(json['timeline']), + ); + } + + @override + Map<String, Object?>? toJson(DataTimelineState state) { + return <String, Object?>{ + 'timeline': state.timeline?.toJson(), + }; + } +} diff --git a/lib/cubit/data_timeline_state.dart b/lib/cubit/data_timeline_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..b0531c799f3d0ec00ba4e0f1532830ba513f98c9 --- /dev/null +++ b/lib/cubit/data_timeline_state.dart @@ -0,0 +1,15 @@ +part of 'data_timeline_cubit.dart'; + +@immutable +class DataTimelineState extends Equatable { + const DataTimelineState({ + this.timeline, + }); + + final TimelineData? timeline; + + @override + List<Object?> get props => <Object?>[ + timeline, + ]; +} diff --git a/lib/cubit/data_top_artists_cubit.dart b/lib/cubit/data_top_artists_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..0011c5ebaeefa1963fd7bc89d7ac6968f6794709 --- /dev/null +++ b/lib/cubit/data_top_artists_cubit.dart @@ -0,0 +1,39 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:hydrated_bloc/hydrated_bloc.dart'; + +import 'package:scrobbles/models/topartists.dart'; + +part 'data_top_artists_state.dart'; + +class DataTopArtistsCubit extends HydratedCubit<DataTopArtistsState> { + DataTopArtistsCubit() : super(const DataTopArtistsState()); + + void getData(DataTopArtistsState state) { + emit(state); + } + + TopArtistsData? getValue(key) { + return state.topArtists; + } + + void setValue(TopArtistsData? topArtists) { + emit(DataTopArtistsState( + topArtists: topArtists, + )); + } + + @override + DataTopArtistsState? fromJson(Map<String, dynamic> json) { + return DataTopArtistsState( + topArtists: TopArtistsData.fromJson(json['topArtists']), + ); + } + + @override + Map<String, Object?>? toJson(DataTopArtistsState state) { + return <String, Object?>{ + 'topArtists': state.topArtists?.toJson(), + }; + } +} diff --git a/lib/cubit/data_top_artists_state.dart b/lib/cubit/data_top_artists_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..e6d14c01e33aa04f23dcb9bb0bb89342f919767a --- /dev/null +++ b/lib/cubit/data_top_artists_state.dart @@ -0,0 +1,15 @@ +part of 'data_top_artists_cubit.dart'; + +@immutable +class DataTopArtistsState extends Equatable { + const DataTopArtistsState({ + this.topArtists, + }); + + final TopArtistsData? topArtists; + + @override + List<Object?> get props => <Object?>[ + topArtists, + ]; +} diff --git a/lib/models/counts_by_day.dart b/lib/models/counts_by_day.dart index fcb455165b86a7274fc7d83302e8223dc7101a2b..27e41f6783fc5e4f408e2266723d5dc1fb5c3079 100644 --- a/lib/models/counts_by_day.dart +++ b/lib/models/counts_by_day.dart @@ -19,11 +19,7 @@ class CountsByDayData { return CountsByDayData(data: data); } - factory CountsByDayData.createEmpty() { - return CountsByDayData.fromJson({'counts-by-day': {}}); - } - - String toString() { + Map<String, Object?>? toJson() { Map<String, double> map = {}; this.data.keys.forEach((day) { @@ -31,6 +27,10 @@ class CountsByDayData { map[day.toString()] = value != null ? value.toDouble() : 0.0; }); - return jsonEncode({'counts-by-day': map}); + return {'counts-by-day': map}; + } + + String toString() { + return jsonEncode(this.toJson()); } } diff --git a/lib/models/counts_by_hour.dart b/lib/models/counts_by_hour.dart index f0c6d50f782af10472ae25db85bf8275e8762c40..7bf380294d2dc2addace67a473cbe05865ac1d69 100644 --- a/lib/models/counts_by_hour.dart +++ b/lib/models/counts_by_hour.dart @@ -21,11 +21,7 @@ class CountsByHourData { return CountsByHourData(data: data); } - factory CountsByHourData.createEmpty() { - return CountsByHourData.fromJson({}); - } - - String toString() { + Map<String, Object?>? toJson() { Map<String, double> map = {}; this.data.keys.forEach((day) { @@ -33,6 +29,10 @@ class CountsByHourData { map[day.toString()] = value != null ? value.toDouble() : 0.0; }); - return jsonEncode({'counts-by-hour': map}); + return {'counts-by-hour': map}; + } + + String toString() { + return jsonEncode(this.toJson()); } } diff --git a/lib/models/discoveries.dart b/lib/models/discoveries.dart index 14f5819e5b095d4c493c9cc5d6b5c29eb66c5617..386098f5304e5b7b326c7b48f3e3ba187f7602fd 100644 --- a/lib/models/discoveries.dart +++ b/lib/models/discoveries.dart @@ -36,11 +36,7 @@ class DiscoveriesData { return DiscoveriesData(data: data); } - factory DiscoveriesData.createEmpty() { - return DiscoveriesData.fromJson({}); - } - - String toString() { + Map<String, Object?>? toJson() { Map<String, Map<String, int>> map = {}; this.data.keys.forEach((element) { @@ -51,6 +47,10 @@ class DiscoveriesData { }; }); - return jsonEncode(map); + return map; + } + + String toString() { + return jsonEncode(this.toJson()); } } diff --git a/lib/models/statistics_global.dart b/lib/models/statistics_global.dart index 4eb90fcfaa7d5a5b03aac17c610f3619f215a028..1f87265ed5902f2515066761fc7c7d9cea515de9 100644 --- a/lib/models/statistics_global.dart +++ b/lib/models/statistics_global.dart @@ -1,8 +1,8 @@ import 'dart:convert'; class StatisticsGlobalData { - final int totalCount; - final DateTime lastScrobble; + final int? totalCount; + final DateTime? lastScrobble; const StatisticsGlobalData({ required this.totalCount, @@ -11,27 +11,25 @@ class StatisticsGlobalData { factory StatisticsGlobalData.fromJson(Map<String, dynamic>? json) { return StatisticsGlobalData( - totalCount: (json?['totalCount'] != null) ? (json?['totalCount'] as int) : 0, + totalCount: (json?['totalCount'] != null) ? (json?['totalCount'] as int) : null, lastScrobble: (json?['lastScrobble'] != null && json?['lastScrobble']['date'] != null) ? DateTime.parse( json?['lastScrobble']['date'], ) - : DateTime.now(), + : null, ); } - factory StatisticsGlobalData.createEmpty() { - return StatisticsGlobalData.fromJson({}); - } - - String toString() { - Map<String, dynamic> map = { + Map<String, Object?>? toJson() { + return <String, Object?>{ 'totalCount': this.totalCount, 'lastScrobble': { - 'date': this.lastScrobble.toString(), + 'date': this.lastScrobble != null ? this.lastScrobble.toString() : null, }, }; + } - return jsonEncode(map); + String toString() { + return jsonEncode(this.toJson()); } } diff --git a/lib/models/statistics_recent.dart b/lib/models/statistics_recent.dart index d72173fd0464c428ef27769e11f2c2eba8fa410d..1f342f9e7d0627789d097eeb17ca5ce8a761ac32 100644 --- a/lib/models/statistics_recent.dart +++ b/lib/models/statistics_recent.dart @@ -1,10 +1,10 @@ import 'dart:convert'; class StatisticsRecentData { - final int recentCount; - final int firstPlayedArtistsCount; - final int firstPlayedTracksCount; - final int selectedPeriod; + final int? recentCount; + final int? firstPlayedArtistsCount; + final int? firstPlayedTracksCount; + final int? selectedPeriod; const StatisticsRecentData({ required this.recentCount, @@ -15,29 +15,28 @@ class StatisticsRecentData { factory StatisticsRecentData.fromJson(Map<String, dynamic>? json) { return StatisticsRecentData( - recentCount: (json?['recentCount'] != null) ? (json?['recentCount'] as int) : 0, + recentCount: (json?['recentCount'] != null) ? (json?['recentCount'] as int) : null, firstPlayedArtistsCount: (json?['firstPlayedArtistsCount'] != null) ? (json?['firstPlayedArtistsCount'] as int) - : 0, + : null, firstPlayedTracksCount: (json?['firstPlayedTracksCount'] != null) ? (json?['firstPlayedTracksCount'] as int) - : 0, - selectedPeriod: (json?['selectedPeriod'] != null) ? (json?['selectedPeriod'] as int) : 0, + : null, + selectedPeriod: + (json?['selectedPeriod'] != null) ? (json?['selectedPeriod'] as int) : null, ); } - factory StatisticsRecentData.createEmpty() { - return StatisticsRecentData.fromJson({}); - } - - String toString() { - Map<String, dynamic> map = { + Map<String, Object?>? toJson() { + return <String, Object?>{ 'recentCount': this.recentCount, 'firstPlayedArtistsCount': this.firstPlayedArtistsCount, 'firstPlayedTracksCount': this.firstPlayedTracksCount, 'selectedPeriod': this.selectedPeriod, }; + } - return jsonEncode(map); + String toString() { + return jsonEncode(this.toJson()); } } diff --git a/lib/models/timeline.dart b/lib/models/timeline.dart index b52a546b5ac6834b5ab50a05d92db31ec1d92bb8..37f987bffb13395954c16714daf91c8eda54ed27 100644 --- a/lib/models/timeline.dart +++ b/lib/models/timeline.dart @@ -36,11 +36,7 @@ class TimelineData { return TimelineData(data: data); } - factory TimelineData.createEmpty() { - return TimelineData.fromJson({}); - } - - String toString() { + Map<String, Object?>? toJson() { Map<String, Map<String, int>> map = {}; this.data.keys.forEach((element) { @@ -51,6 +47,10 @@ class TimelineData { }; }); - return jsonEncode(map); + return map; + } + + String toString() { + return jsonEncode(this.toJson()); } } diff --git a/lib/models/topartists.dart b/lib/models/topartists.dart index 9a7b4188c7d654de2c9395abcd94810cc36cd87e..6c2719047ed1f8f5f05bc51e9aa9decb12b09fca 100644 --- a/lib/models/topartists.dart +++ b/lib/models/topartists.dart @@ -38,13 +38,7 @@ class TopArtistsData { ); } - factory TopArtistsData.createEmpty() { - return TopArtistsData.fromJson({ - 'top-artists': [], - }); - } - - String toString() { + Map<String, Object?>? toJson() { List<Map<String, Object>> listArtists = []; this.topArtists.forEach((TopArtistsDataValue? item) { @@ -54,8 +48,12 @@ class TopArtistsData { }); }); - return jsonEncode({ + return { 'top-artists': listArtists, - }); + }; + } + + String toString() { + return jsonEncode(this.toJson()); } } diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart index 6db981e1ee2ba1a0c98cb52e6f5605586a6ff371..63256fb5c924341ea98dcbc917c1858749955826 100644 --- a/lib/ui/widgets/app_bar.dart +++ b/lib/ui/widgets/app_bar.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:unicons/unicons.dart'; +import 'package:scrobbles/ui/widgets/update_data.dart'; import 'package:scrobbles/ui/widgets/header_app.dart'; class StandardAppBar extends StatelessWidget implements PreferredSizeWidget { @@ -13,6 +14,7 @@ class StandardAppBar extends StatelessWidget implements PreferredSizeWidget { return AppBar( title: const AppHeader(text: 'app_name'), actions: [ + UpdateData(), IconButton( onPressed: () { this.notifyParent(); diff --git a/lib/ui/widgets/cards/counts_by_day.dart b/lib/ui/widgets/cards/counts_by_day.dart index 59d80cbad962cb17e27ddef50dbfd5fc44d5a718..98c6cfef40b4af7f06c6c4b557c2c377f189537b 100644 --- a/lib/ui/widgets/cards/counts_by_day.dart +++ b/lib/ui/widgets/cards/counts_by_day.dart @@ -2,12 +2,12 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:scrobbles/cubit/data_counts_by_day_cubit.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}); @@ -15,30 +15,25 @@ class CardCountsByDay extends StatelessWidget { @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, - ), - ); - }, + return BlocProvider<DataCountsByDayCubit>( + create: (BuildContext context) => DataCountsByDayCubit(), + child: BlocBuilder<DataCountsByDayCubit, DataCountsByDayState>( + builder: (BuildContext context, DataCountsByDayState state) { + return CardContent( + color: Theme.of(context).colorScheme.surface, + title: 'counts_by_day'.tr( + namedArgs: { + 'daysCount': daysCount.toString(), + }, + ), + content: ChartCountsByDay( + chartData: CountsByDayData.fromJson(jsonDecode(state.countsByDay.toString())), + isLoading: false, + ), + ); + }, + ), ); } } diff --git a/lib/ui/widgets/cards/counts_by_hour.dart b/lib/ui/widgets/cards/counts_by_hour.dart index 6c0d91f615dea75d57ecedd23ef85feaad4e6ee2..595818e2c78dd023d540c312bff90be8d6d230a0 100644 --- a/lib/ui/widgets/cards/counts_by_hour.dart +++ b/lib/ui/widgets/cards/counts_by_hour.dart @@ -2,12 +2,12 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:scrobbles/cubit/data_counts_by_hour_cubit.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}); @@ -15,30 +15,25 @@ class CardCountsByHour extends StatelessWidget { @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, - ), - ); - }, + return BlocProvider<DataCountsByHourCubit>( + create: (BuildContext context) => DataCountsByHourCubit(), + child: BlocBuilder<DataCountsByHourCubit, DataCountsByHourState>( + builder: (BuildContext context, DataCountsByHourState state) { + return CardContent( + color: Theme.of(context).colorScheme.surface, + title: 'counts_by_hour'.tr( + namedArgs: { + 'daysCount': daysCount.toString(), + }, + ), + content: ChartCountsByHour( + chartData: CountsByHourData.fromJson(jsonDecode(state.countsByHour.toString())), + isLoading: false, + ), + ); + }, + ), ); } } diff --git a/lib/ui/widgets/cards/discoveries.dart b/lib/ui/widgets/cards/discoveries.dart index f0cd96d77d3486b895001617f8c02052b81a7d9f..fb3baf5cf9386084d3624fa02ac72b3eb7de42df 100644 --- a/lib/ui/widgets/cards/discoveries.dart +++ b/lib/ui/widgets/cards/discoveries.dart @@ -2,13 +2,13 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:scrobbles/cubit/data_discoveries_cubit.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}); @@ -16,51 +16,50 @@ class CardDiscoveries extends StatelessWidget { @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}'); - } + return BlocProvider<DataDiscoveriesCubit>( + create: (BuildContext context) => DataDiscoveriesCubit(), + child: BlocBuilder<DataDiscoveriesCubit, DataDiscoveriesState>( + builder: (BuildContext context, DataDiscoveriesState state) { + final TextTheme textTheme = Theme.of(context).primaryTextTheme; - 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, - ), - ], - ), - ); - }, + 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(state.discoveries.toString())), + isLoading: false, + ), + const SizedBox(height: 8), + Text( + 'discoveries_tracks_title', + style: textTheme.titleMedium!.apply(fontWeightDelta: 2), + ).tr(), + const SizedBox(height: 8), + ChartDiscoveriesTracks( + chartData: + DiscoveriesData.fromJson(jsonDecode(state.discoveries.toString())), + isLoading: false, + ), + ], + ), + ); + }, + ), ); } } diff --git a/lib/ui/widgets/cards/statistics_global.dart b/lib/ui/widgets/cards/statistics_global.dart index 0d8feb802d1f440b600e925322d64c813c9233d7..4980d5cde96e39050b3c91ef5dfb0de5528bbcbc 100644 --- a/lib/ui/widgets/cards/statistics_global.dart +++ b/lib/ui/widgets/cards/statistics_global.dart @@ -2,38 +2,33 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:scrobbles/cubit/data_statistics_global_cubit.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, - ), - ); - }, + return BlocProvider<DataStatisticsGlobalCubit>( + create: (BuildContext context) => DataStatisticsGlobalCubit(), + child: BlocBuilder<DataStatisticsGlobalCubit, DataStatisticsGlobalState>( + builder: (BuildContext context, DataStatisticsGlobalState state) { + return CardContent( + color: Theme.of(context).colorScheme.primary, + title: 'global_statistics'.tr(), + content: ContentStatisticsGlobal( + statistics: + StatisticsGlobalData.fromJson(jsonDecode(state.statisticsGlobal.toString())), + isLoading: false, + ), + ); + }, + ), ); } } diff --git a/lib/ui/widgets/cards/statistics_recent.dart b/lib/ui/widgets/cards/statistics_recent.dart index 0925c42fc4f50c4b1cc048681148749ba3d0dfee..9a14c8af7854054e2b5dfe64a7d4aad842b83973 100644 --- a/lib/ui/widgets/cards/statistics_recent.dart +++ b/lib/ui/widgets/cards/statistics_recent.dart @@ -2,12 +2,12 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:scrobbles/cubit/data_statistics_recent_cubit.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}); @@ -16,30 +16,26 @@ class CardStatisticsRecent extends StatelessWidget { 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, - ), - ); - }, + // data context + return BlocProvider<DataStatisticsRecentCubit>( + create: (BuildContext context) => DataStatisticsRecentCubit(), + child: BlocBuilder<DataStatisticsRecentCubit, DataStatisticsRecentState>( + builder: (BuildContext context, DataStatisticsRecentState dataState) { + return CardContent( + color: Theme.of(context).colorScheme.primary, + title: 'recent_statistics'.tr( + namedArgs: { + 'daysCount': daysCount.toString(), + }, + ), + content: ContentStatisticsRecent( + statistics: StatisticsRecentData.fromJson( + jsonDecode(dataState.statisticsRecent.toString())), + isLoading: false, + ), + ); + }, + ), ); } } diff --git a/lib/ui/widgets/cards/timeline.dart b/lib/ui/widgets/cards/timeline.dart index a7ea95df17ed99169f442080cae763e0ecfbe68e..a7b20d44c2f99a346ebd52b9749a617153f85b34 100644 --- a/lib/ui/widgets/cards/timeline.dart +++ b/lib/ui/widgets/cards/timeline.dart @@ -2,13 +2,13 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:scrobbles/cubit/data_timeline_cubit.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}); @@ -16,36 +16,33 @@ class CardTimeline extends StatelessWidget { @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, - ), - ], - ), - ); - }, + return BlocProvider<DataTimelineCubit>( + create: (BuildContext context) => DataTimelineCubit(), + child: BlocBuilder<DataTimelineCubit, DataTimelineState>( + builder: (BuildContext context, DataTimelineState state) { + return CardContent( + color: Theme.of(context).colorScheme.surface, + title: 'timeline_title'.tr( + namedArgs: { + 'daysCount': daysCount.toString(), + }, + ), + content: Stack( + children: [ + ChartTimelineCounts( + chartData: TimelineData.fromJson(jsonDecode(state.timeline.toString())), + isLoading: false, + ), + ChartTimelineEclecticism( + chartData: TimelineData.fromJson(jsonDecode(state.timeline.toString())), + isLoading: false, + ), + ], + ), + ); + }, + ), ); } } diff --git a/lib/ui/widgets/cards/top_artists.dart b/lib/ui/widgets/cards/top_artists.dart index d5895181a75d9d6cc1a27ccb8b5b5f5be5e36a02..7e05208ed4c1c054a644fe9d3f1cbf5dc1122407 100644 --- a/lib/ui/widgets/cards/top_artists.dart +++ b/lib/ui/widgets/cards/top_artists.dart @@ -2,12 +2,12 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:scrobbles/cubit/data_top_artists_cubit.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}); @@ -15,30 +15,25 @@ class CardTopArtists extends StatelessWidget { @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, - ), - ); - }, + return BlocProvider<DataTopArtistsCubit>( + create: (BuildContext context) => DataTopArtistsCubit(), + child: BlocBuilder<DataTopArtistsCubit, DataTopArtistsState>( + builder: (BuildContext context, DataTopArtistsState state) { + return CardContent( + color: Theme.of(context).colorScheme.surface, + title: 'top_artists_title'.tr( + namedArgs: { + 'daysCount': daysCount.toString(), + }, + ), + content: ChartTopArtists( + chartData: TopArtistsData.fromJson(jsonDecode(state.topArtists.toString())), + isLoading: false, + ), + ); + }, + ), ); } } diff --git a/lib/ui/widgets/content/statistics_global.dart b/lib/ui/widgets/content/statistics_global.dart index d1714413244128c4c9882458fb08db6d4e57509b..c68d2492c70af36bc7ea60f4a040cfcb6bb6d3c9 100644 --- a/lib/ui/widgets/content/statistics_global.dart +++ b/lib/ui/widgets/content/statistics_global.dart @@ -24,7 +24,11 @@ class ContentStatisticsGlobal extends StatelessWidget { style: textTheme.bodyMedium, ).tr( namedArgs: { - 'count': this.isLoading ? placeholder : this.statistics.totalCount.toString(), + 'count': this.isLoading + ? placeholder + : (this.statistics.totalCount != null + ? this.statistics.totalCount.toString() + : ''), }, ), Text( @@ -34,7 +38,9 @@ class ContentStatisticsGlobal extends StatelessWidget { namedArgs: { 'datetime': this.isLoading ? placeholder - : DateFormat().format(this.statistics.lastScrobble), + : (this.statistics.lastScrobble != null + ? DateFormat().format(this.statistics.lastScrobble ?? DateTime.now()) + : ''), }, ), ], diff --git a/lib/ui/widgets/content/statistics_recent.dart b/lib/ui/widgets/content/statistics_recent.dart index 01f04aca04f52195a4c1b9b509210ac88d784a84..cecbff94f77cb6918fd0a3799fb3969ae9da68e1 100644 --- a/lib/ui/widgets/content/statistics_recent.dart +++ b/lib/ui/widgets/content/statistics_recent.dart @@ -20,7 +20,11 @@ class ContentStatisticsRecent extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( - 'statistics_recent_scrobbles_count_and_discoveries', + (this.statistics.recentCount != null && + this.statistics.firstPlayedArtistsCount != null && + this.statistics.firstPlayedTracksCount != null) + ? 'statistics_recent_scrobbles_count_and_discoveries' + : '', style: textTheme.bodyMedium, ).tr( namedArgs: { diff --git a/lib/ui/widgets/update_data.dart b/lib/ui/widgets/update_data.dart new file mode 100644 index 0000000000000000000000000000000000000000..7bc41016e1ca6fbed5b03c969f30ab25b157dbff --- /dev/null +++ b/lib/ui/widgets/update_data.dart @@ -0,0 +1,209 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'package:scrobbles/cubit/data_counts_by_day_cubit.dart'; +import 'package:scrobbles/cubit/data_counts_by_hour_cubit.dart'; +import 'package:scrobbles/cubit/data_discoveries_cubit.dart'; +import 'package:scrobbles/cubit/data_statistics_global_cubit.dart'; +import 'package:scrobbles/cubit/data_statistics_recent_cubit.dart'; +import 'package:scrobbles/cubit/data_timeline_cubit.dart'; +import 'package:scrobbles/cubit/data_top_artists_cubit.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'; +import 'package:scrobbles/network/scrobbles.dart'; +import 'package:scrobbles/ui/widgets/error.dart'; + +class UpdateData extends StatelessWidget { + const UpdateData({super.key}); + + final int daysCount = 21; + final Widget loading = const Text('â³'); + final Widget done = const Text(''); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.all(4), + child: Stack( + children: [ + updateCountsByDay(daysCount), + updateCountsByHour(daysCount), + updateDiscoveries(daysCount), + updateStatisticsGlobal(), + updateStatisticsRecent(daysCount), + updateTimeline(daysCount), + updateTopArtists(daysCount), + ], + ), + ); + } + + Widget updateCountsByDay(int daysCount) { + late Future<CountsByDayData> futureCountsByDay = ScrobblesApi.fetchCountsByDay(daysCount); + + return BlocProvider<DataCountsByDayCubit>( + create: (BuildContext context) => DataCountsByDayCubit(), + child: BlocBuilder<DataCountsByDayCubit, DataCountsByDayState>( + builder: (BuildContext context, DataCountsByDayState state) { + return FutureBuilder<CountsByDayData>( + future: futureCountsByDay, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + BlocProvider.of<DataCountsByDayCubit>(context).setValue(snapshot.data); + return !snapshot.hasData ? loading : done; + }, + ); + }, + ), + ); + } + + Widget updateCountsByHour(int daysCount) { + late Future<CountsByHourData> futureCountsByHour = + ScrobblesApi.fetchCountsByHour(daysCount); + + return BlocProvider<DataCountsByHourCubit>( + create: (BuildContext context) => DataCountsByHourCubit(), + child: BlocBuilder<DataCountsByHourCubit, DataCountsByHourState>( + builder: (BuildContext context, DataCountsByHourState state) { + return FutureBuilder<CountsByHourData>( + future: futureCountsByHour, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + BlocProvider.of<DataCountsByHourCubit>(context).setValue(snapshot.data); + return !snapshot.hasData ? loading : done; + }, + ); + }, + ), + ); + } + + Widget updateDiscoveries(int daysCount) { + late Future<DiscoveriesData> futureDiscoveries = ScrobblesApi.fetchDiscoveries(daysCount); + + return BlocProvider<DataDiscoveriesCubit>( + create: (BuildContext context) => DataDiscoveriesCubit(), + child: BlocBuilder<DataDiscoveriesCubit, DataDiscoveriesState>( + builder: (BuildContext context, DataDiscoveriesState state) { + return FutureBuilder<DiscoveriesData>( + future: futureDiscoveries, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + BlocProvider.of<DataDiscoveriesCubit>(context).setValue(snapshot.data); + return !snapshot.hasData ? loading : done; + }, + ); + }, + ), + ); + } + + Widget updateStatisticsGlobal() { + late Future<StatisticsGlobalData> futureStatisticsGlobal = + ScrobblesApi.fetchGlobalStatistics(); + + return BlocProvider<DataStatisticsGlobalCubit>( + create: (BuildContext context) => DataStatisticsGlobalCubit(), + child: BlocBuilder<DataStatisticsGlobalCubit, DataStatisticsGlobalState>( + builder: (BuildContext context, DataStatisticsGlobalState dataState) { + return FutureBuilder<StatisticsGlobalData>( + future: futureStatisticsGlobal, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + BlocProvider.of<DataStatisticsGlobalCubit>(context).setValue(snapshot.data); + return !snapshot.hasData ? loading : done; + }, + ); + }, + ), + ); + } + + Widget updateStatisticsRecent(int daysCount) { + late Future<StatisticsRecentData> futureStatisticsRecent = + ScrobblesApi.fetchRecentStatistics(daysCount); + + return BlocProvider<DataStatisticsRecentCubit>( + create: (BuildContext context) => DataStatisticsRecentCubit(), + child: BlocBuilder<DataStatisticsRecentCubit, DataStatisticsRecentState>( + builder: (BuildContext context, DataStatisticsRecentState state) { + return FutureBuilder<StatisticsRecentData>( + future: futureStatisticsRecent, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + BlocProvider.of<DataStatisticsRecentCubit>(context).setValue(snapshot.data); + return !snapshot.hasData ? loading : done; + }, + ); + }, + ), + ); + } + + Widget updateTimeline(int daysCount) { + late Future<TimelineData> futureTimeline = ScrobblesApi.fetchTimeline(daysCount); + + return BlocProvider<DataTimelineCubit>( + create: (BuildContext context) => DataTimelineCubit(), + child: BlocBuilder<DataTimelineCubit, DataTimelineState>( + builder: (BuildContext context, DataTimelineState state) { + return FutureBuilder<TimelineData>( + future: futureTimeline, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + BlocProvider.of<DataTimelineCubit>(context).setValue(snapshot.data); + return !snapshot.hasData ? loading : done; + }, + ); + }, + ), + ); + } + + Widget updateTopArtists(int daysCount) { + late Future<TopArtistsData> futureTopArtists = ScrobblesApi.fetchTopArtists(daysCount); + + return BlocProvider<DataTopArtistsCubit>( + create: (BuildContext context) => DataTopArtistsCubit(), + child: BlocBuilder<DataTopArtistsCubit, DataTopArtistsState>( + builder: (BuildContext context, DataTopArtistsState state) { + return FutureBuilder<TopArtistsData>( + future: futureTopArtists, + builder: (context, snapshot) { + if (snapshot.hasError) { + return ShowErrorWidget(message: '${snapshot.error}'); + } + + BlocProvider.of<DataTopArtistsCubit>(context).setValue(snapshot.data); + return !snapshot.hasData ? loading : done; + }, + ); + }, + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 33d49a5ca6245f447ac76bf60cc8d7e6dd46e73d..0a0ceb2fae3ca3414ce67e4ea1e4cc2d79232241 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: Display scrobbles data and charts publish_to: 'none' -version: 0.0.28+28 +version: 0.0.29+29 environment: sdk: '^3.0.0'