Pre-load necessary data

This commit is contained in:
Roland Geider
2021-01-27 13:27:50 +01:00
parent fb8083912f
commit 62c1be5b16
8 changed files with 157 additions and 158 deletions

View File

@@ -29,6 +29,10 @@ import 'package:wger/models/http_exception.dart';
class Auth with ChangeNotifier {
String token;
String serverUrl;
/// flag to indicate that the application has successfully loaded all initial data
bool dataInit = false;
// DateTime _expiryDate;
// String _userId;
// Timer _authTimer;

View File

@@ -276,6 +276,13 @@ class Nutrition extends WgerBaseProvider with ChangeNotifier {
notifyListeners();
}
/// Log meal to nutrition diary
Future<void> fetchAndSetAllLogs() async {
for (var plan in _plans) {
fetchAndSetLogs(plan);
}
}
/// Log meal to nutrition diary
Future<void> fetchAndSetLogs(NutritionalPlan plan) async {
// TODO: update fetch to that it can use the pagination

View File

@@ -90,7 +90,13 @@ class WorkoutPlans extends WgerBaseProvider with ChangeNotifier {
notifyListeners();
}
Future<WorkoutPlan> fetchAndSetFullWorkout(int workoutId) async {
Future<void> setAllFullWorkouts() async {
for (var plan in _workoutPlans) {
setFullWorkout(plan.id);
}
}
Future<WorkoutPlan> setFullWorkout(int workoutId) async {
final data = await fetch(makeUrl(
_workoutPlansUrlPath,
id: workoutId,

View File

@@ -20,6 +20,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:wger/locale/locales.dart';
import 'package:wger/providers/auth.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/nutrition.dart';
@@ -43,13 +44,27 @@ class _DashboardScreenState extends State<DashboardScreen> {
);
}
/// Load inital data from the server
Future _loadCachedEntries(BuildContext context) async {
await Provider.of<Exercises>(context, listen: false).fetchAndSetExercises();
await Provider.of<Nutrition>(context, listen: false).fetchIngredientsFromCache();
await Provider.of<WorkoutPlans>(context, listen: false).fetchAndSetWorkouts();
await Provider.of<Nutrition>(context, listen: false).fetchAndSetPlans();
await Provider.of<BodyWeight>(context, listen: false).fetchAndSetEntries();
/// Load initial data from the server
Future<void> _loadEntries(BuildContext context) async {
if (!Provider.of<Auth>(context, listen: false).dataInit) {
// Exercises
await Provider.of<Exercises>(context, listen: false).fetchAndSetExercises();
// Nutrition
Nutrition nutritionProvider = Provider.of<Nutrition>(context, listen: false);
await nutritionProvider.fetchIngredientsFromCache();
await nutritionProvider.fetchAndSetPlans();
await nutritionProvider.fetchAndSetAllLogs();
// Workouts
WorkoutPlans workoutProvider = Provider.of<WorkoutPlans>(context, listen: false);
await workoutProvider.fetchAndSetWorkouts();
await workoutProvider.setAllFullWorkouts();
// Weight
await Provider.of<BodyWeight>(context, listen: false).fetchAndSetEntries();
}
Provider.of<Auth>(context, listen: false).dataInit = true;
}
@override
@@ -58,7 +73,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
appBar: getAppBar(),
drawer: AppDrawer(),
body: FutureBuilder(
future: _loadCachedEntries(context),
future: _loadEntries(context),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState == ConnectionState.waiting
? Column(

View File

@@ -131,8 +131,7 @@ class _WorkoutPlanScreenState extends State<WorkoutPlanScreen> {
return Scaffold(
appBar: getAppBar(workoutPlan),
body: FutureBuilder<WorkoutPlan>(
future: Provider.of<WorkoutPlans>(context, listen: false)
.fetchAndSetFullWorkout(workoutPlan.id),
future: Provider.of<WorkoutPlans>(context, listen: false).setFullWorkout(workoutPlan.id),
builder: (context, AsyncSnapshot<WorkoutPlan> snapshot) =>
snapshot.connectionState == ConnectionState.waiting
? Center(child: CircularProgressIndicator())

View File

@@ -72,7 +72,7 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
_animationController.forward();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
// Fetch weight entries
// Process weight entries
BodyWeight weightProvider = Provider.of<BodyWeight>(context, listen: false);
for (var entry in weightProvider.items) {
final date = DateTime(entry.date.year, entry.date.month, entry.date.day);
@@ -83,7 +83,7 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
_events[date].add('Body weight: ${entry.weight} kg');
}
// Fetch workout sessions
// Process workout sessions
WorkoutPlans plans = Provider.of<WorkoutPlans>(context, listen: false);
plans.fetchSessionData().then((entries) {
for (var entry in entries['results']) {
@@ -102,20 +102,17 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
}
});
// Fetch nutritional plans
// Process nutritional plans
Nutrition nutritionProvider = Provider.of<Nutrition>(context, listen: false);
for (var plan in nutritionProvider.items) {
nutritionProvider.fetchAndSetLogs(plan).then((value) {
//print(plan.logEntriesValues);
for (var entry in plan.logEntriesValues.entries) {
final date = DateTime(entry.key.year, entry.key.month, entry.key.day);
if (!_events.containsKey(date)) {
_events[date] = [];
}
_events[date].add('Nutrition diary: ${entry.value.energy.toStringAsFixed(0)} kcal');
for (var entry in plan.logEntriesValues.entries) {
final date = DateTime(entry.key.year, entry.key.month, entry.key.day);
if (!_events.containsKey(date)) {
_events[date] = [];
}
});
_events[date].add('Nutrition diary: ${entry.value.energy.toStringAsFixed(0)} kcal');
}
}
});
}
@@ -340,7 +337,7 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(width: 0.5),
borderRadius: BorderRadius.circular(12.0),
borderRadius: BorderRadius.circular(5),
),
margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
child: ListTile(

View File

@@ -47,12 +47,10 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
Nutrition nutrition;
NutritionalPlan plan;
Future<void> _refreshPlanEntries(BuildContext context) async {
plan = Provider.of<Nutrition>(context, listen: false).currentPlan;
}
@override
Widget build(BuildContext context) {
plan = Provider.of<Nutrition>(context, listen: false).currentPlan;
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
@@ -61,36 +59,31 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
AppLocalizations.of(context).nutritionalPlan,
style: Theme.of(context).textTheme.headline4,
),
FutureBuilder(
future: _refreshPlanEntries(context),
builder: (context, snapshot) => snapshot.connectionState == ConnectionState.waiting
? Container(height: 180, child: Center(child: CircularProgressIndicator()))
: plan != null
? Column(
children: [
Text(
DateFormat.yMd().format(plan.creationDate),
style: Theme.of(context).textTheme.headline6,
),
TextButton(
child: Text(
plan.description,
style: TextStyle(fontSize: 20),
),
onPressed: () {
return Navigator.of(context)
.pushNamed(NutritionalPlanScreen.routeName, arguments: plan);
},
),
Container(
padding: EdgeInsets.all(15),
height: 180,
child: NutritionalPlanPieChartWidget(plan.nutritionalValues),
)
],
)
: Text('You have no nutritional plans'),
),
plan != null
? Column(
children: [
Text(
DateFormat.yMd().format(plan.creationDate),
style: Theme.of(context).textTheme.headline6,
),
TextButton(
child: Text(
plan.description,
style: TextStyle(fontSize: 20),
),
onPressed: () {
return Navigator.of(context)
.pushNamed(NutritionalPlanScreen.routeName, arguments: plan);
},
),
Container(
padding: EdgeInsets.all(15),
height: 180,
child: NutritionalPlanPieChartWidget(plan.nutritionalValues),
)
],
)
: Text('You have no nutritional plans'),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
@@ -127,12 +120,10 @@ class DashboardWeightWidget extends StatefulWidget {
class _DashboardWeightWidgetState extends State<DashboardWeightWidget> {
BodyWeight weightEntriesData;
Future<void> _refreshWeightEntries(BuildContext context) async {
weightEntriesData = Provider.of<BodyWeight>(context, listen: false);
}
@override
Widget build(BuildContext context) {
weightEntriesData = Provider.of<BodyWeight>(context, listen: false);
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
@@ -141,39 +132,31 @@ class _DashboardWeightWidgetState extends State<DashboardWeightWidget> {
AppLocalizations.of(context).weight,
style: Theme.of(context).textTheme.headline4,
),
FutureBuilder(
future: _refreshWeightEntries(context),
builder: (context, snapshot) => snapshot.connectionState == ConnectionState.waiting
? Container(
height: 180,
child: Center(child: CircularProgressIndicator()),
)
: Column(
children: [
weightEntriesData.items.length > 0
? Container(
padding: EdgeInsets.all(15),
height: 180,
child: WeightChartWidget(weightEntriesData.items),
)
: Text('You have no weight entries'),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
TextButton(
child: const Text('Action one'),
onPressed: () {},
),
const SizedBox(width: 8),
TextButton(
child: const Text('Action two'),
onPressed: () {},
),
const SizedBox(width: 8),
],
),
],
Column(
children: [
weightEntriesData.items.length > 0
? Container(
padding: EdgeInsets.all(15),
height: 180,
child: WeightChartWidget(weightEntriesData.items),
)
: Text('You have no weight entries'),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
TextButton(
child: const Text('Action one'),
onPressed: () {},
),
const SizedBox(width: 8),
TextButton(
child: const Text('Action two'),
onPressed: () {},
),
const SizedBox(width: 8),
],
),
],
),
],
),
@@ -197,14 +180,16 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
WorkoutPlan _workoutPlan;
var showDetail = false;
Future<void> _fetchWorkoutEntries(BuildContext context) async {
_workoutPlan = Provider.of<WorkoutPlans>(context, listen: false).activePlan;
_workoutPlan = await Provider.of<WorkoutPlans>(context, listen: false)
.fetchAndSetFullWorkout(_workoutPlan.id);
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
Widget build(BuildContext context) {
_workoutPlan = Provider.of<WorkoutPlans>(context, listen: false).activePlan;
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
@@ -213,60 +198,52 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
AppLocalizations.of(context).labelWorkoutPlan,
style: Theme.of(context).textTheme.headline4,
),
FutureBuilder(
future: _fetchWorkoutEntries(context),
builder: (context, snapshot) => snapshot.connectionState == ConnectionState.waiting
? Center(
child:
Container(height: 180, child: Center(child: CircularProgressIndicator())),
_workoutPlan != null
? Column(children: [
Text(
DateFormat.yMd().format(_workoutPlan.creationDate),
style: Theme.of(context).textTheme.headline6,
),
TextButton(
child: Text(
_workoutPlan.description,
style: TextStyle(fontSize: 20),
),
onPressed: () {
return Navigator.of(context)
.pushNamed(WorkoutPlanScreen.routeName, arguments: _workoutPlan);
},
),
..._workoutPlan.days.map((workoutDay) {
return Column(children: [
const SizedBox(height: 10),
showDetail == true
? Text(
workoutDay.description,
style: TextStyle(fontWeight: FontWeight.bold),
)
: Text(workoutDay.description),
if (showDetail)
...workoutDay.sets
.map((set) => Text(set.exercises.map((e) => e.name).join(',')))
.toList(),
]);
}).toList(),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
TextButton(
child: Text(AppLocalizations.of(context).toggleDetails),
onPressed: () {
setState(() {
showDetail = !showDetail;
});
},
),
],
)
: _workoutPlan != null
? Column(children: [
Text(
DateFormat.yMd().format(_workoutPlan.creationDate),
style: Theme.of(context).textTheme.headline6,
),
TextButton(
child: Text(
_workoutPlan.description,
style: TextStyle(fontSize: 20),
),
onPressed: () {
return Navigator.of(context)
.pushNamed(WorkoutPlanScreen.routeName, arguments: _workoutPlan);
},
),
..._workoutPlan.days.map((workoutDay) {
return Column(children: [
const SizedBox(height: 10),
showDetail == true
? Text(
workoutDay.description,
style: TextStyle(fontWeight: FontWeight.bold),
)
: Text(workoutDay.description),
if (showDetail)
...workoutDay.sets
.map((set) => Text(set.exercises.map((e) => e.name).join(',')))
.toList(),
]);
}).toList(),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
TextButton(
child: Text(AppLocalizations.of(context).toggleDetails),
onPressed: () {
setState(() {
showDetail = !showDetail;
});
},
),
],
)
])
: Text('you have no workouts'),
),
])
: Text('you have no workouts'),
],
),
);

View File

@@ -86,7 +86,6 @@ class WeightEntriesList extends StatelessWidget {
),
),
background: Container(
//color: Theme.of(context).accentColor,
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(right: 20),
margin: EdgeInsets.symmetric(
@@ -98,13 +97,8 @@ class WeightEntriesList extends StatelessWidget {
//color: Colors.white,
),
),
//direction: DismissDirection.endToStart,
child: Card(
child: ListTile(
//onTap: () => Navigator.of(context).pushNamed(
// WorkoutPlanScreen.routeName,
// arguments: currentPlan,
//),
onTap: () {},
title: Text(DateFormat.yMd().format(currentEntry.date).toString()),
subtitle: Text('${currentEntry.weight} kg'),