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

Improve loading charts data

parent e70732d6
No related branches found
No related tags found
1 merge request!27Resolve "Display previous data while fetching update"
Pipeline #4644 passed
This commit is part of merge request !27. Comments created here will be created in the context of that merge request.
Showing with 224 additions and 217 deletions
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
app.versionName=0.0.32
app.versionCode=32
app.versionName=0.0.33
app.versionCode=33
Improve loading charts data.
Amélioration du chargement des données des graphiques.
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 {
......@@ -14,7 +13,6 @@ class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
return AppBar(
title: const AppHeader(text: 'app_name'),
actions: [
UpdateData(),
IconButton(
onPressed: () {
this.notifyParent();
......
......@@ -5,11 +5,13 @@ class CardContent extends StatelessWidget {
super.key,
required this.title,
required this.color,
required this.loader,
required this.content,
});
final String title;
final Color color;
final Widget loader;
final Widget content;
@override
......@@ -29,9 +31,17 @@ class CardContent extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
this.title,
style: Theme.of(context).primaryTextTheme.titleLarge!.apply(fontWeightDelta: 2),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
this.title,
style:
Theme.of(context).primaryTextTheme.titleLarge!.apply(fontWeightDelta: 2),
),
this.loader,
],
),
const SizedBox(height: 8),
this.content,
......
......@@ -7,8 +7,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:scrobbles/config/settings.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});
......@@ -28,6 +30,7 @@ class CardCountsByDay extends StatelessWidget {
'daysCount': daysCount.toString(),
},
),
loader: updateCountsByDay(Settings.countsByDayDaysCount),
content: ChartCountsByDay(
chartData: CountsByDayData.fromJson(jsonDecode(state.countsByDay.toString())),
isLoading: false,
......@@ -37,4 +40,30 @@ class CardCountsByDay extends StatelessWidget {
),
);
}
Widget updateCountsByDay(int daysCount) {
final Widget loading = const Text('⏳');
final Widget done = const Text('');
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;
},
);
},
),
);
}
}
......@@ -7,8 +7,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:scrobbles/config/settings.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});
......@@ -28,6 +30,7 @@ class CardCountsByHour extends StatelessWidget {
'daysCount': daysCount.toString(),
},
),
loader: updateCountsByHour(Settings.countsByHourDaysCount),
content: ChartCountsByHour(
chartData: CountsByHourData.fromJson(jsonDecode(state.countsByHour.toString())),
isLoading: false,
......@@ -37,4 +40,31 @@ class CardCountsByHour extends StatelessWidget {
),
);
}
Widget updateCountsByHour(int daysCount) {
final Widget loading = const Text('⏳');
final Widget done = const Text('');
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;
},
);
},
),
);
}
}
......@@ -7,9 +7,11 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:scrobbles/config/settings.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});
......@@ -31,6 +33,7 @@ class CardDiscoveries extends StatelessWidget {
'daysCount': daysCount.toString(),
},
),
loader: updateDiscoveries(Settings.discoveriesDaysCount),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
......@@ -63,4 +66,30 @@ class CardDiscoveries extends StatelessWidget {
),
);
}
Widget updateDiscoveries(int daysCount) {
final Widget loading = const Text('⏳');
final Widget done = const Text('');
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;
},
);
},
),
);
}
}
......@@ -6,8 +6,10 @@ 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});
......@@ -21,6 +23,7 @@ class CardStatisticsGlobal extends StatelessWidget {
return CardContent(
color: Theme.of(context).colorScheme.primary,
title: 'global_statistics'.tr(),
loader: updateStatisticsGlobal(),
content: ContentStatisticsGlobal(
statistics:
StatisticsGlobalData.fromJson(jsonDecode(state.statisticsGlobal.toString())),
......@@ -31,4 +34,31 @@ class CardStatisticsGlobal extends StatelessWidget {
),
);
}
Widget updateStatisticsGlobal() {
final Widget loading = const Text('⏳');
final Widget done = const Text('');
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;
},
);
},
),
);
}
}
......@@ -7,8 +7,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:scrobbles/config/settings.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});
......@@ -29,6 +31,7 @@ class CardStatisticsRecent extends StatelessWidget {
'daysCount': daysCount.toString(),
},
),
loader: updateStatisticsRecent(Settings.statisticsRecentDaysCount),
content: ContentStatisticsRecent(
statistics: StatisticsRecentData.fromJson(
jsonDecode(dataState.statisticsRecent.toString())),
......@@ -39,4 +42,31 @@ class CardStatisticsRecent extends StatelessWidget {
),
);
}
Widget updateStatisticsRecent(int daysCount) {
final Widget loading = const Text('⏳');
final Widget done = const Text('');
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;
},
);
},
),
);
}
}
......@@ -7,9 +7,11 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:scrobbles/config/settings.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});
......@@ -29,6 +31,7 @@ class CardTimeline extends StatelessWidget {
'daysCount': daysCount.toString(),
},
),
loader: updateTimeline(Settings.timelineDaysCount),
content: Stack(
children: [
ChartTimelineCounts(
......@@ -46,4 +49,30 @@ class CardTimeline extends StatelessWidget {
),
);
}
Widget updateTimeline(int daysCount) {
final Widget loading = const Text('⏳');
final Widget done = const Text('');
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;
},
);
},
),
);
}
}
......@@ -7,8 +7,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:scrobbles/config/settings.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});
......@@ -28,6 +30,7 @@ class CardTopArtists extends StatelessWidget {
'daysCount': daysCount.toString(),
},
),
loader: updateTopArtists(Settings.topArtistsDaysCount),
content: ChartTopArtists(
chartData: TopArtistsData.fromJson(jsonDecode(state.topArtists.toString())),
isLoading: false,
......@@ -37,4 +40,30 @@ class CardTopArtists extends StatelessWidget {
),
);
}
Widget updateTopArtists(int daysCount) {
final Widget loading = const Text('⏳');
final Widget done = const Text('');
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;
},
);
},
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:scrobbles/config/settings.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 Widget loading = const Text('⏳');
final Widget done = const Text('');
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(4),
child: Stack(
children: [
updateCountsByDay(Settings.countsByDayDaysCount),
updateCountsByHour(Settings.countsByHourDaysCount),
updateDiscoveries(Settings.discoveriesDaysCount),
updateStatisticsGlobal(),
updateStatisticsRecent(Settings.statisticsRecentDaysCount),
updateTimeline(Settings.timelineDaysCount),
updateTopArtists(Settings.topArtistsDaysCount),
],
),
);
}
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;
},
);
},
),
);
}
}
......@@ -3,7 +3,7 @@ description: Display scrobbles data and charts
publish_to: 'none'
version: 0.0.32+32
version: 0.0.33+33
environment:
sdk: '^3.0.0'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment