From 4a2d86390f56ac36487fef4eb19c8d9c8b7820d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr>
Date: Wed, 29 Nov 2023 11:52:46 +0100
Subject: [PATCH] Improve refresh cards data and charts

---
 android/gradle.properties                     |   4 +-
 .../metadata/android/en-US/changelogs/34.txt  |   1 +
 .../metadata/android/fr-FR/changelogs/34.txt  |   1 +
 lib/cubit/data_counts_by_day_cubit.dart       |   6 +
 lib/cubit/data_counts_by_hour_cubit.dart      |   6 +
 lib/cubit/data_discoveries_cubit.dart         |   6 +
 lib/cubit/data_statistics_global_cubit.dart   |   6 +
 lib/cubit/data_statistics_recent_cubit.dart   |   6 +
 lib/cubit/data_timeline_cubit.dart            |   6 +
 lib/cubit/data_top_artists_cubit.dart         |   6 +
 lib/main.dart                                 |  41 +++++--
 lib/network/scrobbles.dart                    |   7 ++
 lib/ui/screens/discoveries.dart               |   7 +-
 lib/ui/screens/home.dart                      |   7 +-
 lib/ui/screens/statistics.dart                |   7 +-
 lib/ui/skeleton.dart                          |  57 ++++-----
 lib/ui/widgets/cards/counts_by_day.dart       |  65 +++++-----
 lib/ui/widgets/cards/counts_by_hour.dart      |  65 +++++-----
 lib/ui/widgets/cards/discoveries.dart         | 111 ++++++++----------
 lib/ui/widgets/cards/statistics_global.dart   |  61 +++++-----
 lib/ui/widgets/cards/statistics_recent.dart   |  68 +++++------
 lib/ui/widgets/cards/timeline.dart            |  81 ++++++-------
 lib/ui/widgets/cards/top_artists.dart         |  65 +++++-----
 lib/ui/widgets/charts/counts_by_day.dart      |   6 +
 lib/ui/widgets/charts/counts_by_hour.dart     |   6 +
 .../widgets/charts/discoveries_artists.dart   |   6 +
 lib/ui/widgets/charts/discoveries_tracks.dart |   6 +
 lib/ui/widgets/charts/timeline_counts.dart    |   6 +
 .../widgets/charts/timeline_eclecticism.dart  |   6 +
 pubspec.yaml                                  |   2 +-
 30 files changed, 385 insertions(+), 343 deletions(-)
 create mode 100644 fastlane/metadata/android/en-US/changelogs/34.txt
 create mode 100644 fastlane/metadata/android/fr-FR/changelogs/34.txt

diff --git a/android/gradle.properties b/android/gradle.properties
index 9dfcc42..4617f96 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.33
-app.versionCode=33
+app.versionName=0.0.34
+app.versionCode=34
diff --git a/fastlane/metadata/android/en-US/changelogs/34.txt b/fastlane/metadata/android/en-US/changelogs/34.txt
new file mode 100644
index 0000000..821b039
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/34.txt
@@ -0,0 +1 @@
+Improve update data and charts.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/34.txt b/fastlane/metadata/android/fr-FR/changelogs/34.txt
new file mode 100644
index 0000000..1c7bc32
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/34.txt
@@ -0,0 +1 @@
+Amélioration de la mise à jour des données et des graphiques.
diff --git a/lib/cubit/data_counts_by_day_cubit.dart b/lib/cubit/data_counts_by_day_cubit.dart
index 032aec8..cb5b780 100644
--- a/lib/cubit/data_counts_by_day_cubit.dart
+++ b/lib/cubit/data_counts_by_day_cubit.dart
@@ -17,6 +17,12 @@ class DataCountsByDayCubit extends HydratedCubit<DataCountsByDayState> {
     return state.countsByDay;
   }
 
+  void update(CountsByDayData? countsByDay) {
+    if (state.countsByDay.toString() != countsByDay.toString()) {
+      setValue(countsByDay);
+    }
+  }
+
   void setValue(CountsByDayData? countsByDay) {
     emit(DataCountsByDayState(
       countsByDay: countsByDay,
diff --git a/lib/cubit/data_counts_by_hour_cubit.dart b/lib/cubit/data_counts_by_hour_cubit.dart
index 2184993..fae6517 100644
--- a/lib/cubit/data_counts_by_hour_cubit.dart
+++ b/lib/cubit/data_counts_by_hour_cubit.dart
@@ -17,6 +17,12 @@ class DataCountsByHourCubit extends HydratedCubit<DataCountsByHourState> {
     return state.countsByHour;
   }
 
+  void update(CountsByHourData? countsByHour) {
+    if (state.countsByHour.toString() != countsByHour.toString()) {
+      setValue(countsByHour);
+    }
+  }
+
   void setValue(CountsByHourData? countsByHour) {
     emit(DataCountsByHourState(
       countsByHour: countsByHour,
diff --git a/lib/cubit/data_discoveries_cubit.dart b/lib/cubit/data_discoveries_cubit.dart
index 1b9ff97..f2037ab 100644
--- a/lib/cubit/data_discoveries_cubit.dart
+++ b/lib/cubit/data_discoveries_cubit.dart
@@ -17,6 +17,12 @@ class DataDiscoveriesCubit extends HydratedCubit<DataDiscoveriesState> {
     return state.discoveries;
   }
 
+  void update(DiscoveriesData? discoveries) {
+    if (state.discoveries.toString() != discoveries.toString()) {
+      setValue(discoveries);
+    }
+  }
+
   void setValue(DiscoveriesData? discoveries) {
     emit(DataDiscoveriesState(
       discoveries: discoveries,
diff --git a/lib/cubit/data_statistics_global_cubit.dart b/lib/cubit/data_statistics_global_cubit.dart
index 28e7e6b..5962e2c 100644
--- a/lib/cubit/data_statistics_global_cubit.dart
+++ b/lib/cubit/data_statistics_global_cubit.dart
@@ -17,6 +17,12 @@ class DataStatisticsGlobalCubit extends HydratedCubit<DataStatisticsGlobalState>
     return state.statisticsGlobal;
   }
 
+  void update(StatisticsGlobalData? statisticsGlobal) {
+    if (state.statisticsGlobal.toString() != statisticsGlobal.toString()) {
+      setValue(statisticsGlobal);
+    }
+  }
+
   void setValue(StatisticsGlobalData? statisticsGlobal) {
     emit(DataStatisticsGlobalState(
       statisticsGlobal: statisticsGlobal,
diff --git a/lib/cubit/data_statistics_recent_cubit.dart b/lib/cubit/data_statistics_recent_cubit.dart
index d2bc445..945e038 100644
--- a/lib/cubit/data_statistics_recent_cubit.dart
+++ b/lib/cubit/data_statistics_recent_cubit.dart
@@ -17,6 +17,12 @@ class DataStatisticsRecentCubit extends HydratedCubit<DataStatisticsRecentState>
     return state.statisticsRecent;
   }
 
+  void update(StatisticsRecentData? statisticsRecent) {
+    if (state.statisticsRecent.toString() != statisticsRecent.toString()) {
+      setValue(statisticsRecent);
+    }
+  }
+
   void setValue(StatisticsRecentData? statisticsRecent) {
     emit(DataStatisticsRecentState(
       statisticsRecent: statisticsRecent,
diff --git a/lib/cubit/data_timeline_cubit.dart b/lib/cubit/data_timeline_cubit.dart
index 597e594..1dadcfe 100644
--- a/lib/cubit/data_timeline_cubit.dart
+++ b/lib/cubit/data_timeline_cubit.dart
@@ -17,6 +17,12 @@ class DataTimelineCubit extends HydratedCubit<DataTimelineState> {
     return state.timeline;
   }
 
+  void update(TimelineData? timeline) {
+    if (state.timeline.toString() != timeline.toString()) {
+      setValue(timeline);
+    }
+  }
+
   void setValue(TimelineData? timeline) {
     emit(DataTimelineState(
       timeline: timeline,
diff --git a/lib/cubit/data_top_artists_cubit.dart b/lib/cubit/data_top_artists_cubit.dart
index 0011c5e..713f659 100644
--- a/lib/cubit/data_top_artists_cubit.dart
+++ b/lib/cubit/data_top_artists_cubit.dart
@@ -17,6 +17,12 @@ class DataTopArtistsCubit extends HydratedCubit<DataTopArtistsState> {
     return state.topArtists;
   }
 
+  void update(TopArtistsData? topArtists) {
+    if (state.topArtists.toString() != topArtists.toString()) {
+      setValue(topArtists);
+    }
+  }
+
   void setValue(TopArtistsData? topArtists) {
     emit(DataTopArtistsState(
       topArtists: topArtists,
diff --git a/lib/main.dart b/lib/main.dart
index da465fa..52ae6ef 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -2,11 +2,20 @@ import 'dart:io';
 
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:hive/hive.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
 import 'package:path_provider/path_provider.dart';
 
 import 'package:scrobbles/config/theme.dart';
+import 'package:scrobbles/cubit/bottom_nav_cubit.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/ui/skeleton.dart';
 
 void main() async {
@@ -38,16 +47,30 @@ class MyApp extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return MaterialApp(
-      title: 'Scrobbles',
-      theme: appTheme,
-      home: const SkeletonScreen(),
+    return MultiBlocProvider(
+      providers: [
+        BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
+        BlocProvider<DataCountsByDayCubit>(create: (context) => DataCountsByDayCubit()),
+        BlocProvider<DataCountsByHourCubit>(create: (context) => DataCountsByHourCubit()),
+        BlocProvider<DataDiscoveriesCubit>(create: (context) => DataDiscoveriesCubit()),
+        BlocProvider<DataStatisticsGlobalCubit>(
+            create: (context) => DataStatisticsGlobalCubit()),
+        BlocProvider<DataStatisticsRecentCubit>(
+            create: (context) => DataStatisticsRecentCubit()),
+        BlocProvider<DataTimelineCubit>(create: (context) => DataTimelineCubit()),
+        BlocProvider<DataTopArtistsCubit>(create: (context) => DataTopArtistsCubit()),
+      ],
+      child: MaterialApp(
+        title: 'Scrobbles',
+        theme: appTheme,
+        home: const SkeletonScreen(),
 
-      // Localization stuff
-      localizationsDelegates: context.localizationDelegates,
-      supportedLocales: context.supportedLocales,
-      locale: context.locale,
-      debugShowCheckedModeBanner: false,
+        // Localization stuff
+        localizationsDelegates: context.localizationDelegates,
+        supportedLocales: context.supportedLocales,
+        locale: context.locale,
+        debugShowCheckedModeBanner: false,
+      ),
     );
   }
 }
diff --git a/lib/network/scrobbles.dart b/lib/network/scrobbles.dart
index ebfca8a..e107c29 100644
--- a/lib/network/scrobbles.dart
+++ b/lib/network/scrobbles.dart
@@ -18,6 +18,7 @@ class ScrobblesApi {
     final response = await http.get(Uri.parse(url));
 
     if (response.statusCode == 200) {
+      print('ok - fetched ' + url);
       return StatisticsGlobalData.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
     } else {
       throw Exception('Failed to get data from API.');
@@ -30,6 +31,7 @@ class ScrobblesApi {
     final response = await http.get(Uri.parse(url));
 
     if (response.statusCode == 200) {
+      print('ok - fetched ' + url);
       return StatisticsRecentData.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
     } else {
       throw Exception('Failed to get data from API.');
@@ -42,6 +44,7 @@ class ScrobblesApi {
     final response = await http.get(Uri.parse(url));
 
     if (response.statusCode == 200) {
+      print('ok - fetched ' + url);
       return TimelineData.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
     } else {
       throw Exception('Failed to get data from API.');
@@ -54,6 +57,7 @@ class ScrobblesApi {
     final response = await http.get(Uri.parse(url));
 
     if (response.statusCode == 200) {
+      print('ok - fetched ' + url);
       return CountsByDayData.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
     } else {
       throw Exception('Failed to get data from API.');
@@ -66,6 +70,7 @@ class ScrobblesApi {
     final response = await http.get(Uri.parse(url));
 
     if (response.statusCode == 200) {
+      print('ok - fetched ' + url);
       return CountsByHourData.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
     } else {
       throw Exception('Failed to get data from API.');
@@ -78,6 +83,7 @@ class ScrobblesApi {
     final response = await http.get(Uri.parse(url));
 
     if (response.statusCode == 200) {
+      print('ok - fetched ' + url);
       return DiscoveriesData.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
     } else {
       throw Exception('Failed to get data from API.');
@@ -90,6 +96,7 @@ class ScrobblesApi {
     final response = await http.get(Uri.parse(url));
 
     if (response.statusCode == 200) {
+      print('ok - fetched ' + url);
       return TopArtistsData.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
     } else {
       throw Exception('Failed to get data from API.');
diff --git a/lib/ui/screens/discoveries.dart b/lib/ui/screens/discoveries.dart
index fd5f836..d93e921 100644
--- a/lib/ui/screens/discoveries.dart
+++ b/lib/ui/screens/discoveries.dart
@@ -2,14 +2,9 @@ import 'package:flutter/material.dart';
 
 import 'package:scrobbles/ui/widgets/cards/discoveries.dart';
 
-class ScreenDiscoveries extends StatefulWidget {
+class ScreenDiscoveries extends StatelessWidget {
   const ScreenDiscoveries({super.key});
 
-  @override
-  State<ScreenDiscoveries> createState() => _ScreenDiscoveriesState();
-}
-
-class _ScreenDiscoveriesState extends State<ScreenDiscoveries> {
   @override
   Widget build(BuildContext context) {
     return Material(
diff --git a/lib/ui/screens/home.dart b/lib/ui/screens/home.dart
index c2acc00..7bf2d94 100644
--- a/lib/ui/screens/home.dart
+++ b/lib/ui/screens/home.dart
@@ -5,14 +5,9 @@ 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 {
+class ScreenHome extends StatelessWidget {
   const ScreenHome({super.key});
 
-  @override
-  State<ScreenHome> createState() => _ScreenHomeState();
-}
-
-class _ScreenHomeState extends State<ScreenHome> {
   @override
   Widget build(BuildContext context) {
     return Material(
diff --git a/lib/ui/screens/statistics.dart b/lib/ui/screens/statistics.dart
index b719361..6f15f7e 100644
--- a/lib/ui/screens/statistics.dart
+++ b/lib/ui/screens/statistics.dart
@@ -3,14 +3,9 @@ import 'package:flutter/material.dart';
 import 'package:scrobbles/ui/widgets/cards/counts_by_day.dart';
 import 'package:scrobbles/ui/widgets/cards/counts_by_hour.dart';
 
-class ScreenStatistics extends StatefulWidget {
+class ScreenStatistics extends StatelessWidget {
   const ScreenStatistics({super.key});
 
-  @override
-  State<ScreenStatistics> createState() => _ScreenStatisticsState();
-}
-
-class _ScreenStatisticsState extends State<ScreenStatistics> {
   @override
   Widget build(BuildContext context) {
     return Material(
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index 00d1205..fe99383 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -25,47 +25,32 @@ class _SkeletonScreenState extends State<SkeletonScreen> {
       const ScreenStatistics(),
     ];
 
-    return BlocProvider<BottomNavCubit>(
-      create: (BuildContext context) => BottomNavCubit(),
-      child: BlocBuilder<BottomNavCubit, int>(
-        builder: (BuildContext context, int state) {
-          return Scaffold(
-            appBar: StandardAppBar(notifyParent: refresh),
-            extendBodyBehindAppBar: false,
-            body: Swiper(
-              itemCount: BlocProvider.of<BottomNavCubit>(context).pagesCount,
-              itemBuilder: (BuildContext context, int index) {
-                return AnimatedSwitcher(
-                  duration: const Duration(milliseconds: 300),
-                  child: pageNavigation.elementAt(index),
-                );
-              },
-              pagination: SwiperPagination(
-                builder: SwiperCustomPagination(
-                  builder: (BuildContext context, SwiperPluginConfig config) {
-                    return BottomNavBar(swipeController: config.controller);
-                  },
-                ),
-              ),
-              onIndexChanged: (newPageIndex) {
-                BlocProvider.of<BottomNavCubit>(context).updateIndex(newPageIndex);
-              },
-              outer: true,
-              loop: false,
-            ),
-            backgroundColor: Theme.of(context).colorScheme.background,
-          );
+    return Scaffold(
+      appBar: StandardAppBar(notifyParent: refresh),
+      extendBodyBehindAppBar: false,
+      body: Swiper(
+        itemCount: BlocProvider.of<BottomNavCubit>(context).pagesCount,
+        itemBuilder: (BuildContext context, int index) {
+          return pageNavigation.elementAt(index);
         },
+        pagination: SwiperPagination(
+          builder: SwiperCustomPagination(
+            builder: (BuildContext context, SwiperPluginConfig config) {
+              return BottomNavBar(swipeController: config.controller);
+            },
+          ),
+        ),
+        onIndexChanged: (newPageIndex) {
+          BlocProvider.of<BottomNavCubit>(context).updateIndex(newPageIndex);
+        },
+        outer: true,
+        loop: false,
       ),
+      backgroundColor: Theme.of(context).colorScheme.background,
     );
   }
 
   refresh() {
-    void rebuild(Element el) {
-      el.markNeedsBuild();
-      el.visitChildren(rebuild);
-    }
-
-    (context as Element).visitChildren(rebuild);
+    setState(() {});
   }
 }
diff --git a/lib/ui/widgets/cards/counts_by_day.dart b/lib/ui/widgets/cards/counts_by_day.dart
index 2251ffd..43c7249 100644
--- a/lib/ui/widgets/cards/counts_by_day.dart
+++ b/lib/ui/widgets/cards/counts_by_day.dart
@@ -19,25 +19,22 @@ class CardCountsByDay extends StatelessWidget {
   Widget build(BuildContext context) {
     final int daysCount = Settings.countsByDayDaysCount;
 
-    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(),
-              },
-            ),
-            loader: updateCountsByDay(Settings.countsByDayDaysCount),
-            content: ChartCountsByDay(
-              chartData: CountsByDayData.fromJson(jsonDecode(state.countsByDay.toString())),
-              isLoading: false,
-            ),
-          );
-        },
-      ),
+    return 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(),
+            },
+          ),
+          loader: updateCountsByDay(Settings.countsByDayDaysCount),
+          content: ChartCountsByDay(
+            chartData: CountsByDayData.fromJson(jsonDecode(state.countsByDay.toString())),
+            isLoading: false,
+          ),
+        );
+      },
     );
   }
 
@@ -47,23 +44,21 @@ class CardCountsByDay extends StatelessWidget {
 
     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}');
-              }
+    return 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;
-            },
-          );
-        },
-      ),
+            BlocProvider.of<DataCountsByDayCubit>(context).update(snapshot.data);
+
+            return !snapshot.hasData ? loading : done;
+          },
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/cards/counts_by_hour.dart b/lib/ui/widgets/cards/counts_by_hour.dart
index 68b28b2..319748b 100644
--- a/lib/ui/widgets/cards/counts_by_hour.dart
+++ b/lib/ui/widgets/cards/counts_by_hour.dart
@@ -19,25 +19,22 @@ class CardCountsByHour extends StatelessWidget {
   Widget build(BuildContext context) {
     final int daysCount = Settings.countsByHourDaysCount;
 
-    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(),
-              },
-            ),
-            loader: updateCountsByHour(Settings.countsByHourDaysCount),
-            content: ChartCountsByHour(
-              chartData: CountsByHourData.fromJson(jsonDecode(state.countsByHour.toString())),
-              isLoading: false,
-            ),
-          );
-        },
-      ),
+    return 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(),
+            },
+          ),
+          loader: updateCountsByHour(Settings.countsByHourDaysCount),
+          content: ChartCountsByHour(
+            chartData: CountsByHourData.fromJson(jsonDecode(state.countsByHour.toString())),
+            isLoading: false,
+          ),
+        );
+      },
     );
   }
 
@@ -48,23 +45,21 @@ class CardCountsByHour extends StatelessWidget {
     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}');
-              }
+    return 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;
-            },
-          );
-        },
-      ),
+            BlocProvider.of<DataCountsByHourCubit>(context).update(snapshot.data);
+
+            return !snapshot.hasData ? loading : done;
+          },
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/cards/discoveries.dart b/lib/ui/widgets/cards/discoveries.dart
index 891c03a..c285627 100644
--- a/lib/ui/widgets/cards/discoveries.dart
+++ b/lib/ui/widgets/cards/discoveries.dart
@@ -20,50 +20,45 @@ class CardDiscoveries extends StatelessWidget {
   Widget build(BuildContext context) {
     final int daysCount = Settings.discoveriesDaysCount;
 
-    return BlocProvider<DataDiscoveriesCubit>(
-      create: (BuildContext context) => DataDiscoveriesCubit(),
-      child: BlocBuilder<DataDiscoveriesCubit, DataDiscoveriesState>(
-        builder: (BuildContext context, DataDiscoveriesState state) {
-          final TextTheme textTheme = Theme.of(context).primaryTextTheme;
+    return BlocBuilder<DataDiscoveriesCubit, DataDiscoveriesState>(
+      builder: (BuildContext context, DataDiscoveriesState state) {
+        final TextTheme textTheme = Theme.of(context).primaryTextTheme;
 
-          return CardContent(
-            color: Theme.of(context).colorScheme.surface,
-            title: 'discoveries_title'.tr(
-              namedArgs: {
-                'daysCount': daysCount.toString(),
-              },
-            ),
-            loader: updateDiscoveries(Settings.discoveriesDaysCount),
-            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,
-                ),
-              ],
-            ),
-          );
-        },
-      ),
+        return CardContent(
+          color: Theme.of(context).colorScheme.surface,
+          title: 'discoveries_title'.tr(
+            namedArgs: {
+              'daysCount': daysCount.toString(),
+            },
+          ),
+          loader: updateDiscoveries(Settings.discoveriesDaysCount),
+          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,
+              ),
+            ],
+          ),
+        );
+      },
     );
   }
 
@@ -73,23 +68,21 @@ class CardDiscoveries extends StatelessWidget {
 
     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}');
-              }
+    return 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;
-            },
-          );
-        },
-      ),
+            BlocProvider.of<DataDiscoveriesCubit>(context).update(snapshot.data);
+
+            return !snapshot.hasData ? loading : done;
+          },
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/cards/statistics_global.dart b/lib/ui/widgets/cards/statistics_global.dart
index 30d082f..bca1aa9 100644
--- a/lib/ui/widgets/cards/statistics_global.dart
+++ b/lib/ui/widgets/cards/statistics_global.dart
@@ -16,22 +16,19 @@ class CardStatisticsGlobal extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    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(),
-            loader: updateStatisticsGlobal(),
-            content: ContentStatisticsGlobal(
-              statistics:
-                  StatisticsGlobalData.fromJson(jsonDecode(state.statisticsGlobal.toString())),
-              isLoading: false,
-            ),
-          );
-        },
-      ),
+    return BlocBuilder<DataStatisticsGlobalCubit, DataStatisticsGlobalState>(
+      builder: (BuildContext context, DataStatisticsGlobalState state) {
+        return CardContent(
+          color: Theme.of(context).colorScheme.primary,
+          title: 'global_statistics'.tr(),
+          loader: updateStatisticsGlobal(),
+          content: ContentStatisticsGlobal(
+            statistics:
+                StatisticsGlobalData.fromJson(jsonDecode(state.statisticsGlobal.toString())),
+            isLoading: false,
+          ),
+        );
+      },
     );
   }
 
@@ -42,23 +39,21 @@ class CardStatisticsGlobal extends StatelessWidget {
     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;
-            },
-          );
-        },
-      ),
+    return 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).update(snapshot.data);
+
+            return !snapshot.hasData ? loading : done;
+          },
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/cards/statistics_recent.dart b/lib/ui/widgets/cards/statistics_recent.dart
index 951f19a..2c227fc 100644
--- a/lib/ui/widgets/cards/statistics_recent.dart
+++ b/lib/ui/widgets/cards/statistics_recent.dart
@@ -19,27 +19,23 @@ class CardStatisticsRecent extends StatelessWidget {
   Widget build(BuildContext context) {
     final int daysCount = Settings.statisticsRecentDaysCount;
 
-    // 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(),
-              },
-            ),
-            loader: updateStatisticsRecent(Settings.statisticsRecentDaysCount),
-            content: ContentStatisticsRecent(
-              statistics: StatisticsRecentData.fromJson(
-                  jsonDecode(dataState.statisticsRecent.toString())),
-              isLoading: false,
-            ),
-          );
-        },
-      ),
+    return BlocBuilder<DataStatisticsRecentCubit, DataStatisticsRecentState>(
+      builder: (BuildContext context, DataStatisticsRecentState dataState) {
+        return CardContent(
+          color: Theme.of(context).colorScheme.primary,
+          title: 'recent_statistics'.tr(
+            namedArgs: {
+              'daysCount': daysCount.toString(),
+            },
+          ),
+          loader: updateStatisticsRecent(Settings.statisticsRecentDaysCount),
+          content: ContentStatisticsRecent(
+            statistics: StatisticsRecentData.fromJson(
+                jsonDecode(dataState.statisticsRecent.toString())),
+            isLoading: false,
+          ),
+        );
+      },
     );
   }
 
@@ -50,23 +46,21 @@ class CardStatisticsRecent extends StatelessWidget {
     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}');
-              }
+    return 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;
-            },
-          );
-        },
-      ),
+            BlocProvider.of<DataStatisticsRecentCubit>(context).update(snapshot.data);
+
+            return !snapshot.hasData ? loading : done;
+          },
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/cards/timeline.dart b/lib/ui/widgets/cards/timeline.dart
index 9e61b20..1ac2cf4 100644
--- a/lib/ui/widgets/cards/timeline.dart
+++ b/lib/ui/widgets/cards/timeline.dart
@@ -20,33 +20,30 @@ class CardTimeline extends StatelessWidget {
   Widget build(BuildContext context) {
     final int daysCount = Settings.timelineDaysCount;
 
-    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(),
-              },
-            ),
-            loader: updateTimeline(Settings.timelineDaysCount),
-            content: Stack(
-              children: [
-                ChartTimelineCounts(
-                  chartData: TimelineData.fromJson(jsonDecode(state.timeline.toString())),
-                  isLoading: false,
-                ),
-                ChartTimelineEclecticism(
-                  chartData: TimelineData.fromJson(jsonDecode(state.timeline.toString())),
-                  isLoading: false,
-                ),
-              ],
-            ),
-          );
-        },
-      ),
+    return BlocBuilder<DataTimelineCubit, DataTimelineState>(
+      builder: (BuildContext context, DataTimelineState state) {
+        return CardContent(
+          color: Theme.of(context).colorScheme.surface,
+          title: 'timeline_title'.tr(
+            namedArgs: {
+              'daysCount': daysCount.toString(),
+            },
+          ),
+          loader: updateTimeline(Settings.timelineDaysCount),
+          content: Stack(
+            children: [
+              ChartTimelineCounts(
+                chartData: TimelineData.fromJson(jsonDecode(state.timeline.toString())),
+                isLoading: false,
+              ),
+              ChartTimelineEclecticism(
+                chartData: TimelineData.fromJson(jsonDecode(state.timeline.toString())),
+                isLoading: false,
+              ),
+            ],
+          ),
+        );
+      },
     );
   }
 
@@ -56,23 +53,21 @@ class CardTimeline extends StatelessWidget {
 
     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}');
-              }
+    return BlocBuilder<DataTimelineCubit, DataTimelineState>(
+      builder: (BuildContext context, DataTimelineState dataTimelineState) {
+        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;
-            },
-          );
-        },
-      ),
+              BlocProvider.of<DataTimelineCubit>(context).update(snapshot.data);
+
+            return !snapshot.hasData ? loading : done;
+          },
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/cards/top_artists.dart b/lib/ui/widgets/cards/top_artists.dart
index 9488cbd..176c673 100644
--- a/lib/ui/widgets/cards/top_artists.dart
+++ b/lib/ui/widgets/cards/top_artists.dart
@@ -19,25 +19,22 @@ class CardTopArtists extends StatelessWidget {
   Widget build(BuildContext context) {
     final int daysCount = Settings.topArtistsDaysCount;
 
-    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(),
-              },
-            ),
-            loader: updateTopArtists(Settings.topArtistsDaysCount),
-            content: ChartTopArtists(
-              chartData: TopArtistsData.fromJson(jsonDecode(state.topArtists.toString())),
-              isLoading: false,
-            ),
-          );
-        },
-      ),
+    return 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(),
+            },
+          ),
+          loader: updateTopArtists(Settings.topArtistsDaysCount),
+          content: ChartTopArtists(
+            chartData: TopArtistsData.fromJson(jsonDecode(state.topArtists.toString())),
+            isLoading: false,
+          ),
+        );
+      },
     );
   }
 
@@ -47,23 +44,21 @@ class CardTopArtists extends StatelessWidget {
 
     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}');
-              }
+    return 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;
-            },
-          );
-        },
-      ),
+            BlocProvider.of<DataTopArtistsCubit>(context).update(snapshot.data);
+
+            return !snapshot.hasData ? loading : done;
+          },
+        );
+      },
     );
   }
 }
diff --git a/lib/ui/widgets/charts/counts_by_day.dart b/lib/ui/widgets/charts/counts_by_day.dart
index 19492b4..9fb3721 100644
--- a/lib/ui/widgets/charts/counts_by_day.dart
+++ b/lib/ui/widgets/charts/counts_by_day.dart
@@ -17,6 +17,12 @@ class ChartCountsByDay extends CustomBarChart {
 
   @override
   Widget build(BuildContext context) {
+    if (this.chartData.data.keys.length == 0) {
+      return SizedBox(
+        height: this.chartHeight,
+      );
+    }
+
     return Container(
       height: this.chartHeight,
       child: this.isLoading
diff --git a/lib/ui/widgets/charts/counts_by_hour.dart b/lib/ui/widgets/charts/counts_by_hour.dart
index 79c8167..de66a75 100644
--- a/lib/ui/widgets/charts/counts_by_hour.dart
+++ b/lib/ui/widgets/charts/counts_by_hour.dart
@@ -17,6 +17,12 @@ class ChartCountsByHour extends CustomBarChart {
 
   @override
   Widget build(BuildContext context) {
+    if (this.chartData.data.keys.length == 0) {
+      return SizedBox(
+        height: this.chartHeight,
+      );
+    }
+
     return Container(
       height: this.chartHeight,
       child: this.isLoading
diff --git a/lib/ui/widgets/charts/discoveries_artists.dart b/lib/ui/widgets/charts/discoveries_artists.dart
index d441c27..96a5a78 100644
--- a/lib/ui/widgets/charts/discoveries_artists.dart
+++ b/lib/ui/widgets/charts/discoveries_artists.dart
@@ -14,6 +14,12 @@ class ChartDiscoveriesArtists extends CustomBarChart {
 
   @override
   Widget build(BuildContext context) {
+    if (this.chartData.data.keys.length == 0) {
+      return SizedBox(
+        height: this.chartHeight,
+      );
+    }
+
     return Container(
       height: this.chartHeight,
       child: this.isLoading
diff --git a/lib/ui/widgets/charts/discoveries_tracks.dart b/lib/ui/widgets/charts/discoveries_tracks.dart
index 343c02d..44d9d6f 100644
--- a/lib/ui/widgets/charts/discoveries_tracks.dart
+++ b/lib/ui/widgets/charts/discoveries_tracks.dart
@@ -14,6 +14,12 @@ class ChartDiscoveriesTracks extends CustomBarChart {
 
   @override
   Widget build(BuildContext context) {
+    if (this.chartData.data.keys.length == 0) {
+      return SizedBox(
+        height: this.chartHeight,
+      );
+    }
+
     return Container(
       height: this.chartHeight,
       child: this.isLoading
diff --git a/lib/ui/widgets/charts/timeline_counts.dart b/lib/ui/widgets/charts/timeline_counts.dart
index 8e5fec0..5b7399f 100644
--- a/lib/ui/widgets/charts/timeline_counts.dart
+++ b/lib/ui/widgets/charts/timeline_counts.dart
@@ -15,6 +15,12 @@ class ChartTimelineCounts extends CustomBarChart {
 
   @override
   Widget build(BuildContext context) {
+    if (this.chartData.data.keys.length == 0) {
+      return SizedBox(
+        height: this.chartHeight,
+      );
+    }
+
     return Container(
       height: this.chartHeight,
       child: this.isLoading
diff --git a/lib/ui/widgets/charts/timeline_eclecticism.dart b/lib/ui/widgets/charts/timeline_eclecticism.dart
index f5ddd96..dea2a0d 100644
--- a/lib/ui/widgets/charts/timeline_eclecticism.dart
+++ b/lib/ui/widgets/charts/timeline_eclecticism.dart
@@ -16,6 +16,12 @@ class ChartTimelineEclecticism extends CustomLineChart {
   Widget build(BuildContext context) {
     final horizontalScale = getHorizontalScale();
 
+    if (this.chartData.data.keys.length == 0) {
+      return SizedBox(
+        height: this.chartHeight,
+      );
+    }
+
     return Container(
       height: this.chartHeight,
       child: this.isLoading
diff --git a/pubspec.yaml b/pubspec.yaml
index edd2e48..8c8dc91 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: Display scrobbles data and charts
 
 publish_to: 'none'
 
-version: 0.0.33+33
+version: 0.0.34+34
 
 environment:
   sdk: '^3.0.0'
-- 
GitLab