mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
Extract some logic to their own widgets
This commit is contained in:
@@ -49,9 +49,11 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
List<NutritionalPlan> _plans = [];
|
||||
List<Ingredient> ingredients = [];
|
||||
|
||||
NutritionPlansProvider(this.baseProvider, List<NutritionalPlan> entries,
|
||||
{IngredientDatabase? database})
|
||||
: _plans = entries {
|
||||
NutritionPlansProvider(
|
||||
this.baseProvider,
|
||||
List<NutritionalPlan> entries, {
|
||||
IngredientDatabase? database,
|
||||
}) : _plans = entries {
|
||||
this.database = database ?? locator<IngredientDatabase>();
|
||||
}
|
||||
|
||||
@@ -73,8 +75,10 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
NutritionalPlan? get currentPlan {
|
||||
final now = DateTime.now();
|
||||
return _plans
|
||||
.where((plan) =>
|
||||
plan.startDate.isBefore(now) && (plan.endDate == null || plan.endDate!.isAfter(now)))
|
||||
.where(
|
||||
(plan) =>
|
||||
plan.startDate.isBefore(now) && (plan.endDate == null || plan.endDate!.isAfter(now)),
|
||||
)
|
||||
.toList()
|
||||
.sorted((a, b) => b.creationDate.compareTo(a.creationDate))
|
||||
.firstOrNull;
|
||||
@@ -114,10 +118,9 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
|
||||
/// Fetches and sets all plans fully, i.e. with all corresponding child objects
|
||||
Future<void> fetchAndSetAllPlansFull() async {
|
||||
final data = await baseProvider.fetchPaginated(baseProvider.makeUrl(
|
||||
_nutritionalPlansPath,
|
||||
query: {'limit': API_MAX_PAGE_SIZE},
|
||||
));
|
||||
final data = await baseProvider.fetchPaginated(
|
||||
baseProvider.makeUrl(_nutritionalPlansPath, query: {'limit': API_MAX_PAGE_SIZE}),
|
||||
);
|
||||
await Future.wait(data.map((e) => fetchAndSetPlanFull(e['id'])).toList());
|
||||
}
|
||||
|
||||
@@ -225,10 +228,7 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
/// Adds a meal to a plan
|
||||
Future<Meal> addMeal(Meal meal, int planId) async {
|
||||
final plan = findById(planId);
|
||||
final data = await baseProvider.post(
|
||||
meal.toJson(),
|
||||
baseProvider.makeUrl(_mealPath),
|
||||
);
|
||||
final data = await baseProvider.post(meal.toJson(), baseProvider.makeUrl(_mealPath));
|
||||
|
||||
meal = Meal.fromJson(data);
|
||||
plan.meals.add(meal);
|
||||
@@ -269,10 +269,7 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
|
||||
/// Adds a meal item to a meal
|
||||
Future<MealItem> addMealItem(MealItem mealItem, Meal meal) async {
|
||||
final data = await baseProvider.post(
|
||||
mealItem.toJson(),
|
||||
baseProvider.makeUrl(_mealItemPath),
|
||||
);
|
||||
final data = await baseProvider.post(mealItem.toJson(), baseProvider.makeUrl(_mealItemPath));
|
||||
|
||||
mealItem = MealItem.fromJson(data);
|
||||
mealItem.ingredient = await fetchIngredient(mealItem.ingredientId);
|
||||
@@ -301,6 +298,7 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
Future<void> clearIngredientCache() async {
|
||||
ingredients = [];
|
||||
await database.deleteEverything();
|
||||
}
|
||||
|
||||
@@ -314,9 +312,9 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
try {
|
||||
ingredient = ingredients.firstWhere((e) => e.id == ingredientId);
|
||||
} on StateError {
|
||||
final ingredientDb = await (database.select(database.ingredients)
|
||||
..where((e) => e.id.equals(ingredientId)))
|
||||
.getSingleOrNull();
|
||||
final ingredientDb = await (database.select(
|
||||
database.ingredients,
|
||||
)..where((e) => e.id.equals(ingredientId))).getSingleOrNull();
|
||||
|
||||
// Try to fetch from local db
|
||||
if (ingredientDb != null) {
|
||||
@@ -325,8 +323,9 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
_logger.info("Loaded ingredient '${ingredient.name}' from db cache");
|
||||
|
||||
// Prune old entries
|
||||
if (DateTime.now()
|
||||
.isAfter(ingredientDb.lastFetched.add(const Duration(days: DAYS_TO_CACHE)))) {
|
||||
if (DateTime.now().isAfter(
|
||||
ingredientDb.lastFetched.add(const Duration(days: DAYS_TO_CACHE)),
|
||||
)) {
|
||||
(database.delete(database.ingredients)..where((i) => i.id.equals(ingredientId))).go();
|
||||
}
|
||||
} else {
|
||||
@@ -336,7 +335,9 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
ingredient = Ingredient.fromJson(data);
|
||||
ingredients.add(ingredient);
|
||||
|
||||
database.into(database.ingredients).insert(
|
||||
database
|
||||
.into(database.ingredients)
|
||||
.insert(
|
||||
IngredientsCompanion.insert(
|
||||
id: ingredientId,
|
||||
data: jsonEncode(data),
|
||||
@@ -415,10 +416,7 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
final plan = findById(meal.planId);
|
||||
final Log log = Log.fromMealItem(item, plan.id!, meal.id, mealDateTime);
|
||||
|
||||
final data = await baseProvider.post(
|
||||
log.toJson(),
|
||||
baseProvider.makeUrl(_nutritionDiaryPath),
|
||||
);
|
||||
final data = await baseProvider.post(log.toJson(), baseProvider.makeUrl(_nutritionDiaryPath));
|
||||
log.id = data['id'];
|
||||
plan.diaryEntries.add(log);
|
||||
}
|
||||
@@ -426,19 +424,12 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
/// Log custom ingredient to nutrition diary
|
||||
Future<void> logIngredientToDiary(
|
||||
MealItem mealItem,
|
||||
int planId, [
|
||||
DateTime? dateTime,
|
||||
]) async {
|
||||
Future<void> logIngredientToDiary(MealItem mealItem, int planId, [DateTime? dateTime]) async {
|
||||
final plan = findById(planId);
|
||||
mealItem.ingredient = await fetchIngredient(mealItem.ingredientId);
|
||||
final log = Log.fromMealItem(mealItem, plan.id!, null, dateTime);
|
||||
|
||||
final data = await baseProvider.post(
|
||||
log.toJson(),
|
||||
baseProvider.makeUrl(_nutritionDiaryPath),
|
||||
);
|
||||
final data = await baseProvider.post(log.toJson(), baseProvider.makeUrl(_nutritionDiaryPath));
|
||||
log.id = data['id'];
|
||||
plan.diaryEntries.add(log);
|
||||
notifyListeners();
|
||||
@@ -458,11 +449,7 @@ class NutritionPlansProvider with ChangeNotifier {
|
||||
final data = await baseProvider.fetchPaginated(
|
||||
baseProvider.makeUrl(
|
||||
_nutritionDiaryPath,
|
||||
query: {
|
||||
'plan': plan.id?.toString(),
|
||||
'limit': API_MAX_PAGE_SIZE,
|
||||
'ordering': 'datetime',
|
||||
},
|
||||
query: {'plan': plan.id?.toString(), 'limit': API_MAX_PAGE_SIZE, 'ordering': 'datetime'},
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -18,12 +18,11 @@
|
||||
|
||||
//import 'package:drift/drift.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/providers/user.dart';
|
||||
import 'package:wger/screens/configure_plates_screen.dart';
|
||||
import 'package:wger/widgets/core/settings/exercise_cache.dart';
|
||||
import 'package:wger/widgets/core/settings/ingredient_cache.dart';
|
||||
import 'package:wger/widgets/core/settings/theme.dart';
|
||||
|
||||
class SettingsPage extends StatelessWidget {
|
||||
static String routeName = '/SettingsPage';
|
||||
@@ -33,8 +32,6 @@ class SettingsPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final i18n = AppLocalizations.of(context);
|
||||
final nutritionProvider = Provider.of<NutritionPlansProvider>(context, listen: false);
|
||||
final userProvider = Provider.of<UserProvider>(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(i18n.settingsTitle)),
|
||||
@@ -44,50 +41,9 @@ class SettingsPage extends StatelessWidget {
|
||||
title: Text(i18n.settingsCacheTitle, style: Theme.of(context).textTheme.headlineSmall),
|
||||
),
|
||||
const SettingsExerciseCache(),
|
||||
ListTile(
|
||||
title: Text(i18n.settingsIngredientCacheDescription),
|
||||
subtitle: Text('${nutritionProvider.ingredients.length} cached ingredients'),
|
||||
trailing: IconButton(
|
||||
key: const ValueKey('cacheIconIngredients'),
|
||||
icon: const Icon(Icons.delete),
|
||||
onPressed: () async {
|
||||
await nutritionProvider.clearIngredientCache();
|
||||
|
||||
if (context.mounted) {
|
||||
final snackBar = SnackBar(content: Text(i18n.settingsCacheDeletedSnackbar));
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
const SettingsIngredientCache(),
|
||||
ListTile(title: Text(i18n.others, style: Theme.of(context).textTheme.headlineSmall)),
|
||||
ListTile(
|
||||
title: Text(i18n.themeMode),
|
||||
trailing: DropdownButton<ThemeMode>(
|
||||
key: const ValueKey('themeModeDropdown'),
|
||||
value: userProvider.themeMode,
|
||||
onChanged: (ThemeMode? newValue) {
|
||||
if (newValue != null) {
|
||||
userProvider.setThemeMode(newValue);
|
||||
}
|
||||
},
|
||||
items: ThemeMode.values.map<DropdownMenuItem<ThemeMode>>((ThemeMode value) {
|
||||
final label = (() {
|
||||
switch (value) {
|
||||
case ThemeMode.system:
|
||||
return i18n.systemMode;
|
||||
case ThemeMode.light:
|
||||
return i18n.lightMode;
|
||||
case ThemeMode.dark:
|
||||
return i18n.darkMode;
|
||||
}
|
||||
})();
|
||||
|
||||
return DropdownMenuItem<ThemeMode>(value: value, child: Text(label));
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
const SettingsTheme(),
|
||||
ListTile(
|
||||
title: Text(i18n.selectAvailablePlates),
|
||||
onTap: () {
|
||||
|
||||
32
lib/widgets/core/settings/ingredient_cache.dart
Normal file
32
lib/widgets/core/settings/ingredient_cache.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
|
||||
class SettingsIngredientCache extends StatelessWidget {
|
||||
const SettingsIngredientCache({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final i18n = AppLocalizations.of(context);
|
||||
final nutritionProvider = Provider.of<NutritionPlansProvider>(context, listen: false);
|
||||
|
||||
return ListTile(
|
||||
title: Text(i18n.settingsIngredientCacheDescription),
|
||||
subtitle: Text('${nutritionProvider.ingredients.length} cached ingredients'),
|
||||
trailing: IconButton(
|
||||
key: const ValueKey('cacheIconIngredients'),
|
||||
icon: const Icon(Icons.delete),
|
||||
onPressed: () async {
|
||||
await nutritionProvider.clearIngredientCache();
|
||||
|
||||
if (context.mounted) {
|
||||
final snackBar = SnackBar(content: Text(i18n.settingsCacheDeletedSnackbar));
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
41
lib/widgets/core/settings/theme.dart
Normal file
41
lib/widgets/core/settings/theme.dart
Normal file
@@ -0,0 +1,41 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/user.dart';
|
||||
|
||||
class SettingsTheme extends StatelessWidget {
|
||||
const SettingsTheme({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final i18n = AppLocalizations.of(context);
|
||||
final userProvider = Provider.of<UserProvider>(context);
|
||||
|
||||
return ListTile(
|
||||
title: Text(i18n.themeMode),
|
||||
trailing: DropdownButton<ThemeMode>(
|
||||
key: const ValueKey('themeModeDropdown'),
|
||||
value: userProvider.themeMode,
|
||||
onChanged: (ThemeMode? newValue) {
|
||||
if (newValue != null) {
|
||||
userProvider.setThemeMode(newValue);
|
||||
}
|
||||
},
|
||||
items: ThemeMode.values.map<DropdownMenuItem<ThemeMode>>((ThemeMode value) {
|
||||
final label = (() {
|
||||
switch (value) {
|
||||
case ThemeMode.system:
|
||||
return i18n.systemMode;
|
||||
case ThemeMode.light:
|
||||
return i18n.lightMode;
|
||||
case ThemeMode.dark:
|
||||
return i18n.darkMode;
|
||||
}
|
||||
})();
|
||||
|
||||
return DropdownMenuItem<ThemeMode>(value: value, child: Text(label));
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user