Skip to content
Snippets Groups Projects
Commit ae63e6b1 authored by Benoît Harrault's avatar Benoît Harrault
Browse files

Merge branch '41-improve-refresh-data-and-charts' into 'master'

Resolve "Improve refresh data and charts"

Closes #41

See merge request !36
parents 28142ac4 4a2d8639
No related branches found
No related tags found
1 merge request!36Resolve "Improve refresh data and charts"
Pipeline #4660 passed
Showing
with 249 additions and 227 deletions
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
Improve update data and charts.
Amélioration de la mise à jour des données et des graphiques.
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,7 +47,20 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
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(),
......@@ -48,6 +70,7 @@ class MyApp extends StatelessWidget {
supportedLocales: context.supportedLocales,
locale: context.locale,
debugShowCheckedModeBanner: false,
),
);
}
}
......@@ -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.');
......
......@@ -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(
......
......@@ -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(
......
......@@ -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(
......
......@@ -25,20 +25,13 @@ 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),
);
return pageNavigation.elementAt(index);
},
pagination: SwiperPagination(
builder: SwiperCustomPagination(
......@@ -55,17 +48,9 @@ class _SkeletonScreenState extends State<SkeletonScreen> {
),
backgroundColor: Theme.of(context).colorScheme.background,
);
},
),
);
}
refresh() {
void rebuild(Element el) {
el.markNeedsBuild();
el.visitChildren(rebuild);
}
(context as Element).visitChildren(rebuild);
setState(() {});
}
}
......@@ -19,9 +19,7 @@ class CardCountsByDay extends StatelessWidget {
Widget build(BuildContext context) {
final int daysCount = Settings.countsByDayDaysCount;
return BlocProvider<DataCountsByDayCubit>(
create: (BuildContext context) => DataCountsByDayCubit(),
child: BlocBuilder<DataCountsByDayCubit, DataCountsByDayState>(
return BlocBuilder<DataCountsByDayCubit, DataCountsByDayState>(
builder: (BuildContext context, DataCountsByDayState state) {
return CardContent(
color: Theme.of(context).colorScheme.surface,
......@@ -37,7 +35,6 @@ class CardCountsByDay extends StatelessWidget {
),
);
},
),
);
}
......@@ -47,9 +44,7 @@ class CardCountsByDay extends StatelessWidget {
late Future<CountsByDayData> futureCountsByDay = ScrobblesApi.fetchCountsByDay(daysCount);
return BlocProvider<DataCountsByDayCubit>(
create: (BuildContext context) => DataCountsByDayCubit(),
child: BlocBuilder<DataCountsByDayCubit, DataCountsByDayState>(
return BlocBuilder<DataCountsByDayCubit, DataCountsByDayState>(
builder: (BuildContext context, DataCountsByDayState state) {
return FutureBuilder<CountsByDayData>(
future: futureCountsByDay,
......@@ -58,12 +53,12 @@ class CardCountsByDay extends StatelessWidget {
return ShowErrorWidget(message: '${snapshot.error}');
}
BlocProvider.of<DataCountsByDayCubit>(context).setValue(snapshot.data);
BlocProvider.of<DataCountsByDayCubit>(context).update(snapshot.data);
return !snapshot.hasData ? loading : done;
},
);
},
),
);
}
}
......@@ -19,9 +19,7 @@ class CardCountsByHour extends StatelessWidget {
Widget build(BuildContext context) {
final int daysCount = Settings.countsByHourDaysCount;
return BlocProvider<DataCountsByHourCubit>(
create: (BuildContext context) => DataCountsByHourCubit(),
child: BlocBuilder<DataCountsByHourCubit, DataCountsByHourState>(
return BlocBuilder<DataCountsByHourCubit, DataCountsByHourState>(
builder: (BuildContext context, DataCountsByHourState state) {
return CardContent(
color: Theme.of(context).colorScheme.surface,
......@@ -37,7 +35,6 @@ class CardCountsByHour extends StatelessWidget {
),
);
},
),
);
}
......@@ -48,9 +45,7 @@ class CardCountsByHour extends StatelessWidget {
late Future<CountsByHourData> futureCountsByHour =
ScrobblesApi.fetchCountsByHour(daysCount);
return BlocProvider<DataCountsByHourCubit>(
create: (BuildContext context) => DataCountsByHourCubit(),
child: BlocBuilder<DataCountsByHourCubit, DataCountsByHourState>(
return BlocBuilder<DataCountsByHourCubit, DataCountsByHourState>(
builder: (BuildContext context, DataCountsByHourState state) {
return FutureBuilder<CountsByHourData>(
future: futureCountsByHour,
......@@ -59,12 +54,12 @@ class CardCountsByHour extends StatelessWidget {
return ShowErrorWidget(message: '${snapshot.error}');
}
BlocProvider.of<DataCountsByHourCubit>(context).setValue(snapshot.data);
BlocProvider.of<DataCountsByHourCubit>(context).update(snapshot.data);
return !snapshot.hasData ? loading : done;
},
);
},
),
);
}
}
......@@ -20,9 +20,7 @@ class CardDiscoveries extends StatelessWidget {
Widget build(BuildContext context) {
final int daysCount = Settings.discoveriesDaysCount;
return BlocProvider<DataDiscoveriesCubit>(
create: (BuildContext context) => DataDiscoveriesCubit(),
child: BlocBuilder<DataDiscoveriesCubit, DataDiscoveriesState>(
return BlocBuilder<DataDiscoveriesCubit, DataDiscoveriesState>(
builder: (BuildContext context, DataDiscoveriesState state) {
final TextTheme textTheme = Theme.of(context).primaryTextTheme;
......@@ -44,8 +42,7 @@ class CardDiscoveries extends StatelessWidget {
).tr(),
const SizedBox(height: 8),
ChartDiscoveriesArtists(
chartData:
DiscoveriesData.fromJson(jsonDecode(state.discoveries.toString())),
chartData: DiscoveriesData.fromJson(jsonDecode(state.discoveries.toString())),
isLoading: false,
),
const SizedBox(height: 8),
......@@ -55,15 +52,13 @@ class CardDiscoveries extends StatelessWidget {
).tr(),
const SizedBox(height: 8),
ChartDiscoveriesTracks(
chartData:
DiscoveriesData.fromJson(jsonDecode(state.discoveries.toString())),
chartData: DiscoveriesData.fromJson(jsonDecode(state.discoveries.toString())),
isLoading: false,
),
],
),
);
},
),
);
}
......@@ -73,9 +68,7 @@ class CardDiscoveries extends StatelessWidget {
late Future<DiscoveriesData> futureDiscoveries = ScrobblesApi.fetchDiscoveries(daysCount);
return BlocProvider<DataDiscoveriesCubit>(
create: (BuildContext context) => DataDiscoveriesCubit(),
child: BlocBuilder<DataDiscoveriesCubit, DataDiscoveriesState>(
return BlocBuilder<DataDiscoveriesCubit, DataDiscoveriesState>(
builder: (BuildContext context, DataDiscoveriesState state) {
return FutureBuilder<DiscoveriesData>(
future: futureDiscoveries,
......@@ -84,12 +77,12 @@ class CardDiscoveries extends StatelessWidget {
return ShowErrorWidget(message: '${snapshot.error}');
}
BlocProvider.of<DataDiscoveriesCubit>(context).setValue(snapshot.data);
BlocProvider.of<DataDiscoveriesCubit>(context).update(snapshot.data);
return !snapshot.hasData ? loading : done;
},
);
},
),
);
}
}
......@@ -16,9 +16,7 @@ class CardStatisticsGlobal extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<DataStatisticsGlobalCubit>(
create: (BuildContext context) => DataStatisticsGlobalCubit(),
child: BlocBuilder<DataStatisticsGlobalCubit, DataStatisticsGlobalState>(
return BlocBuilder<DataStatisticsGlobalCubit, DataStatisticsGlobalState>(
builder: (BuildContext context, DataStatisticsGlobalState state) {
return CardContent(
color: Theme.of(context).colorScheme.primary,
......@@ -31,7 +29,6 @@ class CardStatisticsGlobal extends StatelessWidget {
),
);
},
),
);
}
......@@ -42,9 +39,7 @@ class CardStatisticsGlobal extends StatelessWidget {
late Future<StatisticsGlobalData> futureStatisticsGlobal =
ScrobblesApi.fetchGlobalStatistics();
return BlocProvider<DataStatisticsGlobalCubit>(
create: (BuildContext context) => DataStatisticsGlobalCubit(),
child: BlocBuilder<DataStatisticsGlobalCubit, DataStatisticsGlobalState>(
return BlocBuilder<DataStatisticsGlobalCubit, DataStatisticsGlobalState>(
builder: (BuildContext context, DataStatisticsGlobalState dataState) {
return FutureBuilder<StatisticsGlobalData>(
future: futureStatisticsGlobal,
......@@ -53,12 +48,12 @@ class CardStatisticsGlobal extends StatelessWidget {
return ShowErrorWidget(message: '${snapshot.error}');
}
BlocProvider.of<DataStatisticsGlobalCubit>(context).setValue(snapshot.data);
BlocProvider.of<DataStatisticsGlobalCubit>(context).update(snapshot.data);
return !snapshot.hasData ? loading : done;
},
);
},
),
);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment