Fix import for localization strings

This commit is contained in:
Roland Geider
2025-10-19 14:23:58 +02:00
parent 5c44678557
commit 64dc10cdb2
94 changed files with 1446 additions and 1828 deletions

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/providers/measurement.dart';
import 'package:wger/providers/nutrition.dart';
@@ -42,8 +42,9 @@ Widget createDashboardScreen({locale = 'en'}) {
final mockNutritionProvider = MockNutritionPlansProvider();
when(mockNutritionProvider.currentPlan)
.thenAnswer((realInvocation) => getNutritionalPlanScreenshot());
when(
mockNutritionProvider.currentPlan,
).thenAnswer((realInvocation) => getNutritionalPlanScreenshot());
when(mockNutritionProvider.items).thenReturn([getNutritionalPlanScreenshot()]);
final mockWeightProvider = MockBodyWeightProvider();
@@ -57,21 +58,11 @@ Widget createDashboardScreen({locale = 'en'}) {
return MultiProvider(
providers: [
ChangeNotifierProvider<UserProvider>(
create: (context) => mockUserProvider,
),
ChangeNotifierProvider<WorkoutPlansProvider>(
create: (context) => mockWorkoutProvider,
),
ChangeNotifierProvider<NutritionPlansProvider>(
create: (context) => mockNutritionProvider,
),
ChangeNotifierProvider<BodyWeightProvider>(
create: (context) => mockWeightProvider,
),
ChangeNotifierProvider<MeasurementProvider>(
create: (context) => mockMeasurementProvider,
),
ChangeNotifierProvider<UserProvider>(create: (context) => mockUserProvider),
ChangeNotifierProvider<WorkoutPlansProvider>(create: (context) => mockWorkoutProvider),
ChangeNotifierProvider<NutritionPlansProvider>(create: (context) => mockNutritionProvider),
ChangeNotifierProvider<BodyWeightProvider>(create: (context) => mockWeightProvider),
ChangeNotifierProvider<MeasurementProvider>(create: (context) => mockMeasurementProvider),
],
child: MaterialApp(
locale: Locale(locale),

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/workout_plans.dart';
import 'package:wger/screens/workout_plan_screen.dart';
import 'package:wger/theme/theme.dart';
@@ -20,9 +20,7 @@ Widget createWorkoutDetailScreen({locale = 'en'}) {
return MultiProvider(
providers: [
ChangeNotifierProvider<WorkoutPlansProvider>(
create: (context) => mockWorkoutProvider,
),
ChangeNotifierProvider<WorkoutPlansProvider>(create: (context) => mockWorkoutProvider),
],
child: MaterialApp(
locale: Locale(locale),

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/workout_plans.dart';
import 'package:wger/screens/gym_mode.dart';
@@ -26,11 +26,7 @@ Widget createGymModeScreen({locale = 'en'}) {
//when(mockExerciseProvider.findExerciseBaseById(3)).thenReturn(bases[2]); // dead lift
return ChangeNotifierProvider<WorkoutPlansProvider>(
create: (context) => WorkoutPlansProvider(
mockBaseProvider,
mockExerciseProvider,
[workout],
),
create: (context) => WorkoutPlansProvider(mockBaseProvider, mockExerciseProvider, [workout]),
child: ChangeNotifierProvider<ExercisesProvider>(
create: (context) => mockExerciseProvider,
child: MaterialApp(
@@ -49,9 +45,7 @@ Widget createGymModeScreen({locale = 'en'}) {
),
child: const SizedBox(),
),
routes: {
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
},
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
),
),
);

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/measurement.dart';
import 'package:wger/screens/measurement_categories_screen.dart';
import 'package:wger/theme/theme.dart';
@@ -15,9 +15,7 @@ Widget createMeasurementScreen({locale = 'en'}) {
return MultiProvider(
providers: [
ChangeNotifierProvider<MeasurementProvider>(
create: (context) => mockMeasurementProvider,
),
ChangeNotifierProvider<MeasurementProvider>(create: (context) => mockMeasurementProvider),
],
child: MaterialApp(
locale: Locale(locale),

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/screens/nutritional_plan_screen.dart';

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/providers/user.dart';
import 'package:wger/screens/form_screen.dart';
@@ -22,12 +22,8 @@ Widget createWeightScreen({locale = 'en'}) {
return MultiProvider(
providers: [
ChangeNotifierProvider<UserProvider>(
create: (context) => mockUserProvider,
),
ChangeNotifierProvider<BodyWeightProvider>(
create: (context) => mockWeightProvider,
),
ChangeNotifierProvider<UserProvider>(create: (context) => mockUserProvider),
ChangeNotifierProvider<BodyWeightProvider>(create: (context) => mockWeightProvider),
],
child: MaterialApp(
locale: Locale(locale),

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
/// The amount of characters an exercise description needs to have
const MIN_CHARS_DESCRIPTION = 40;

View File

@@ -7,7 +7,7 @@ library;
/// probably better ways to do this, but that's the way it is right now).
import 'package:flutter/widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
String getTranslation(String value, BuildContext context) {
switch (value) {

View File

@@ -19,9 +19,9 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/exceptions/http_exception.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/exercises/translation.dart';
import 'package:wger/models/workouts/log.dart';
@@ -50,10 +50,7 @@ void showErrorDialog(dynamic exception, BuildContext context) {
);
}
void showHttpExceptionErrorDialog(
WgerHttpException exception,
BuildContext context,
) {
void showHttpExceptionErrorDialog(WgerHttpException exception, BuildContext context) {
log('showHttpExceptionErrorDialog: ');
log(exception.toString());
log('-------------------');
@@ -119,9 +116,7 @@ dynamic showDeleteDialog(
context: context,
builder: (BuildContext contextDialog) {
return AlertDialog(
content: Text(
AppLocalizations.of(context).confirmDelete(confirmDeleteName),
),
content: Text(AppLocalizations.of(context).confirmDelete(confirmDeleteName)),
actions: [
TextButton(
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
@@ -134,9 +129,7 @@ dynamic showDeleteDialog(
),
onPressed: () {
exerciseData[exercise]!.removeWhere((el) => el.id == log.id);
Provider.of<WorkoutPlansProvider>(context, listen: false).deleteLog(
log,
);
Provider.of<WorkoutPlansProvider>(context, listen: false).deleteLog(log);
Navigator.of(contextDialog).pop();

View File

@@ -19,6 +19,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
import 'package:wger/core/locator.dart';
import 'package:wger/powersync.dart';
@@ -53,8 +54,7 @@ import 'package:wger/screens/workout_plan_screen.dart';
import 'package:wger/screens/workout_plans_screen.dart';
import 'package:wger/theme/theme.dart';
import 'package:wger/widgets/core/about.dart';
import 'package:wger/widgets/core/settings.dart';
import 'package:logging/logging.dart';
import 'package:wger/widgets/core/settingsdart';
import 'providers/auth.dart';
@@ -92,9 +92,8 @@ class MyApp extends StatelessWidget {
providers: [
ChangeNotifierProvider(create: (ctx) => AuthProvider()),
ChangeNotifierProxyProvider<AuthProvider, ExercisesProvider>(
create: (context) => ExercisesProvider(
WgerBaseProvider(Provider.of(context, listen: false)),
),
create: (context) =>
ExercisesProvider(WgerBaseProvider(Provider.of(context, listen: false))),
update: (context, base, previous) =>
previous ?? ExercisesProvider(WgerBaseProvider(base)),
),
@@ -108,44 +107,34 @@ class MyApp extends StatelessWidget {
previous ?? WorkoutPlansProvider(WgerBaseProvider(auth), exercises, []),
),
ChangeNotifierProxyProvider<AuthProvider, NutritionPlansProvider>(
create: (context) => NutritionPlansProvider(
WgerBaseProvider(Provider.of(context, listen: false)),
[],
),
create: (context) =>
NutritionPlansProvider(WgerBaseProvider(Provider.of(context, listen: false)), []),
update: (context, auth, previous) =>
previous ?? NutritionPlansProvider(WgerBaseProvider(auth), []),
),
ChangeNotifierProxyProvider<AuthProvider, MeasurementProvider>(
create: (context) => MeasurementProvider(
WgerBaseProvider(Provider.of(context, listen: false)),
),
create: (context) =>
MeasurementProvider(WgerBaseProvider(Provider.of(context, listen: false))),
update: (context, base, previous) =>
previous ?? MeasurementProvider(WgerBaseProvider(base)),
),
ChangeNotifierProxyProvider<AuthProvider, UserProvider>(
create: (context) => UserProvider(
WgerBaseProvider(Provider.of(context, listen: false)),
),
create: (context) => UserProvider(WgerBaseProvider(Provider.of(context, listen: false))),
update: (context, base, previous) => previous ?? UserProvider(WgerBaseProvider(base)),
),
ChangeNotifierProxyProvider<AuthProvider, BodyWeightProvider>(
create: (context) => BodyWeightProvider(
WgerBaseProvider(Provider.of(context, listen: false)),
),
create: (context) =>
BodyWeightProvider(WgerBaseProvider(Provider.of(context, listen: false))),
update: (context, base, previous) =>
previous ?? BodyWeightProvider(WgerBaseProvider(base)),
),
ChangeNotifierProxyProvider<AuthProvider, GalleryProvider>(
create: (context) => GalleryProvider(
Provider.of(context, listen: false),
[],
),
create: (context) => GalleryProvider(Provider.of(context, listen: false), []),
update: (context, auth, previous) => previous ?? GalleryProvider(auth, []),
),
ChangeNotifierProxyProvider<AuthProvider, AddExerciseProvider>(
create: (context) => AddExerciseProvider(
WgerBaseProvider(Provider.of(context, listen: false)),
),
create: (context) =>
AddExerciseProvider(WgerBaseProvider(Provider.of(context, listen: false))),
update: (context, base, previous) =>
previous ?? AddExerciseProvider(WgerBaseProvider(base)),
),
@@ -164,8 +153,8 @@ class MyApp extends StatelessWidget {
future: auth.tryAutoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState == ConnectionState.waiting
? const SplashScreen()
: const AuthScreen(),
? const SplashScreen()
: const AuthScreen(),
),
routes: {
DashboardScreen.routeName: (ctx) => const DashboardScreen(),

View File

@@ -18,11 +18,11 @@
import 'package:collection/collection.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:powersync/sqlite3.dart' as sqlite;
import 'package:wger/helpers/consts.dart';
import 'package:wger/helpers/json.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/log.dart';
import 'package:wger/models/nutrition/meal.dart';
import 'package:wger/models/nutrition/meal_item.dart';
@@ -128,10 +128,7 @@ class NutritionalPlan {
}
Future<NutritionalPlan> loadChildren() async {
return copyWith(
diaryEntries: await Log.readByPlanId(id!),
meals: await Meal.readByPlanId(id!),
);
return copyWith(diaryEntries: await Log.readByPlanId(id!), meals: await Meal.readByPlanId(id!));
}
NutritionalPlan.empty() {
@@ -186,10 +183,7 @@ class NutritionalPlan {
return NutritionalGoals();
}
// otherwise, add up all the nutritional values of the meals and use that as goals
final sumValues = meals.fold(
NutritionalValues(),
(a, b) => a + b.plannedNutritionalValues,
);
final sumValues = meals.fold(NutritionalValues(), (a, b) => a + b.plannedNutritionalValues);
return NutritionalGoals(
energy: sumValues.energy,
fat: sumValues.fat,
@@ -304,21 +298,21 @@ class NutritionalPlan {
return NutritionalPlan.fromRow(row).loadChildren();
}
// this is a bit complicated.
// what we need at the end of the day, is a stream of List<NutritionPlan>, where
// a new value is emitted any time a plan is changed. But the plan is not just the plan record
// we need to load data for Logs and Meals corresponding to the plan also.
// so our options are:
// 1) db.watch with a select query on plans; and extra dart code to load the logs/meals stuff,
// but this only triggers for updates on the plans table, and misses logs/meals updates
// 2) db.watch with a huge join query across all tables from which we need info,
// so we have all the data in our resultset to create the datastructures with, but:
// - this creates long rows with lots of duplicated data (e.g. all the plan data) for every row
// which would only differ for e.g. the meal or the log item
// - it would probably get a bit messy to parse the resultset into the datastructures
// 3) the best of both worlds: load the data we need in dart at runtime, but explicitly
// trigger our code execution when *any* of the relevant tables changes
//
// this is a bit complicated.
// what we need at the end of the day, is a stream of List<NutritionPlan>, where
// a new value is emitted any time a plan is changed. But the plan is not just the plan record
// we need to load data for Logs and Meals corresponding to the plan also.
// so our options are:
// 1) db.watch with a select query on plans; and extra dart code to load the logs/meals stuff,
// but this only triggers for updates on the plans table, and misses logs/meals updates
// 2) db.watch with a huge join query across all tables from which we need info,
// so we have all the data in our resultset to create the datastructures with, but:
// - this creates long rows with lots of duplicated data (e.g. all the plan data) for every row
// which would only differ for e.g. the meal or the log item
// - it would probably get a bit messy to parse the resultset into the datastructures
// 3) the best of both worlds: load the data we need in dart at runtime, but explicitly
// trigger our code execution when *any* of the relevant tables changes
//
static Stream<List<NutritionalPlan>> watchNutritionPlans() {
return db.onChange([tableNutritionPlans, tableLogItems, tableMeals]).asyncMap((event) async {
final data = await db.getAll('SELECT * FROM $tableNutritionPlans ORDER BY creation_date');
@@ -336,15 +330,16 @@ class NutritionalPlan {
static Stream<NutritionalPlan?> watchNutritionPlanLast() {
return db.onChange([tableNutritionPlans, tableLogItems, tableMeals]).asyncMap((event) async {
final res =
await db.getAll('SELECT * FROM $tableNutritionPlans ORDER BY creation_date DESC LIMIT 1');
final res = await db.getAll(
'SELECT * FROM $tableNutritionPlans ORDER BY creation_date DESC LIMIT 1',
);
if (res.isEmpty) {
return null;
}
return NutritionalPlan.fromRow(res.first).loadChildren();
});
}
/*
/*
static Stream<List<NutritionalPlan>> watchNutritionPlan(int id) {
return db
.watch('SELECT * FROM $tableNutritionPlans WHERE id = ?', parameters: [id]).map((results) {

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/add_exercise.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/user.dart';
@@ -76,9 +76,7 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
final baseId = await addExerciseProvider.addExercise();
final base = await exerciseProvider.fetchAndSetExercise(baseId);
final name = base
.getExercise(
Localizations.localeOf(context).languageCode,
)
.getExercise(Localizations.localeOf(context).languageCode)
.name;
setState(() {
@@ -91,9 +89,7 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
builder: (BuildContext context) {
return AlertDialog(
title: Text(AppLocalizations.of(context).success),
content: Text(
AppLocalizations.of(context).cacheWarning,
),
content: Text(AppLocalizations.of(context).cacheWarning),
actions: [
TextButton(
child: Text(name),
@@ -112,11 +108,7 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
);
},
child: _isLoading
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(),
)
? const SizedBox(height: 20, width: 20, child: CircularProgressIndicator())
: Text(AppLocalizations.of(context).save),
)
else
@@ -207,8 +199,11 @@ class EmailNotVerified extends StatelessWidget {
ListTile(
leading: const Icon(Icons.warning),
title: Text(AppLocalizations.of(context).unVerifiedEmail),
subtitle: Text(AppLocalizations.of(context)
.contributeExerciseWarning(MIN_ACCOUNT_AGE.toString())),
subtitle: Text(
AppLocalizations.of(
context,
).contributeExerciseWarning(MIN_ACCOUNT_AGE.toString()),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,

View File

@@ -19,21 +19,18 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/exceptions/http_exception.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/helpers/misc.dart';
import 'package:wger/helpers/ui.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/screens/update_app_screen.dart';
import 'package:wger/theme/theme.dart';
import '../providers/auth.dart';
enum AuthMode {
Signup,
Login,
}
enum AuthMode { Signup, Login }
class AuthScreen extends StatelessWidget {
const AuthScreen();
@@ -50,10 +47,7 @@ class AuthScreen extends StatelessWidget {
top: 0,
right: 0,
left: 0,
child: Container(
height: 0.55 * deviceSize.height,
color: wgerPrimaryColor,
),
child: Container(height: 0.55 * deviceSize.height, color: wgerPrimaryColor),
),
SingleChildScrollView(
child: SizedBox(
@@ -64,16 +58,10 @@ class AuthScreen extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: 0.15 * deviceSize.height),
const Image(
image: AssetImage('assets/images/logo-white.png'),
width: 85,
),
const Image(image: AssetImage('assets/images/logo-white.png'), width: 85),
Container(
margin: const EdgeInsets.only(bottom: 20.0),
padding: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 94.0,
),
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 94.0),
child: const Text(
'wger',
style: TextStyle(
@@ -190,11 +178,10 @@ class _AuthCardState extends State<AuthCard> {
// Login existing user
late Map<String, LoginActions> res;
if (_authMode == AuthMode.Login) {
res = await Provider.of<AuthProvider>(context, listen: false).login(
_authData['username']!,
_authData['password']!,
_authData['serverUrl']!,
);
res = await Provider.of<AuthProvider>(
context,
listen: false,
).login(_authData['username']!, _authData['password']!, _authData['serverUrl']!);
// Register new user
} else {
@@ -210,9 +197,9 @@ class _AuthCardState extends State<AuthCard> {
// Check if update is required else continue normally
if (res.containsKey('action')) {
if (res['action'] == LoginActions.update && mounted) {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => const UpdateAppScreen()),
);
Navigator.of(
context,
).push(MaterialPageRoute(builder: (context) => const UpdateAppScreen()));
return;
}
}
@@ -260,16 +247,11 @@ class _AuthCardState extends State<AuthCard> {
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
elevation: 8.0,
child: Container(
width: deviceSize.width * 0.9,
padding: EdgeInsets.symmetric(
horizontal: 15.0,
vertical: 0.025 * deviceSize.height,
),
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 0.025 * deviceSize.height),
child: Form(
key: _formKey,
child: SingleChildScrollView(
@@ -297,9 +279,7 @@ class _AuthCardState extends State<AuthCard> {
return null;
},
inputFormatters: [
FilteringTextInputFormatter.deny(RegExp(r'\s\b|\b\s')),
],
inputFormatters: [FilteringTextInputFormatter.deny(RegExp(r'\s\b|\b\s'))],
onSaved: (value) {
_authData['username'] = value!;
},
@@ -327,63 +307,69 @@ class _AuthCardState extends State<AuthCard> {
_authData['email'] = value!;
},
),
StatefulBuilder(builder: (context, updateState) {
return TextFormField(
key: const Key('inputPassword'),
decoration: InputDecoration(
labelText: AppLocalizations.of(context).password,
prefixIcon: const Icon(Icons.password),
suffixIcon: IconButton(
icon: Icon(isObscure ? Icons.visibility_off : Icons.visibility),
onPressed: () {
isObscure = !isObscure;
updateState(() {});
},
),
),
autofillHints: const [AutofillHints.password],
obscureText: isObscure,
controller: _passwordController,
textInputAction: TextInputAction.next,
validator: (value) {
if (value!.isEmpty || value.length < 8) {
return AppLocalizations.of(context).passwordTooShort;
}
return null;
},
onSaved: (value) {
_authData['password'] = value!;
},
);
}),
if (_authMode == AuthMode.Signup)
StatefulBuilder(builder: (context, updateState) {
StatefulBuilder(
builder: (context, updateState) {
return TextFormField(
key: const Key('inputPassword2'),
key: const Key('inputPassword'),
decoration: InputDecoration(
labelText: AppLocalizations.of(context).confirmPassword,
labelText: AppLocalizations.of(context).password,
prefixIcon: const Icon(Icons.password),
suffixIcon: IconButton(
icon: Icon(confirmIsObscure ? Icons.visibility_off : Icons.visibility),
icon: Icon(isObscure ? Icons.visibility_off : Icons.visibility),
onPressed: () {
confirmIsObscure = !confirmIsObscure;
isObscure = !isObscure;
updateState(() {});
},
),
),
controller: _password2Controller,
enabled: _authMode == AuthMode.Signup,
obscureText: confirmIsObscure,
validator: _authMode == AuthMode.Signup
? (value) {
if (value != _passwordController.text) {
return AppLocalizations.of(context).passwordsDontMatch;
}
return null;
}
: null,
autofillHints: const [AutofillHints.password],
obscureText: isObscure,
controller: _passwordController,
textInputAction: TextInputAction.next,
validator: (value) {
if (value!.isEmpty || value.length < 8) {
return AppLocalizations.of(context).passwordTooShort;
}
return null;
},
onSaved: (value) {
_authData['password'] = value!;
},
);
}),
},
),
if (_authMode == AuthMode.Signup)
StatefulBuilder(
builder: (context, updateState) {
return TextFormField(
key: const Key('inputPassword2'),
decoration: InputDecoration(
labelText: AppLocalizations.of(context).confirmPassword,
prefixIcon: const Icon(Icons.password),
suffixIcon: IconButton(
icon: Icon(
confirmIsObscure ? Icons.visibility_off : Icons.visibility,
),
onPressed: () {
confirmIsObscure = !confirmIsObscure;
updateState(() {});
},
),
),
controller: _password2Controller,
enabled: _authMode == AuthMode.Signup,
obscureText: confirmIsObscure,
validator: _authMode == AuthMode.Signup
? (value) {
if (value != _passwordController.text) {
return AppLocalizations.of(context).passwordsDontMatch;
}
return null;
}
: null,
);
},
),
// Off-stage widgets are kept in the tree, otherwise the server URL
// would not be saved to _authData
Offstage(
@@ -426,8 +412,9 @@ class _AuthCardState extends State<AuthCard> {
IconButton(
icon: const Icon(Icons.undo),
onPressed: () {
_serverUrlController.text =
kDebugMode ? DEFAULT_SERVER_TEST : DEFAULT_SERVER_PROD;
_serverUrlController.text = kDebugMode
? DEFAULT_SERVER_TEST
: DEFAULT_SERVER_PROD;
},
),
Text(AppLocalizations.of(context).reset),
@@ -485,14 +472,9 @@ class _AuthCardState extends State<AuthCard> {
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(text.substring(0, text.lastIndexOf('?') + 1)),
Text(
text.substring(0, text.lastIndexOf('?') + 1),
),
Text(
text.substring(
text.lastIndexOf('?') + 1,
text.length,
),
text.substring(text.lastIndexOf('?') + 1, text.length),
style: const TextStyle(
//color: wgerPrimaryColor,
fontWeight: FontWeight.w700,

View File

@@ -20,6 +20,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/l10n/generatedapp_localizations.dart';
import 'package:wger/models/muscle.dart';
import 'package:wger/widgets/core/app_bar.dart';
import 'package:wger/widgets/dashboard/calendar.dart';
@@ -90,9 +91,8 @@ class _DashboardMuscleWidgetState extends State<DashboardMuscleWidget> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.brown,
child: Column(
children: [Text('muscles'), ..._data.map((e) => Text(e.name)).toList()],
));
color: Colors.brown,
child: Column(children: [Text('muscles'), ..._data.map((e) => Text(e.name)).toList()]),
);
}
}

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/widgets/core/app_bar.dart';
@@ -43,11 +43,7 @@ class _ExercisesScreenState extends State<ExercisesScreen> {
Expanded(
child: exercisesList.isEmpty
? const Center(
child: SizedBox(
height: 100,
width: 100,
child: CircularProgressIndicator(),
),
child: SizedBox(height: 100, width: 100, child: CircularProgressIndicator()),
)
: _ExercisesList(exerciseBaseList: exercisesList),
),

View File

@@ -17,9 +17,9 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/platform.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/gallery.dart';
import 'package:wger/widgets/core/app_bar.dart';
import 'package:wger/widgets/gallery/forms.dart';

View File

@@ -17,11 +17,11 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
import 'package:rive/rive.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/powersync.dart';
import 'package:wger/providers/auth.dart';
import 'package:wger/providers/body_weight.dart';

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/meal.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/widgets/nutrition/meal.dart';
@@ -59,10 +59,7 @@ class _LogMealScreenState extends State<LogMealScreen> {
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: Column(
children: [
Text(
meal.name,
style: Theme.of(context).textTheme.headlineSmall,
),
Text(meal.name, style: Theme.of(context).textTheme.headlineSmall),
if (meal.mealItems.isEmpty)
ListTile(title: Text(AppLocalizations.of(context).noIngredientsDefined))
else
@@ -114,9 +111,7 @@ class _LogMealScreenState extends State<LogMealScreen> {
},
),
TextButton(
child: Text(
MaterialLocalizations.of(context).cancelButtonLabel,
),
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
onPressed: () => Navigator.of(context).pop(),
),
],

View File

@@ -17,7 +17,7 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/widgets/nutrition/meal.dart';
@@ -37,17 +37,11 @@ class _LogMealsScreenState extends State<LogMealsScreen> {
final nutritionalPlan = ModalRoute.of(context)!.settings.arguments as NutritionalPlan;
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context).selectMealToLog),
),
appBar: AppBar(title: Text(AppLocalizations.of(context).selectMealToLog)),
body: ListView.builder(
itemCount: nutritionalPlan.meals.length,
itemBuilder: (context, index) => MealWidget(
nutritionalPlan.meals[index],
nutritionalPlan.dedupMealItems,
true,
true,
),
itemBuilder: (context, index) =>
MealWidget(nutritionalPlan.meals[index], nutritionalPlan.dedupMealItems, true, true),
),
);
}

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/measurement.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/widgets/measurements/categories.dart';

View File

@@ -17,17 +17,14 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/measurement.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/widgets/measurements/entries.dart';
import 'package:wger/widgets/measurements/forms.dart';
enum MeasurementOptions {
edit,
delete,
}
enum MeasurementOptions { edit, delete }
class MeasurementEntriesScreen extends StatelessWidget {
const MeasurementEntriesScreen();
@@ -62,9 +59,7 @@ class MeasurementEntriesScreen extends StatelessWidget {
context: context,
builder: (BuildContext contextDialog) {
return AlertDialog(
content: Text(
AppLocalizations.of(context).confirmDelete(category.name),
),
content: Text(AppLocalizations.of(context).confirmDelete(category.name)),
actions: [
TextButton(
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
@@ -73,9 +68,7 @@ class MeasurementEntriesScreen extends StatelessWidget {
TextButton(
child: Text(
AppLocalizations.of(context).delete,
style: TextStyle(
color: Theme.of(context).colorScheme.error,
),
style: TextStyle(color: Theme.of(context).colorScheme.error),
),
onPressed: () {
// Confirmed, delete the workout

View File

@@ -19,9 +19,9 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_svg_icons/flutter_svg_icons.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/screens/form_screen.dart';
@@ -29,10 +29,7 @@ import 'package:wger/screens/log_meals_screen.dart';
import 'package:wger/widgets/nutrition/forms.dart';
import 'package:wger/widgets/nutrition/nutritional_plan_detail.dart';
enum NutritionalPlanOptions {
edit,
delete,
}
enum NutritionalPlanOptions { edit, delete }
class NutritionalPlanScreen extends StatefulWidget {
const NutritionalPlanScreen();
@@ -52,8 +49,10 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
final id = ModalRoute.of(context)!.settings.arguments as String;
//final id = 111;
final stream =
Provider.of<NutritionPlansProvider>(context, listen: false).watchNutritionPlan(id);
final stream = Provider.of<NutritionPlansProvider>(
context,
listen: false,
).watchNutritionPlan(id);
_subscription = stream.listen((plan) {
if (!context.mounted) {
return;
@@ -105,10 +104,7 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
heroTag: null,
tooltip: AppLocalizations.of(context).logMeal,
onPressed: () {
Navigator.of(context).pushNamed(
LogMealsScreen.routeName,
arguments: _plan,
);
Navigator.of(context).pushNamed(LogMealsScreen.routeName, arguments: _plan);
},
child: const SvgIcon(
icon: SvgIconData('assets/icons/meal-diary.svg'),
@@ -128,9 +124,7 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
actions: [
if (!_plan!.onlyLogging)
IconButton(
icon: const SvgIcon(
icon: SvgIconData('assets/icons/meal-add.svg'),
),
icon: const SvgIcon(icon: SvgIconData('assets/icons/meal-add.svg')),
onPressed: () {
Navigator.pushNamed(
context,
@@ -158,8 +152,10 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
);
break;
case NutritionalPlanOptions.delete:
Provider.of<NutritionPlansProvider>(context, listen: false)
.deletePlan(_plan!.id!);
Provider.of<NutritionPlansProvider>(
context,
listen: false,
).deletePlan(_plan!.id!);
Navigator.of(context).pop();
break;
}
@@ -189,8 +185,9 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
titlePadding: const EdgeInsets.fromLTRB(56, 0, 56, 16),
title: Text(
_plan!.getLabel(context),
style:
Theme.of(context).textTheme.titleLarge?.copyWith(color: appBarForeground),
style: Theme.of(
context,
).textTheme.titleLarge?.copyWith(color: appBarForeground),
),
),
),
@@ -198,22 +195,17 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
future: NutritionalPlan.read(_plan!.id!),
builder: (context, AsyncSnapshot<NutritionalPlan> snapshot) =>
snapshot.connectionState == ConnectionState.waiting
? SliverList(
delegate: SliverChildListDelegate(
[
const SizedBox(
height: 200,
child: Center(
child: CircularProgressIndicator(),
),
),
],
),
)
: Consumer<NutritionPlansProvider>(
builder: (context, value, child) =>
NutritionalPlanDetailWidget(_plan!),
? SliverList(
delegate: SliverChildListDelegate([
const SizedBox(
height: 200,
child: Center(child: CircularProgressIndicator()),
),
]),
)
: Consumer<NutritionPlansProvider>(
builder: (context, value, child) => NutritionalPlanDetailWidget(_plan!),
),
),
],
),

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/widgets/core/app_bar.dart';

View File

@@ -17,7 +17,7 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
class UpdateAppScreen extends StatelessWidget {
const UpdateAppScreen();

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/widgets/core/app_bar.dart';

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/workout_plan.dart';
import 'package:wger/providers/workout_plans.dart';
import 'package:wger/screens/form_screen.dart';
@@ -27,15 +27,9 @@ import 'package:wger/widgets/workouts/forms.dart';
import 'package:wger/widgets/workouts/workout_logs.dart';
import 'package:wger/widgets/workouts/workout_plan_detail.dart';
enum WorkoutScreenMode {
workout,
log,
}
enum WorkoutScreenMode { workout, log }
enum WorkoutOptions {
edit,
delete,
}
enum WorkoutOptions { edit, delete }
class WorkoutPlanScreen extends StatefulWidget {
const WorkoutPlanScreen();
@@ -55,8 +49,10 @@ class _WorkoutPlanScreenState extends State<WorkoutPlanScreen> {
}
Future<WorkoutPlan> _loadFullWorkout(BuildContext context, int planId) {
return Provider.of<WorkoutPlansProvider>(context, listen: false)
.fetchAndSetWorkoutPlanFull(planId);
return Provider.of<WorkoutPlansProvider>(
context,
listen: false,
).fetchAndSetWorkoutPlanFull(planId);
}
Widget getBody(WorkoutPlan plan) {
@@ -105,8 +101,10 @@ class _WorkoutPlanScreenState extends State<WorkoutPlanScreen> {
// Delete
} else if (value == WorkoutOptions.delete) {
Provider.of<WorkoutPlansProvider>(context, listen: false)
.deleteWorkout(workoutPlan.id!);
Provider.of<WorkoutPlansProvider>(
context,
listen: false,
).deleteWorkout(workoutPlan.id!);
Navigator.of(context).pop();
// Toggle Mode
@@ -131,19 +129,14 @@ class _WorkoutPlanScreenState extends State<WorkoutPlanScreen> {
FutureBuilder(
future: _loadFullWorkout(context, workoutPlan.id!),
builder: (context, AsyncSnapshot<WorkoutPlan> snapshot) => SliverList(
delegate: SliverChildListDelegate(
[
if (snapshot.connectionState == ConnectionState.waiting)
const SizedBox(
height: 200,
child: Center(child: CircularProgressIndicator()),
)
else
Consumer<WorkoutPlansProvider>(
builder: (context, value, child) => getBody(workoutPlan),
),
],
),
delegate: SliverChildListDelegate([
if (snapshot.connectionState == ConnectionState.waiting)
const SizedBox(height: 200, child: Center(child: CircularProgressIndicator()))
else
Consumer<WorkoutPlansProvider>(
builder: (context, value, child) => getBody(workoutPlan),
),
]),
),
),
],

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/workout_plan.dart';
import 'package:wger/providers/workout_plans.dart';
import 'package:wger/screens/form_screen.dart';

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/exercises/forms.dart';
import 'package:wger/helpers/i18n.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/category.dart';
import 'package:wger/models/exercises/equipment.dart';
import 'package:wger/models/exercises/muscle.dart';

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/add_exercise.dart';
import 'package:wger/providers/exercises.dart';
@@ -40,9 +40,7 @@ class Step2Variations extends StatelessWidget {
...exerciseProvider.exerciseBasesByVariation[key]!.map(
(base) => Text(
base
.getExercise(
Localizations.localeOf(context).languageCode,
)
.getExercise(Localizations.localeOf(context).languageCode)
.name,
overflow: TextOverflow.ellipsis,
),
@@ -61,7 +59,9 @@ class Step2Variations extends StatelessWidget {
),
),
// Exercise bases without variations
...exerciseProvider.exercises.where((b) => b.variationId == null).map(
...exerciseProvider.exercises
.where((b) => b.variationId == null)
.map(
(base) => Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -72,9 +72,7 @@ class Step2Variations extends StatelessWidget {
children: [
Text(
base
.getExercise(
Localizations.localeOf(context).languageCode,
)
.getExercise(Localizations.localeOf(context).languageCode)
.name,
overflow: TextOverflow.ellipsis,
),

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/exercises/forms.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/add_exercise.dart';
import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart';

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/exercises/forms.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/language.dart';
import 'package:wger/providers/add_exercise.dart';
import 'package:wger/providers/exercises.dart';
@@ -74,10 +74,9 @@ class _Step4TranslationState extends State<Step4Translation> {
final names = alternateNames!.split('\n');
for (final name in names) {
if (name.length < MIN_CHARS_NAME || name.length > MAX_CHARS_NAME) {
return AppLocalizations.of(context).enterCharacters(
MIN_CHARS_NAME,
MAX_CHARS_NAME,
);
return AppLocalizations.of(
context,
).enterCharacters(MIN_CHARS_NAME, MAX_CHARS_NAME);
}
}
}

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/add_exercise.dart';
import 'package:wger/widgets/add_exercise/mixins/image_picker_mixin.dart';
import 'package:wger/widgets/add_exercise/preview_images.dart';
@@ -26,9 +26,7 @@ class _Step5ImagesState extends State<Step5Images> with ExerciseImagePickerMixin
),
Consumer<AddExerciseProvider>(
builder: (ctx, provider, __) => provider.exerciseImages.isNotEmpty
? PreviewExerciseImages(
selectedImages: provider.exerciseImages,
)
? PreviewExerciseImages(selectedImages: provider.exerciseImages)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [

View File

@@ -17,10 +17,10 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/misc.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/auth.dart';
class AboutEntry extends StatelessWidget {
@@ -66,9 +66,7 @@ class AboutPage extends StatelessWidget {
final today = DateTime.now();
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context).aboutPageTitle),
),
appBar: AppBar(title: Text(AppLocalizations.of(context).aboutPageTitle)),
body: SingleChildScrollView(
padding: const EdgeInsets.all(20.0),
child: Column(
@@ -89,13 +87,12 @@ class AboutPage extends StatelessWidget {
children: [
const Text(
'Wger',
style: TextStyle(
fontSize: 23,
fontWeight: FontWeight.w600,
),
style: TextStyle(fontSize: 23, fontWeight: FontWeight.w600),
),
Text(
'App: ${authProvider.applicationVersion!.version}\n'
'Server: ${authProvider.serverVersion}',
),
Text('App: ${authProvider.applicationVersion!.version}\n'
'Server: ${authProvider.serverVersion}'),
],
),
],
@@ -163,7 +160,8 @@ class AboutPage extends StatelessWidget {
showLicensePage(
context: context,
applicationName: 'wger',
applicationVersion: 'App: ${authProvider.applicationVersion!.version}\n'
applicationVersion:
'App: ${authProvider.applicationVersion!.version}\n'
'Server: ${authProvider.serverVersion}',
applicationLegalese: '\u{a9} 2020 - 2021 contributors',
applicationIcon: Padding(

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/auth.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/providers/gallery.dart';
@@ -50,9 +50,7 @@ class MainAppBar extends StatelessWidget implements PreferredSizeWidget {
title: Text(AppLocalizations.of(context).optionsLabel),
actions: [
TextButton(
child: Text(
MaterialLocalizations.of(context).closeButtonLabel,
),
child: Text(MaterialLocalizations.of(context).closeButtonLabel),
onPressed: () => Navigator.of(context).pop(),
),
],
@@ -69,9 +67,7 @@ class MainAppBar extends StatelessWidget implements PreferredSizeWidget {
FormScreen.routeName,
arguments: FormScreenArguments(
AppLocalizations.of(context).userProfile,
UserProfileForm(
context.read<UserProvider>().profile!,
),
UserProfileForm(context.read<UserProvider>().profile!),
),
),
),

View File

@@ -18,8 +18,8 @@
//import 'package:drift/drift.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/nutrition.dart';
@@ -34,9 +34,7 @@ class SettingsPage extends StatelessWidget {
final nutritionProvider = Provider.of<NutritionPlansProvider>(context, listen: false);
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context).settingsTitle),
),
appBar: AppBar(title: Text(AppLocalizations.of(context).settingsTitle)),
body: ListView(
children: [
ListTile(

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
class TextPrompt extends StatelessWidget {
const TextPrompt();

View File

@@ -17,12 +17,12 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/helpers/json.dart';
import 'package:wger/helpers/misc.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/session.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/providers/measurement.dart';
@@ -31,12 +31,7 @@ import 'package:wger/providers/workout_plans.dart';
import 'package:wger/theme/theme.dart';
/// Types of events
enum EventType {
weight,
measurement,
session,
caloriesDiary,
}
enum EventType { weight, measurement, session, caloriesDiary }
/// An event in the dashboard calendar
class Event {
@@ -84,8 +79,10 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
void loadEvents() async {
// Process weight entries
final BodyWeightProvider weightProvider =
Provider.of<BodyWeightProvider>(context, listen: false);
final BodyWeightProvider weightProvider = Provider.of<BodyWeightProvider>(
context,
listen: false,
);
for (final entry in weightProvider.items) {
final date = DateFormatLists.format(entry.date);
@@ -98,8 +95,10 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
}
// Process measurements
final MeasurementProvider measurementProvider =
Provider.of<MeasurementProvider>(context, listen: false);
final MeasurementProvider measurementProvider = Provider.of<MeasurementProvider>(
context,
listen: false,
);
for (final category in measurementProvider.categories) {
for (final entry in category.entries) {
final date = DateFormatLists.format(entry.date);
@@ -108,10 +107,9 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
_events[date] = [];
}
_events[date]!.add(Event(
EventType.measurement,
'${category.name}: ${entry.value} ${category.unit}',
));
_events[date]!.add(
Event(EventType.measurement, '${category.name}: ${entry.value} ${category.unit}'),
);
}
}
@@ -128,16 +126,20 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
time = '(${timeToString(session.timeStart)} - ${timeToString(session.timeEnd)})';
// Add events to lists
_events[date]!.add(Event(
EventType.session,
'${AppLocalizations.of(context).impression}: ${session.impressionAsString} $time',
));
_events[date]!.add(
Event(
EventType.session,
'${AppLocalizations.of(context).impression}: ${session.impressionAsString} $time',
),
);
}
});
// Process nutritional plans
final NutritionPlansProvider nutritionProvider =
Provider.of<NutritionPlansProvider>(context, listen: false);
final NutritionPlansProvider nutritionProvider = Provider.of<NutritionPlansProvider>(
context,
listen: false,
);
for (final plan in nutritionProvider.items) {
for (final entry in plan.logEntriesValues.entries) {
final date = DateFormatLists.format(entry.key);
@@ -146,10 +148,9 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
}
// Add events to lists
_events[date]!.add(Event(
EventType.caloriesDiary,
'${entry.value.energy.toStringAsFixed(0)} kcal',
));
_events[date]!.add(
Event(EventType.caloriesDiary, '${entry.value.energy.toStringAsFixed(0)} kcal'),
);
}
}
@@ -247,8 +248,10 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
valueListenable: _selectedEvents,
builder: (context, value, _) => Column(
children: [
...value.map((event) => ListTile(
title: Text((() {
...value.map(
(event) => ListTile(
title: Text(
(() {
switch (event.type) {
case EventType.caloriesDiary:
return AppLocalizations.of(context).nutritionalDiary;
@@ -262,10 +265,12 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
case EventType.measurement:
return AppLocalizations.of(context).measurement;
}
})()),
subtitle: Text(event.description),
//onTap: () => print('$event tapped!'),
)),
})(),
),
subtitle: Text(event.description),
//onTap: () => print('$event tapped!'),
),
),
],
),
),

View File

@@ -20,11 +20,11 @@ import 'dart:async';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_svg_icons/flutter_svg_icons.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/models/workouts/workout_plan.dart';
import 'package:wger/providers/body_weight.dart';
@@ -66,8 +66,10 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
@override
void initState() {
super.initState();
final stream =
Provider.of<NutritionPlansProvider>(context, listen: false).watchNutritionPlanLast();
final stream = Provider.of<NutritionPlansProvider>(
context,
listen: false,
).watchNutritionPlanLast();
_subscription = stream.listen((plan) {
if (!context.mounted) {
return;
@@ -97,8 +99,9 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
),
subtitle: Text(
_hasContent
? DateFormat.yMd(Localizations.localeOf(context).languageCode)
.format(_plan!.creationDate)
? DateFormat.yMd(
Localizations.localeOf(context).languageCode,
).format(_plan!.creationDate)
: '',
),
leading: Icon(
@@ -127,17 +130,14 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
TextButton(
child: Text(AppLocalizations.of(context).goToDetailPage),
onPressed: () {
Navigator.of(context).pushNamed(
NutritionalPlanScreen.routeName,
arguments: _plan!.id,
);
Navigator.of(
context,
).pushNamed(NutritionalPlanScreen.routeName, arguments: _plan!.id);
},
),
Expanded(child: Container()),
IconButton(
icon: const SvgIcon(
icon: SvgIconData('assets/icons/ingredient-diary.svg'),
),
icon: const SvgIcon(icon: SvgIconData('assets/icons/ingredient-diary.svg')),
tooltip: AppLocalizations.of(context).logIngredient,
onPressed: () {
Navigator.pushNamed(
@@ -152,9 +152,7 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
},
),
IconButton(
icon: const SvgIcon(
icon: SvgIconData('assets/icons/meal-diary.svg'),
),
icon: const SvgIcon(icon: SvgIconData('assets/icons/meal-diary.svg')),
tooltip: AppLocalizations.of(context).logMeal,
onPressed: () {
Navigator.of(context).pushNamed(LogMealsScreen.routeName, arguments: _plan);
@@ -223,9 +221,7 @@ class _DashboardWeightWidgetState extends State<DashboardWeightWidget> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TextButton(
child: Text(
AppLocalizations.of(context).goToDetailPage,
),
child: Text(AppLocalizations.of(context).goToDetailPage),
onPressed: () {
Navigator.of(context).pushNamed(WeightScreen.routeName);
},
@@ -238,9 +234,12 @@ class _DashboardWeightWidgetState extends State<DashboardWeightWidget> {
FormScreen.routeName,
arguments: FormScreenArguments(
AppLocalizations.of(context).newEntry,
WeightForm(weightProvider
.getNewestEntry()
?.copyWith(id: null, date: DateTime.now())),
WeightForm(
weightProvider.getNewestEntry()?.copyWith(
id: null,
date: DateTime.now(),
),
),
),
);
},
@@ -279,8 +278,9 @@ class _DashboardMeasurementWidgetState extends State<DashboardMeasurementWidget>
Widget build(BuildContext context) {
final provider = Provider.of<MeasurementProvider>(context, listen: false);
final items =
provider.categories.map<Widget>((item) => CategoriesCard(item, elevation: 0)).toList();
final items = provider.categories
.map<Widget>((item) => CategoriesCard(item, elevation: 0))
.toList();
if (items.isNotEmpty) {
items.add(
NothingFound(
@@ -309,10 +309,8 @@ class _DashboardMeasurementWidgetState extends State<DashboardMeasurementWidget>
// maybe we should just add a "Go to all" at the bottom of the widget
trailing: IconButton(
icon: const Icon(Icons.arrow_forward),
onPressed: () => Navigator.pushNamed(
context,
MeasurementCategoriesScreen.routeName,
),
onPressed: () =>
Navigator.pushNamed(context, MeasurementCategoriesScreen.routeName),
),
),
Column(
@@ -346,16 +344,11 @@ class _DashboardMeasurementWidgetState extends State<DashboardMeasurementWidget>
child: Container(
width: 12.0,
height: 12.0,
margin: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 4.0,
),
margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color:
Theme.of(context).textTheme.headlineSmall!.color!.withOpacity(
_current == entry.key ? 0.9 : 0.4,
),
color: Theme.of(context).textTheme.headlineSmall!.color!
.withOpacity(_current == entry.key ? 0.9 : 0.4),
),
),
);
@@ -407,61 +400,63 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
}
for (final day in _workoutPlan!.days) {
out.add(SizedBox(
width: double.infinity,
child: Row(
children: [
Expanded(
child: Text(
day.description,
style: const TextStyle(fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
),
),
Expanded(
child: MutedText(day.getDaysText, textAlign: TextAlign.right),
),
IconButton(
icon: const Icon(Icons.play_arrow),
color: wgerPrimaryButtonColor,
onPressed: () {
Navigator.of(context).pushNamed(GymModeScreen.routeName, arguments: day);
},
),
],
),
));
for (final set in day.sets) {
out.add(SizedBox(
out.add(
SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
child: Row(
children: [
...set.settingsFiltered.map((s) {
return _showDetail
? Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(s.exerciseObj
.getExercise(Localizations.localeOf(context).languageCode)
.name),
const SizedBox(width: 10),
MutedText(
set.getSmartRepr(s.exerciseObj).join('\n'),
),
],
),
const SizedBox(height: 10),
],
)
: Container();
}),
Expanded(
child: Text(
day.description,
style: const TextStyle(fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
),
),
Expanded(child: MutedText(day.getDaysText, textAlign: TextAlign.right)),
IconButton(
icon: const Icon(Icons.play_arrow),
color: wgerPrimaryButtonColor,
onPressed: () {
Navigator.of(context).pushNamed(GymModeScreen.routeName, arguments: day);
},
),
],
),
));
),
);
for (final set in day.sets) {
out.add(
SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
...set.settingsFiltered.map((s) {
return _showDetail
? Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
s.exerciseObj
.getExercise(Localizations.localeOf(context).languageCode)
.name,
),
const SizedBox(width: 10),
MutedText(set.getSmartRepr(s.exerciseObj).join('\n')),
],
),
const SizedBox(height: 10),
],
)
: Container();
}),
],
),
),
);
}
out.add(const Divider());
}
@@ -481,8 +476,9 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
),
subtitle: Text(
_hasContent
? DateFormat.yMd(Localizations.localeOf(context).languageCode)
.format(_workoutPlan!.creationDate)
? DateFormat.yMd(
Localizations.localeOf(context).languageCode,
).format(_workoutPlan!.creationDate)
: '',
),
leading: Icon(
@@ -519,10 +515,9 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
TextButton(
child: Text(AppLocalizations.of(context).goToDetailPage),
onPressed: () {
Navigator.of(context).pushNamed(
WorkoutPlanScreen.routeName,
arguments: _workoutPlan,
);
Navigator.of(
context,
).pushNamed(WorkoutPlanScreen.routeName, arguments: _workoutPlan);
},
),
],
@@ -555,11 +550,7 @@ class NothingFound extends StatelessWidget {
Navigator.pushNamed(
context,
FormScreen.routeName,
arguments: FormScreenArguments(
_titleForm,
hasListView: true,
_form,
),
arguments: FormScreenArguments(_titleForm, hasListView: true, _form),
);
},
),

View File

@@ -17,13 +17,13 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/helpers/i18n.dart';
import 'package:wger/helpers/platform.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/exercises/muscle.dart';
import 'package:wger/models/exercises/translation.dart';
@@ -83,18 +83,20 @@ class ExerciseDetail extends StatelessWidget {
return out;
}
out.add(Text(
AppLocalizations.of(context).variations,
style: Theme.of(context).textTheme.headlineSmall,
));
out.add(
Text(
AppLocalizations.of(context).variations,
style: Theme.of(context).textTheme.headlineSmall,
),
);
Provider.of<ExercisesProvider>(context, listen: false)
.findExercisesByVariationId(
_exerciseBase.variationId!,
exerciseBaseIdToExclude: _exerciseBase.id,
)
_exerciseBase.variationId!,
exerciseBaseIdToExclude: _exerciseBase.id,
)
.forEach((element) {
out.add(ExerciseListTile(exerciseBase: element));
});
out.add(ExerciseListTile(exerciseBase: element));
});
out.add(const SizedBox(height: PADDING));
return out;
@@ -103,10 +105,9 @@ class ExerciseDetail extends StatelessWidget {
List<Widget> getNotes(BuildContext context) {
final List<Widget> out = [];
if (_exercise.notes.isNotEmpty) {
out.add(Text(
AppLocalizations.of(context).notes,
style: Theme.of(context).textTheme.headlineSmall,
));
out.add(
Text(AppLocalizations.of(context).notes, style: Theme.of(context).textTheme.headlineSmall),
);
for (final e in _exercise.notes) {
out.add(Text(e.comment));
}
@@ -118,36 +119,37 @@ class ExerciseDetail extends StatelessWidget {
List<Widget> getMuscles(BuildContext context) {
final List<Widget> out = [];
out.add(Text(
AppLocalizations.of(context).muscles,
style: Theme.of(context).textTheme.headlineSmall,
));
out.add(Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: PADDING),
child: MuscleWidget(
muscles: _exerciseBase.muscles,
musclesSecondary: _exerciseBase.musclesSecondary,
isFront: true,
out.add(
Text(AppLocalizations.of(context).muscles, style: Theme.of(context).textTheme.headlineSmall),
);
out.add(
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: PADDING),
child: MuscleWidget(
muscles: _exerciseBase.muscles,
musclesSecondary: _exerciseBase.musclesSecondary,
isFront: true,
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: PADDING),
child: MuscleWidget(
muscles: _exerciseBase.muscles,
musclesSecondary: _exerciseBase.musclesSecondary,
isFront: false,
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: PADDING),
child: MuscleWidget(
muscles: _exerciseBase.muscles,
musclesSecondary: _exerciseBase.musclesSecondary,
isFront: false,
),
),
),
),
],
));
],
),
);
out.add(
Column(
@@ -176,10 +178,12 @@ class ExerciseDetail extends StatelessWidget {
List<Widget> getDescription(BuildContext context) {
final List<Widget> out = [];
out.add(Text(
AppLocalizations.of(context).description,
style: Theme.of(context).textTheme.headlineSmall,
));
out.add(
Text(
AppLocalizations.of(context).description,
style: Theme.of(context).textTheme.headlineSmall,
),
);
out.add(Html(data: _exercise.description));
return out;
@@ -212,14 +216,16 @@ class ExerciseDetail extends StatelessWidget {
);
if (_exerciseBase.equipment.isNotEmpty) {
_exerciseBase.equipment
.map((e) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Chip(
label: Text(getTranslation(e.name, context)),
padding: EdgeInsets.zero,
backgroundColor: theme.splashColor,
),
))
.map(
(e) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Chip(
label: Text(getTranslation(e.name, context)),
padding: EdgeInsets.zero,
backgroundColor: theme.splashColor,
),
),
)
.forEach((element) => out.add(element));
}
out.add(const SizedBox(height: PADDING));
@@ -242,11 +248,13 @@ class ExerciseDetail extends StatelessWidget {
List<Widget> getAliases(BuildContext context) {
final List<Widget> out = [];
if (_exercise.aliases.isNotEmpty) {
out.add(MutedText(
AppLocalizations.of(context).alsoKnownAs(
_exercise.aliases.map((e) => e.alias).toList().join(', '),
out.add(
MutedText(
AppLocalizations.of(
context,
).alsoKnownAs(_exercise.aliases.map((e) => e.alias).toList().join(', ')),
),
));
);
out.add(const SizedBox(height: PADDING));
}
@@ -284,10 +292,7 @@ class MuscleRowWidget extends StatelessWidget {
final List<Muscle> muscles;
final List<Muscle> musclesSecondary;
const MuscleRowWidget({
required this.muscles,
required this.musclesSecondary,
});
const MuscleRowWidget({required this.muscles, required this.musclesSecondary});
@override
Widget build(BuildContext context) {
@@ -342,9 +347,9 @@ class MuscleWidget extends StatelessWidget {
children: [
SvgPicture.asset('assets/images/muscles/$background.svg'),
...muscles.map((m) => SvgPicture.asset('assets/images/muscles/main/muscle-${m.id}.svg')),
...musclesSecondary.map((m) => SvgPicture.asset(
'assets/images/muscles/secondary/muscle-${m.id}.svg',
)),
...musclesSecondary.map(
(m) => SvgPicture.asset('assets/images/muscles/secondary/muscle-${m.id}.svg'),
),
],
);
}

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/screens/add_exercise_screen.dart';
@@ -59,9 +59,7 @@ class _FilterRowState extends State<FilterRow> {
decoration: InputDecoration(
hintText: '${AppLocalizations.of(context).exerciseName}...',
contentPadding: const EdgeInsets.symmetric(horizontal: 10),
border: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
border: const OutlineInputBorder(borderSide: BorderSide(color: Colors.black)),
),
),
),

View File

@@ -19,11 +19,11 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/helpers/json.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/gallery/image.dart' as gallery;
import 'package:wger/providers/gallery.dart';
@@ -126,9 +126,7 @@ class _ImageFormState extends State<ImageForm> {
_showPicker(ImageSource.gallery);
},
leading: const Icon(Icons.photo_library),
title: Text(
AppLocalizations.of(context).chooseFromLibrary,
),
title: Text(AppLocalizations.of(context).chooseFromLibrary),
),
],
),
@@ -174,9 +172,7 @@ class _ImageFormState extends State<ImageForm> {
),
TextFormField(
key: const Key('field-description'),
decoration: InputDecoration(
labelText: AppLocalizations.of(context).description,
),
decoration: InputDecoration(labelText: AppLocalizations.of(context).description),
minLines: 3,
maxLines: 10,
controller: descriptionController,
@@ -196,12 +192,16 @@ class _ImageFormState extends State<ImageForm> {
_form.currentState!.save();
if (widget._image.id == null) {
Provider.of<GalleryProvider>(context, listen: false)
.addImage(widget._image, _file!);
Provider.of<GalleryProvider>(
context,
listen: false,
).addImage(widget._image, _file!);
Navigator.of(context).pop();
} else {
Provider.of<GalleryProvider>(context, listen: false)
.editImage(widget._image, _file);
Provider.of<GalleryProvider>(
context,
listen: false,
).editImage(widget._image, _file);
Navigator.of(context).pop();
}
},

View File

@@ -17,11 +17,11 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/platform.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/gallery.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/widgets/core/text_prompt.dart';
@@ -58,13 +58,12 @@ class Gallery extends StatelessWidget {
child: Column(
children: [
Text(
DateFormat.yMd(Localizations.localeOf(context).languageCode)
.format(currentImage.date),
DateFormat.yMd(
Localizations.localeOf(context).languageCode,
).format(currentImage.date),
style: Theme.of(context).textTheme.headlineSmall,
),
Expanded(
child: Image.network(currentImage.url!),
),
Expanded(child: Image.network(currentImage.url!)),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Text(currentImage.description),

View File

@@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/models/measurements/measurement_category.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/screens/measurement_entries_screen.dart';
import 'package:wger/widgets/measurements/helpers.dart';
import 'charts.dart';
import 'forms.dart';
@@ -26,19 +26,12 @@ class CategoriesCard extends StatelessWidget {
children: [
Padding(
padding: const EdgeInsets.only(top: 5),
child: Text(
currentCategory.name,
style: Theme.of(context).textTheme.titleLarge,
),
child: Text(currentCategory.name, style: Theme.of(context).textTheme.titleLarge),
),
Container(
padding: const EdgeInsets.all(10),
height: 220,
child: MeasurementChartWidgetFl(
entriesAll,
currentCategory.unit,
avgs: entries7dAvg,
),
child: MeasurementChartWidgetFl(entriesAll, currentCategory.unit, avgs: entries7dAvg),
),
if (entries7dAvg.isNotEmpty)
MeasurementOverallChangeWidget(

View File

@@ -18,9 +18,9 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:wger/helpers/charts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
class MeasurementOverallChangeWidget extends StatelessWidget {
final MeasurementChartEntry _first;
@@ -34,8 +34,8 @@ class MeasurementOverallChangeWidget extends StatelessWidget {
final prefix = delta > 0
? '+'
: delta < 0
? '-'
: '';
? '-'
: '';
return Text('overall change $prefix ${delta.abs().toStringAsFixed(1)} $_unit');
}
@@ -61,10 +61,7 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 1.70,
child: Padding(
padding: const EdgeInsets.all(4),
child: LineChart(mainData()),
),
child: Padding(padding: const EdgeInsets.all(4), child: LineChart(mainData())),
);
}
@@ -75,15 +72,13 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
getTooltipItems: (touchedSpots) {
return touchedSpots.map((touchedSpot) {
final DateTime date = DateTime.fromMillisecondsSinceEpoch(touchedSpot.x.toInt());
final dateStr =
DateFormat.Md(Localizations.localeOf(context).languageCode).format(date);
final dateStr = DateFormat.Md(
Localizations.localeOf(context).languageCode,
).format(date);
return LineTooltipItem(
'$dateStr: ${touchedSpot.y.toStringAsFixed(1)} ${widget._unit}',
TextStyle(
color: touchedSpot.bar.color,
fontWeight: FontWeight.bold,
),
TextStyle(color: touchedSpot.bar.color, fontWeight: FontWeight.bold),
);
}).toList();
},
@@ -108,12 +103,8 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
),
titlesData: FlTitlesData(
show: true,
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
@@ -132,15 +123,10 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
DateFormat.yMd(Localizations.localeOf(context).languageCode).format(date),
);
}
return Text(
DateFormat.Md(Localizations.localeOf(context).languageCode).format(date),
);
return Text(DateFormat.Md(Localizations.localeOf(context).languageCode).format(date));
},
interval: widget._entries.isNotEmpty
? chartGetInterval(
widget._entries.last.date,
widget._entries.first.date,
)
? chartGetInterval(widget._entries.last.date, widget._entries.first.date)
: 1000,
),
),
@@ -168,10 +154,7 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
lineBarsData: [
LineChartBarData(
spots: widget._entries
.map((e) => FlSpot(
e.date.millisecondsSinceEpoch.toDouble(),
e.value.toDouble(),
))
.map((e) => FlSpot(e.date.millisecondsSinceEpoch.toDouble(), e.value.toDouble()))
.toList(),
isCurved: false,
color: Theme.of(context).colorScheme.primary,
@@ -182,10 +165,7 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
if (widget.avgs != null)
LineChartBarData(
spots: widget.avgs!
.map((e) => FlSpot(
e.date.millisecondsSinceEpoch.toDouble(),
e.value.toDouble(),
))
.map((e) => FlSpot(e.date.millisecondsSinceEpoch.toDouble(), e.value.toDouble()))
.toList(),
isCurved: false,
color: Theme.of(context).colorScheme.tertiary,

View File

@@ -17,9 +17,9 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/measurements/measurement_category.dart';
import 'package:wger/providers/measurement.dart';
import 'package:wger/providers/nutrition.dart';
@@ -38,82 +38,80 @@ class EntriesList extends StatelessWidget {
Widget build(BuildContext context) {
final plan = Provider.of<NutritionPlansProvider>(context, listen: false).currentPlan;
final entriesAll =
_category.entries.map((e) => MeasurementChartEntry(e.value, e.date)).toList();
final entriesAll = _category.entries
.map((e) => MeasurementChartEntry(e.value, e.date))
.toList();
final entries7dAvg = moving7dAverage(entriesAll);
return Column(children: [
...getOverviewWidgetsSeries(
_category.name,
entriesAll,
entries7dAvg,
plan,
_category.unit,
context,
),
SizedBox(
height: 300,
child: ListView.builder(
padding: const EdgeInsets.all(10.0),
itemCount: _category.entries.length,
itemBuilder: (context, index) {
final currentEntry = _category.entries[index];
final provider = Provider.of<MeasurementProvider>(context, listen: false);
return Column(
children: [
...getOverviewWidgetsSeries(
_category.name,
entriesAll,
entries7dAvg,
plan,
_category.unit,
context,
),
SizedBox(
height: 300,
child: ListView.builder(
padding: const EdgeInsets.all(10.0),
itemCount: _category.entries.length,
itemBuilder: (context, index) {
final currentEntry = _category.entries[index];
final provider = Provider.of<MeasurementProvider>(context, listen: false);
return Card(
child: ListTile(
title: Text('${currentEntry.value} ${_category.unit}'),
subtitle: Text(
DateFormat.yMd(Localizations.localeOf(context).languageCode)
.format(currentEntry.date),
),
trailing: PopupMenuButton(
itemBuilder: (BuildContext context) {
return [
PopupMenuItem(
child: Text(AppLocalizations.of(context).edit),
onTap: () => Navigator.pushNamed(
context,
FormScreen.routeName,
arguments: FormScreenArguments(
AppLocalizations.of(context).edit,
MeasurementEntryForm(
currentEntry.category,
currentEntry,
return Card(
child: ListTile(
title: Text('${currentEntry.value} ${_category.unit}'),
subtitle: Text(
DateFormat.yMd(
Localizations.localeOf(context).languageCode,
).format(currentEntry.date),
),
trailing: PopupMenuButton(
itemBuilder: (BuildContext context) {
return [
PopupMenuItem(
child: Text(AppLocalizations.of(context).edit),
onTap: () => Navigator.pushNamed(
context,
FormScreen.routeName,
arguments: FormScreenArguments(
AppLocalizations.of(context).edit,
MeasurementEntryForm(currentEntry.category, currentEntry),
),
),
),
),
PopupMenuItem(
child: Text(AppLocalizations.of(context).delete),
onTap: () async {
// Delete entry from DB
await provider.deleteEntry(
currentEntry.id!,
currentEntry.category,
);
PopupMenuItem(
child: Text(AppLocalizations.of(context).delete),
onTap: () async {
// Delete entry from DB
await provider.deleteEntry(currentEntry.id!, currentEntry.category);
// and inform the user
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context).successfullyDeleted,
textAlign: TextAlign.center,
// and inform the user
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context).successfullyDeleted,
textAlign: TextAlign.center,
),
),
),
);
}
},
),
];
},
);
}
},
),
];
},
),
),
),
);
},
);
},
),
),
),
]);
],
);
}
}

View File

@@ -17,11 +17,11 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/exceptions/http_exception.dart';
import 'package:wger/helpers/json.dart';
import 'package:wger/helpers/ui.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/measurements/measurement_category.dart';
import 'package:wger/models/measurements/measurement_entry.dart';
import 'package:wger/providers/measurement.dart';
@@ -31,11 +31,7 @@ class MeasurementCategoryForm extends StatelessWidget {
final nameController = TextEditingController();
final unitController = TextEditingController();
final Map<String, dynamic> categoryData = {
'id': null,
'name': '',
'unit': '',
};
final Map<String, dynamic> categoryData = {'id': null, 'name': '', 'unit': ''};
MeasurementCategoryForm([MeasurementCategory? category]) {
//this._category = category ?? MeasurementCategory();
@@ -103,20 +99,14 @@ class MeasurementCategoryForm extends StatelessWidget {
// Save the entry on the server
try {
categoryData['id'] == null
? await Provider.of<MeasurementProvider>(
context,
listen: false,
).addCategory(
? await Provider.of<MeasurementProvider>(context, listen: false).addCategory(
MeasurementCategory(
id: categoryData['id'],
name: categoryData['name'],
unit: categoryData['unit'],
),
)
: await Provider.of<MeasurementProvider>(
context,
listen: false,
).editCategory(
: await Provider.of<MeasurementProvider>(context, listen: false).editCategory(
categoryData['id'],
categoryData['name'],
categoryData['unit'],
@@ -274,20 +264,16 @@ class MeasurementEntryForm extends StatelessWidget {
// Save the entry on the server
try {
_entryData['id'] == null
? await Provider.of<MeasurementProvider>(
context,
listen: false,
).addEntry(MeasurementEntry(
id: _entryData['id'],
category: _entryData['category'],
date: _entryData['date'],
value: _entryData['value'],
notes: _entryData['notes'],
))
: await Provider.of<MeasurementProvider>(
context,
listen: false,
).editEntry(
? await Provider.of<MeasurementProvider>(context, listen: false).addEntry(
MeasurementEntry(
id: _entryData['id'],
category: _entryData['category'],
date: _entryData['date'],
value: _entryData['value'],
notes: _entryData['notes'],
),
)
: await Provider.of<MeasurementProvider>(context, listen: false).editEntry(
_entryData['id'],
_entryData['category'],
_entryData['value'],

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/widgets/measurements/charts.dart';
@@ -11,11 +11,7 @@ List<Widget> getOverviewWidgets(
BuildContext context,
) {
return [
Text(
title,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
),
Text(title, textAlign: TextAlign.center, style: Theme.of(context).textTheme.titleLarge),
Container(
padding: const EdgeInsets.all(15),
height: 220,

View File

@@ -20,8 +20,8 @@ import 'dart:math';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/helpers/colors.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/models/nutrition/nutritional_values.dart';
import 'package:wger/widgets/measurements/charts.dart';
@@ -34,10 +34,8 @@ import 'package:wger/widgets/measurements/charts.dart';
// * here we draw our own simple gauges that can go beyond 100%,
// and support multiple segments
class FlNutritionalPlanGoalWidget extends StatelessWidget {
const FlNutritionalPlanGoalWidget({
super.key,
required NutritionalPlan nutritionalPlan,
}) : _nutritionalPlan = nutritionalPlan;
const FlNutritionalPlanGoalWidget({super.key, required NutritionalPlan nutritionalPlan})
: _nutritionalPlan = nutritionalPlan;
final NutritionalPlan _nutritionalPlan;
@@ -47,20 +45,12 @@ class FlNutritionalPlanGoalWidget extends StatelessWidget {
// why don't we just handle this inside this function? because it might be
// *another* gauge that's in surplus and we want to have consistent widths
// between all gauges
Widget _diyGauge(
BuildContext context,
double normWidth,
double? plan,
double val,
) {
Widget _diyGauge(BuildContext context, double normWidth, double? plan, double val) {
Container segment(double width, Color color) {
return Container(
height: 16,
width: width,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(15.0),
),
decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(15.0)),
);
}
@@ -71,17 +61,21 @@ class FlNutritionalPlanGoalWidget extends StatelessWidget {
// paint a surplus
if (val > plan) {
return Stack(children: [
segment(normWidth * val / plan, COLOR_SURPLUS),
segment(normWidth, LIST_OF_COLORS8[0]),
]);
return Stack(
children: [
segment(normWidth * val / plan, COLOR_SURPLUS),
segment(normWidth, LIST_OF_COLORS8[0]),
],
);
}
// paint a deficit
return Stack(children: [
segment(normWidth, Theme.of(context).colorScheme.surface),
segment(normWidth * val / plan, LIST_OF_COLORS8[0]),
]);
return Stack(
children: [
segment(normWidth, Theme.of(context).colorScheme.surface),
segment(normWidth * val / plan, LIST_OF_COLORS8[0]),
],
);
}
@override
@@ -90,87 +84,97 @@ class FlNutritionalPlanGoalWidget extends StatelessWidget {
final goals = plan.nutritionalGoals;
final today = plan.loggedNutritionalValuesToday;
return LayoutBuilder(builder: (context, constraints) {
// if any of the bars goes over 100%, find the one that goes over the most
// that one needs the most horizontal space to show how much it goes over,
// and therefore reduces the width of "100%" the most, and this width we want
// to be consistent for all other bars.
// if none goes over, 100% means fill all available space
final maxVal = [
1.0,
if (goals.energy != null && goals.energy! > 0) today.energy / goals.energy!,
if (goals.protein != null && goals.protein! > 0) today.protein / goals.protein!,
if (goals.carbohydrates != null && goals.carbohydrates! > 0)
today.carbohydrates / goals.carbohydrates!,
if (goals.fat != null && goals.fat! > 0) today.fat / goals.fat!,
if (goals.fiber != null && goals.fiber! > 0) today.fiber / goals.fiber!,
].reduce(max);
return LayoutBuilder(
builder: (context, constraints) {
// if any of the bars goes over 100%, find the one that goes over the most
// that one needs the most horizontal space to show how much it goes over,
// and therefore reduces the width of "100%" the most, and this width we want
// to be consistent for all other bars.
// if none goes over, 100% means fill all available space
final maxVal = [
1.0,
if (goals.energy != null && goals.energy! > 0) today.energy / goals.energy!,
if (goals.protein != null && goals.protein! > 0) today.protein / goals.protein!,
if (goals.carbohydrates != null && goals.carbohydrates! > 0)
today.carbohydrates / goals.carbohydrates!,
if (goals.fat != null && goals.fat! > 0) today.fat / goals.fat!,
if (goals.fiber != null && goals.fiber! > 0) today.fiber / goals.fiber!,
].reduce(max);
final normWidth = constraints.maxWidth / maxVal;
final normWidth = constraints.maxWidth / maxVal;
String fmtMacro(String name, double today, double? goal, String unit) {
return '$name: ${today.toStringAsFixed(0)}${goal == null ? '' : ' / ${goal.toStringAsFixed(0)}'} $unit';
}
String fmtMacro(String name, double today, double? goal, String unit) {
return '$name: ${today.toStringAsFixed(0)}${goal == null ? '' : ' / ${goal.toStringAsFixed(0)}'} $unit';
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(fmtMacro(
AppLocalizations.of(context).energy,
today.energy,
goals.energy,
AppLocalizations.of(context).kcal,
)),
const SizedBox(height: 2),
_diyGauge(context, normWidth, goals.energy, today.energy),
const SizedBox(height: 8),
Text(fmtMacro(
AppLocalizations.of(context).protein,
today.protein,
goals.protein,
AppLocalizations.of(context).g,
)),
const SizedBox(height: 2),
_diyGauge(context, normWidth, goals.protein, today.protein),
const SizedBox(height: 8),
Text(fmtMacro(
AppLocalizations.of(context).carbohydrates,
today.carbohydrates,
goals.carbohydrates,
AppLocalizations.of(context).g,
)),
const SizedBox(height: 2),
_diyGauge(
context,
normWidth,
goals.carbohydrates,
today.carbohydrates,
),
const SizedBox(height: 8),
Text(fmtMacro(
AppLocalizations.of(context).fat,
today.fat,
goals.fat,
AppLocalizations.of(context).g,
)),
const SizedBox(height: 2),
_diyGauge(context, normWidth, goals.fat, today.fat),
// optionally display the advanced macro goals:
if (goals.fiber != null)
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
const SizedBox(height: 8),
Text(fmtMacro(
AppLocalizations.of(context).fiber,
today.fiber,
goals.fiber,
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
fmtMacro(
AppLocalizations.of(context).energy,
today.energy,
goals.energy,
AppLocalizations.of(context).kcal,
),
),
const SizedBox(height: 2),
_diyGauge(context, normWidth, goals.energy, today.energy),
const SizedBox(height: 8),
Text(
fmtMacro(
AppLocalizations.of(context).protein,
today.protein,
goals.protein,
AppLocalizations.of(context).g,
)),
const SizedBox(height: 2),
_diyGauge(context, normWidth, goals.fiber, today.fiber),
]),
],
);
});
),
),
const SizedBox(height: 2),
_diyGauge(context, normWidth, goals.protein, today.protein),
const SizedBox(height: 8),
Text(
fmtMacro(
AppLocalizations.of(context).carbohydrates,
today.carbohydrates,
goals.carbohydrates,
AppLocalizations.of(context).g,
),
),
const SizedBox(height: 2),
_diyGauge(context, normWidth, goals.carbohydrates, today.carbohydrates),
const SizedBox(height: 8),
Text(
fmtMacro(
AppLocalizations.of(context).fat,
today.fat,
goals.fat,
AppLocalizations.of(context).g,
),
),
const SizedBox(height: 2),
_diyGauge(context, normWidth, goals.fat, today.fat),
// optionally display the advanced macro goals:
if (goals.fiber != null)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 8),
Text(
fmtMacro(
AppLocalizations.of(context).fiber,
today.fiber,
goals.fiber,
AppLocalizations.of(context).g,
),
),
const SizedBox(height: 2),
_diyGauge(context, normWidth, goals.fiber, today.fiber),
],
),
],
);
},
);
}
}
@@ -227,16 +231,19 @@ class FlNutritionalPlanPieChartState extends State<FlNutritionalPlanPieChartWidg
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(AppLocalizations.of(context).protein, LIST_OF_COLORS3[1]),
(AppLocalizations.of(context).carbohydrates, LIST_OF_COLORS3[0]),
(AppLocalizations.of(context).fat, LIST_OF_COLORS3[2]),
]
.map((e) => Padding(
padding: const EdgeInsets.symmetric(vertical: 2),
child: Indicator(color: e.$2, text: e.$1, isSquare: true),
))
.toList(),
children:
[
(AppLocalizations.of(context).protein, LIST_OF_COLORS3[1]),
(AppLocalizations.of(context).carbohydrates, LIST_OF_COLORS3[0]),
(AppLocalizations.of(context).fat, LIST_OF_COLORS3[2]),
]
.map(
(e) => Padding(
padding: const EdgeInsets.symmetric(vertical: 2),
child: Indicator(color: e.$2, text: e.$1, isSquare: true),
),
)
.toList(),
),
const SizedBox(width: 28),
],
@@ -265,10 +272,8 @@ class FlNutritionalPlanPieChartState extends State<FlNutritionalPlanPieChartWidg
/// Shows results vs plan of common macros, for today and last 7 days, as barchart
class NutritionalDiaryChartWidgetFl extends StatefulWidget {
const NutritionalDiaryChartWidgetFl({
super.key,
required NutritionalPlan nutritionalPlan,
}) : _nutritionalPlan = nutritionalPlan;
const NutritionalDiaryChartWidgetFl({super.key, required NutritionalPlan nutritionalPlan})
: _nutritionalPlan = nutritionalPlan;
final NutritionalPlan _nutritionalPlan;
@@ -315,12 +320,7 @@ class NutritionalDiaryChartWidgetFlState extends State<NutritionalDiaryChartWidg
final [colorPlanned, colorLoggedToday, colorLogged7Day] = LIST_OF_COLORS3;
BarChartGroupData barchartGroup(
int x,
double barsSpace,
double barsWidth,
String prop,
) {
BarChartGroupData barchartGroup(int x, double barsSpace, double barsWidth, String prop) {
final plan = planned.prop(prop);
BarChartRodData barChartRodData(double? plan, double val, Color color) {
@@ -391,20 +391,14 @@ class NutritionalDiaryChartWidgetFlState extends State<NutritionalDiaryChartWidg
getTitlesWidget: leftTitles,
),
),
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
),
gridData: FlGridData(
show: true,
checkToShowHorizontalLine: (value) => value % 10 == 0,
getDrawingHorizontalLine: (value) => const FlLine(
color: Colors.black,
strokeWidth: 1,
),
getDrawingHorizontalLine: (value) =>
const FlLine(color: Colors.black, strokeWidth: 1),
drawVerticalLine: false,
),
borderData: FlBorderData(show: false),
@@ -412,12 +406,7 @@ class NutritionalDiaryChartWidgetFlState extends State<NutritionalDiaryChartWidg
barGroups: [
barchartGroup(0, barsSpace, barsWidth, 'protein'),
barchartGroup(1, barsSpace, barsWidth, 'carbohydrates'),
barchartGroup(
2,
barsSpace,
barsWidth,
'carbohydratesSugar',
),
barchartGroup(2, barsSpace, barsWidth, 'carbohydratesSugar'),
barchartGroup(3, barsSpace, barsWidth, 'fat'),
barchartGroup(4, barsSpace, barsWidth, 'fatSaturated'),
if (widget._nutritionalPlan.nutritionalGoals.fiber != null)
@@ -430,21 +419,17 @@ class NutritionalDiaryChartWidgetFlState extends State<NutritionalDiaryChartWidg
padding: const EdgeInsets.only(bottom: 40, left: 25, right: 25),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
(AppLocalizations.of(context).deficit, colorPlanned),
(AppLocalizations.of(context).surplus, COLOR_SURPLUS),
(AppLocalizations.of(context).today, colorLoggedToday),
(AppLocalizations.of(context).weekAverage, colorLogged7Day),
]
.map(
(e) => Indicator(
color: e.$2,
text: e.$1,
isSquare: true,
marginRight: 0,
),
)
.toList(),
children:
[
(AppLocalizations.of(context).deficit, colorPlanned),
(AppLocalizations.of(context).surplus, COLOR_SURPLUS),
(AppLocalizations.of(context).today, colorLoggedToday),
(AppLocalizations.of(context).weekAverage, colorLogged7Day),
]
.map(
(e) => Indicator(color: e.$2, text: e.$1, isSquare: true, marginRight: 0),
)
.toList(),
),
),
],
@@ -460,8 +445,8 @@ class MealDiaryBarChartWidget extends StatefulWidget {
super.key,
required NutritionalValues logged,
required NutritionalValues planned,
}) : _logged = logged,
_planned = planned;
}) : _logged = logged,
_planned = planned;
final NutritionalValues _logged;
final NutritionalValues _planned;
@@ -486,12 +471,12 @@ class MealDiaryBarChartWidgetState extends State<MealDiaryBarChartWidget> {
}
Widget leftTitles(double value, TitleMeta meta) => SideTitleWidget(
axisSide: meta.axisSide,
child: Text(
AppLocalizations.of(context).percentValue(value.toStringAsFixed(0)),
style: const TextStyle(fontSize: 10),
),
);
axisSide: meta.axisSide,
child: Text(
AppLocalizations.of(context).percentValue(value.toStringAsFixed(0)),
style: const TextStyle(fontSize: 10),
),
);
@override
Widget build(BuildContext context) {
@@ -523,19 +508,13 @@ class MealDiaryBarChartWidgetState extends State<MealDiaryBarChartWidget> {
getTitlesWidget: leftTitles,
),
),
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
),
gridData: FlGridData(
show: true,
getDrawingHorizontalLine: (value) => const FlLine(
color: Colors.black,
strokeWidth: 1,
),
getDrawingHorizontalLine: (value) =>
const FlLine(color: Colors.black, strokeWidth: 1),
drawVerticalLine: false,
),
borderData: FlBorderData(show: false),

View File

@@ -17,12 +17,12 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/exceptions/http_exception.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/helpers/json.dart';
import 'package:wger/helpers/ui.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/ingredient.dart';
import 'package:wger/models/nutrition/log.dart';
import 'package:wger/models/nutrition/meal.dart';
@@ -65,10 +65,7 @@ class MealForm extends StatelessWidget {
FocusScope.of(context).requestFocus(FocusNode());
// Open time picker
final pickedTime = await showTimePicker(
context: context,
initialTime: _meal.time!,
);
final pickedTime = await showTimePicker(context: context, initialTime: _meal.time!);
if (pickedTime != null) {
_timeController.text = timeToString(pickedTime)!;
}
@@ -101,10 +98,7 @@ class MealForm extends StatelessWidget {
context,
listen: false,
).addMeal(_meal, _planId)
: Provider.of<NutritionPlansProvider>(
context,
listen: false,
).editMeal(_meal);
: Provider.of<NutritionPlansProvider>(context, listen: false).editMeal(_meal);
} on WgerHttpException catch (error) {
showHttpExceptionErrorDialog(error, context);
} catch (error) {
@@ -120,12 +114,7 @@ class MealForm extends StatelessWidget {
}
}
Widget MealItemForm(
Meal meal,
List<MealItem> recent, [
String? barcode,
bool? test,
]) {
Widget MealItemForm(Meal meal, List<MealItem> recent, [String? barcode, bool? test]) {
return IngredientForm(
// TODO we use planId 0 here cause we don't have one and we don't need it I think?
recent: recent.map((e) => Log.fromMealItem(e, "0", e.mealId)).toList(),
@@ -143,14 +132,13 @@ Widget IngredientLogForm(NutritionalPlan plan) {
return IngredientForm(
recent: plan.dedupDiaryEntries,
onSave: (BuildContext context, MealItem mealItem, DateTime? dt) {
Provider.of<NutritionPlansProvider>(context, listen: false)
.logIngredientToDiary(mealItem, plan.id!, dt);
Provider.of<NutritionPlansProvider>(
context,
listen: false,
).logIngredientToDiary(mealItem, plan.id!, dt);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context).ingredientLogged,
textAlign: TextAlign.center,
),
content: Text(AppLocalizations.of(context).ingredientLogged, textAlign: TextAlign.center),
),
);
},
@@ -241,8 +229,9 @@ class IngredientFormState extends State<IngredientForm> {
Widget build(BuildContext context) {
final String unit = AppLocalizations.of(context).g;
final queryLower = _searchQuery.toLowerCase();
final suggestions =
widget.recent.where((e) => e.ingredient.name.toLowerCase().contains(queryLower)).toList();
final suggestions = widget.recent
.where((e) => e.ingredient.name.toLowerCase().contains(queryLower))
.toList();
return Container(
margin: const EdgeInsets.all(20),
child: Form(
@@ -263,9 +252,7 @@ class IngredientFormState extends State<IngredientForm> {
Expanded(
child: TextFormField(
key: const Key('field-weight'), // needed ?
decoration: InputDecoration(
labelText: AppLocalizations.of(context).weight,
),
decoration: InputDecoration(labelText: AppLocalizations.of(context).weight),
controller: _amountController,
keyboardType: TextInputType.number,
onChanged: (value) {
@@ -361,10 +348,7 @@ class IngredientFormState extends State<IngredientForm> {
context,
listen: false,
).fetchIngredient(_mealItem.ingredientId),
builder: (
BuildContext context,
AsyncSnapshot<Ingredient> snapshot,
) {
builder: (BuildContext context, AsyncSnapshot<Ingredient> snapshot) {
if (snapshot.hasData) {
_mealItem.ingredient = snapshot.data!;
return MealItemValuesTile(
@@ -403,13 +387,7 @@ class IngredientFormState extends State<IngredientForm> {
try {
var date = DateTime.parse(_dateController.text);
final tod = stringToTime(_timeController.text);
date = DateTime(
date.year,
date.month,
date.day,
tod.hour,
tod.minute,
);
date = DateTime(date.year, date.month, date.day, tod.hour, tod.minute);
widget.onSave(context, _mealItem, date);
} on WgerHttpException catch (error) {
showHttpExceptionErrorDialog(error, context);
@@ -431,11 +409,7 @@ class IngredientFormState extends State<IngredientForm> {
itemBuilder: (context, index) {
void select() {
final ingredient = suggestions[index].ingredient;
selectIngredient(
ingredient.id,
ingredient.name,
suggestions[index].amount,
);
selectIngredient(ingredient.id, ingredient.name, suggestions[index].amount);
}
return Card(
@@ -444,10 +418,12 @@ class IngredientFormState extends State<IngredientForm> {
title: Text(
'${suggestions[index].ingredient.name} (${suggestions[index].amount.toStringAsFixed(0)}$unit)',
),
subtitle: Text(getShortNutritionValues(
suggestions[index].ingredient.nutritionalValues,
context,
)),
subtitle: Text(
getShortNutritionValues(
suggestions[index].ingredient.nutritionalValues,
context,
),
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
@@ -539,9 +515,7 @@ class _PlanFormState extends State<PlanForm> {
// Description
TextFormField(
key: const Key('field-description'),
decoration: InputDecoration(
labelText: AppLocalizations.of(context).description,
),
decoration: InputDecoration(labelText: AppLocalizations.of(context).description),
controller: _descriptionController,
onSaved: (newValue) {
widget._plan.description = newValue!;
@@ -569,12 +543,7 @@ class _PlanFormState extends State<PlanForm> {
child: DropdownButtonFormField<GoalType>(
value: _goalType,
items: GoalType.values
.map(
(e) => DropdownMenuItem<GoalType>(
value: e,
child: Text(e.label),
),
)
.map((e) => DropdownMenuItem<GoalType>(value: e, child: Text(e.label)))
.toList(),
onChanged: (GoalType? g) {
setState(() {

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/ingredient.dart';
import 'package:wger/models/nutrition/meal.dart';
import 'package:wger/models/nutrition/nutritional_values.dart';
@@ -27,18 +27,18 @@ import 'package:wger/widgets/core/core.dart';
import 'package:wger/widgets/nutrition/ingredient_dialogs.dart';
List<String> getNutritionColumnNames(BuildContext context) => [
AppLocalizations.of(context).energy,
AppLocalizations.of(context).protein,
AppLocalizations.of(context).carbohydrates,
AppLocalizations.of(context).fat,
];
AppLocalizations.of(context).energy,
AppLocalizations.of(context).protein,
AppLocalizations.of(context).carbohydrates,
AppLocalizations.of(context).fat,
];
List<String> getNutritionalValues(NutritionalValues values, BuildContext context) => [
AppLocalizations.of(context).kcalValue(values.energy.toStringAsFixed(0)),
AppLocalizations.of(context).gValue(values.protein.toStringAsFixed(0)),
AppLocalizations.of(context).gValue(values.carbohydrates.toStringAsFixed(0)),
AppLocalizations.of(context).gValue(values.fat.toStringAsFixed(0)),
];
AppLocalizations.of(context).kcalValue(values.energy.toStringAsFixed(0)),
AppLocalizations.of(context).gValue(values.protein.toStringAsFixed(0)),
AppLocalizations.of(context).gValue(values.carbohydrates.toStringAsFixed(0)),
AppLocalizations.of(context).gValue(values.fat.toStringAsFixed(0)),
];
List<int> getNutritionColumnFlexes(BuildContext context) {
return getNutritionColumnNames(context).map((e) {
@@ -51,11 +51,7 @@ List<int> getNutritionColumnFlexes(BuildContext context) {
}
List<Widget> muted(List<String> children) => children
.map((e) => MutedText(
e,
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
))
.map((e) => MutedText(e, textAlign: TextAlign.right, overflow: TextOverflow.ellipsis))
.toList();
// return a row of elements in the standard macros spacing
@@ -85,15 +81,17 @@ String getShortNutritionValues(NutritionalValues values, BuildContext context) {
}
String getKcalConsumed(Meal meal, BuildContext context) {
final consumed =
meal.diaryEntriesToday.map((e) => e.nutritionalValues.energy).fold(0.0, (a, b) => a + b);
final consumed = meal.diaryEntriesToday
.map((e) => e.nutritionalValues.energy)
.fold(0.0, (a, b) => a + b);
return AppLocalizations.of(context).kcalValue(consumed.toStringAsFixed(0));
}
String getKcalConsumedVsPlanned(Meal meal, BuildContext context) {
final planned = meal.plannedNutritionalValues.energy;
final consumed =
meal.diaryEntriesToday.map((e) => e.nutritionalValues.energy).fold(0.0, (a, b) => a + b);
final consumed = meal.diaryEntriesToday
.map((e) => e.nutritionalValues.energy)
.fold(0.0, (a, b) => a + b);
final loc = AppLocalizations.of(context);
return '${consumed.toStringAsFixed(0)} / ${planned.toStringAsFixed(0)} ${loc.kcal}';

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/helpers/misc.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/ingredient.dart';
import 'package:wger/models/nutrition/nutritional_goals.dart';
import 'package:wger/widgets/nutrition/macro_nutrients_table.dart';
@@ -143,15 +143,14 @@ class IngredientScanResultDialog extends StatelessWidget {
if (snapshot.connectionState == ConnectionState.done && ingredient == null)
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text(
AppLocalizations.of(context).productNotFoundDescription(barcode),
),
child: Text(AppLocalizations.of(context).productNotFoundDescription(barcode)),
),
if (ingredient != null)
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child:
Text(AppLocalizations.of(context).productFoundDescription(ingredient.name)),
child: Text(
AppLocalizations.of(context).productFoundDescription(ingredient.name),
),
),
if (ingredient?.image?.image != null)
ingredientImage(ingredient!.image!.image, context),

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_goals.dart';
class MacronutrientsTable extends StatelessWidget {
@@ -22,13 +22,13 @@ class MacronutrientsTable extends StatelessWidget {
final loc = AppLocalizations.of(context);
Widget columnHeader(bool left, String title) => Padding(
padding: const EdgeInsets.symmetric(vertical: tablePadding),
child: Text(
title,
style: const TextStyle(fontWeight: FontWeight.bold),
textAlign: left ? TextAlign.left : TextAlign.right,
),
);
padding: const EdgeInsets.symmetric(vertical: tablePadding),
child: Text(
title,
style: const TextStyle(fontWeight: FontWeight.bold),
textAlign: left ? TextAlign.left : TextAlign.right,
),
);
TableRow macroRow(int indent, bool g, String title, double? Function(NutritionalGoals ng) get) {
final goal = get(nutritionalGoals);
@@ -53,10 +53,7 @@ class MacronutrientsTable extends StatelessWidget {
return Table(
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
border: TableBorder(
horizontalInside: BorderSide(
width: 1,
color: Theme.of(context).colorScheme.outline,
),
horizontalInside: BorderSide(width: 1, color: Theme.of(context).colorScheme.outline),
),
columnWidths: const {0: FractionColumnWidth(0.4)},
children: [

View File

@@ -17,10 +17,10 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_svg_icons/flutter_svg_icons.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/meal.dart';
import 'package:wger/models/nutrition/meal_item.dart';
import 'package:wger/providers/nutrition.dart';
@@ -36,7 +36,7 @@ import 'package:wger/widgets/nutrition/widgets.dart';
enum viewMode {
base, // just highlevel meal info (name, time)
withIngredients, // + ingredients
withAllDetails // + nutritional breakdown of ingredients, + logged today
withAllDetails, // + nutritional breakdown of ingredients, + logged today
}
class MealWidget extends StatefulWidget {
@@ -45,12 +45,7 @@ class MealWidget extends StatefulWidget {
final bool popTwice;
final bool readOnly;
const MealWidget(
this._meal,
this._recentMealItems,
this.popTwice,
this.readOnly,
);
const MealWidget(this._meal, this._recentMealItems, this.popTwice, this.readOnly);
@override
_MealWidgetState createState() => _MealWidgetState();
@@ -173,8 +168,9 @@ class _MealWidgetState extends State<MealWidget> {
),
)
else
...widget._meal.mealItems
.map((item) => MealItemEditableFullTile(item, _viewMode, _editing)),
...widget._meal.mealItems.map(
(item) => MealItemEditableFullTile(item, _viewMode, _editing),
),
if (_viewMode == viewMode.withIngredients || _viewMode == viewMode.withAllDetails)
const Divider(),
if (_viewMode == viewMode.withIngredients || _viewMode == viewMode.withAllDetails)
@@ -201,12 +197,12 @@ class _MealWidgetState extends State<MealWidget> {
planned: widget._meal.plannedNutritionalValues,
logged: widget._meal.loggedNutritionalValuesToday,
),
...widget._meal.diaryEntriesToday.map((item) => Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [DiaryEntryTile(diaryEntry: item)],
),
)),
...widget._meal.diaryEntriesToday.map(
(item) => Padding(
padding: const EdgeInsets.all(8.0),
child: Column(children: [DiaryEntryTile(diaryEntry: item)]),
),
),
],
),
],
@@ -293,11 +289,11 @@ class MealHeader extends StatelessWidget {
required viewMode viewMode,
required Function() toggleEditing,
required Function() toggleViewMode,
}) : _meal = meal,
_editing = editing,
_viewMode = viewMode,
_toggleViewMode = toggleViewMode,
_toggleEditing = toggleEditing;
}) : _meal = meal,
_editing = editing,
_viewMode = viewMode,
_toggleViewMode = toggleViewMode,
_toggleEditing = toggleEditing;
@override
Widget build(BuildContext context) {
@@ -306,35 +302,34 @@ class MealHeader extends StatelessWidget {
children: [
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
title: Row(children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_meal.name,
style: Theme.of(context).textTheme.titleLarge,
),
Row(
children: [
if (_meal.time != null)
title: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(_meal.name, style: Theme.of(context).textTheme.titleLarge),
Row(
children: [
if (_meal.time != null)
Text(
_meal.time!.format(context),
style: Theme.of(context).textTheme.titleSmall,
),
if (_meal.time != null) const SizedBox(width: 12),
Text(
_meal.time!.format(context),
_meal.isRealMeal
? getKcalConsumedVsPlanned(_meal, context)
: getKcalConsumed(_meal, context),
style: Theme.of(context).textTheme.titleSmall,
),
if (_meal.time != null) const SizedBox(width: 12),
Text(
_meal.isRealMeal
? getKcalConsumedVsPlanned(_meal, context)
: getKcalConsumed(_meal, context),
style: Theme.of(context).textTheme.titleSmall,
),
],
),
],
],
),
],
),
),
),
]),
],
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/ingredient.dart';
import 'package:wger/models/nutrition/log.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
@@ -18,11 +18,7 @@ class MealItemValuesTile extends StatelessWidget {
final Ingredient ingredient;
final NutritionalValues nutritionalValues;
const MealItemValuesTile({
super.key,
required this.ingredient,
required this.nutritionalValues,
});
const MealItemValuesTile({super.key, required this.ingredient, required this.nutritionalValues});
@override
Widget build(BuildContext context) {
@@ -53,11 +49,7 @@ class DiaryheaderTile extends StatelessWidget {
/// a NutritionTitle showing diary entries
class DiaryEntryTile extends StatelessWidget {
const DiaryEntryTile({
super.key,
required this.diaryEntry,
this.nutritionalPlan,
});
const DiaryEntryTile({super.key, required this.diaryEntry, this.nutritionalPlan});
final Log diaryEntry;
final NutritionalPlan? nutritionalPlan;
@@ -82,8 +74,10 @@ class DiaryEntryTile extends StatelessWidget {
: IconButton(
tooltip: AppLocalizations.of(context).delete,
onPressed: () {
Provider.of<NutritionPlansProvider>(context, listen: false)
.deleteLog(diaryEntry.id!, nutritionalPlan!.id!);
Provider.of<NutritionPlansProvider>(
context,
listen: false,
).deleteLog(diaryEntry.id!, nutritionalPlan!.id!);
},
icon: const Icon(Icons.delete_outline),
iconSize: ICON_SIZE_SMALL,

View File

@@ -17,7 +17,7 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/models/nutrition/nutritional_values.dart';
import 'package:wger/widgets/nutrition/charts.dart';
@@ -61,20 +61,14 @@ class NutritionalDiaryDetailWidget extends StatelessWidget {
),
const SizedBox(height: 15),
const DiaryheaderTile(),
...logs.map(
(e) => DiaryEntryTile(diaryEntry: e, nutritionalPlan: _nutritionalPlan),
),
...logs.map((e) => DiaryEntryTile(diaryEntry: e, nutritionalPlan: _nutritionalPlan)),
],
);
}
}
class NutritionDiaryTable extends StatelessWidget {
const NutritionDiaryTable({
super.key,
required this.planned,
required this.logged,
});
const NutritionDiaryTable({super.key, required this.planned, required this.logged});
static const double tablePadding = 7;
final NutritionalValues planned;
@@ -85,13 +79,13 @@ class NutritionDiaryTable extends StatelessWidget {
final loc = AppLocalizations.of(context);
Widget columnHeader(bool left, String title) => Padding(
padding: const EdgeInsets.symmetric(vertical: tablePadding),
child: Text(
title,
style: const TextStyle(fontWeight: FontWeight.bold),
textAlign: left ? TextAlign.left : TextAlign.right,
),
);
padding: const EdgeInsets.symmetric(vertical: tablePadding),
child: Text(
title,
style: const TextStyle(fontWeight: FontWeight.bold),
textAlign: left ? TextAlign.left : TextAlign.right,
),
);
TableRow macroRow(int indent, bool g, String title, double Function(NutritionalValues nv) get) {
final valFn = g ? loc.gValue : loc.kcalValue;
@@ -115,12 +109,14 @@ class NutritionDiaryTable extends StatelessWidget {
),
columnWidths: const {0: FractionColumnWidth(0.4)},
children: [
TableRow(children: [
columnHeader(true, loc.macronutrients),
columnHeader(false, loc.planned),
columnHeader(false, loc.logged),
columnHeader(false, loc.difference),
]),
TableRow(
children: [
columnHeader(true, loc.macronutrients),
columnHeader(false, loc.planned),
columnHeader(false, loc.logged),
columnHeader(false, loc.difference),
],
),
macroRow(0, false, loc.energy, (NutritionalValues nv) => nv.energy),
macroRow(0, true, loc.protein, (NutritionalValues nv) => nv.protein),
macroRow(0, true, loc.carbohydrates, (NutritionalValues nv) => nv.carbohydrates),

View File

@@ -1,17 +1,15 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:wger/helpers/colors.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_goals.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/models/nutrition/nutritional_values.dart';
import 'package:wger/screens/nutritional_diary_screen.dart';
class NutritionalDiaryTable extends StatelessWidget {
const NutritionalDiaryTable({
super.key,
required NutritionalPlan nutritionalPlan,
}) : plan = nutritionalPlan;
const NutritionalDiaryTable({super.key, required NutritionalPlan nutritionalPlan})
: plan = nutritionalPlan;
final NutritionalPlan plan;
@@ -82,46 +80,49 @@ class NutritionalDiaryTable extends StatelessWidget {
decoration: BoxDecoration(
border: Border(top: BorderSide(color: Colors.grey[300]!)),
),
children: [
Text(
style: Theme.of(context).textTheme.titleMedium?.copyWith(color: LIST_OF_COLORS3.first),
DateFormat.Md(Localizations.localeOf(context).languageCode).format(date),
),
Text(
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.end,
values.energy.toStringAsFixed(0),
),
if (goals.energy != null)
Text(
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.end,
(values.energy - goals.energy!).toStringAsFixed(0),
),
Text(
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.end,
values.protein.toStringAsFixed(0),
),
Text(
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.end,
values.carbohydrates.toStringAsFixed(0),
),
Text(
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.end,
values.fat.toStringAsFixed(0),
),
].map((element) {
return GestureDetector(
onTap: () => Navigator.of(context).pushNamed(
NutritionalDiaryScreen.routeName,
arguments: NutritionalDiaryArguments(plan.id!, date),
),
child: element,
);
}).toList(),
children:
[
Text(
style: Theme.of(
context,
).textTheme.titleMedium?.copyWith(color: LIST_OF_COLORS3.first),
DateFormat.Md(Localizations.localeOf(context).languageCode).format(date),
),
Text(
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.end,
values.energy.toStringAsFixed(0),
),
if (goals.energy != null)
Text(
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.end,
(values.energy - goals.energy!).toStringAsFixed(0),
),
Text(
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.end,
values.protein.toStringAsFixed(0),
),
Text(
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.end,
values.carbohydrates.toStringAsFixed(0),
),
Text(
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.end,
values.fat.toStringAsFixed(0),
),
].map((element) {
return GestureDetector(
onTap: () => Navigator.of(context).pushNamed(
NutritionalDiaryScreen.routeName,
arguments: NutritionalDiaryArguments(plan.id!, date),
),
child: element,
);
}).toList(),
);
}
}

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/widgets/nutrition/charts.dart';
@@ -34,86 +34,78 @@ class NutritionalPlanDetailWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final nutritionalGoals = _nutritionalPlan.nutritionalGoals;
final lastWeightEntry =
Provider.of<BodyWeightProvider>(context, listen: false).getNewestEntry();
final nutritionalGoalsGperKg =
lastWeightEntry != null ? nutritionalGoals / lastWeightEntry.weight.toDouble() : null;
final lastWeightEntry = Provider.of<BodyWeightProvider>(
context,
listen: false,
).getNewestEntry();
final nutritionalGoalsGperKg = lastWeightEntry != null
? nutritionalGoals / lastWeightEntry.weight.toDouble()
: null;
return SliverList(
delegate: SliverChildListDelegate(
[
SizedBox(
width: 300,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FlNutritionalPlanGoalWidget(
nutritionalPlan: _nutritionalPlan,
),
),
),
const SizedBox(height: 10),
..._nutritionalPlan.meals.map((meal) => MealWidget(
meal,
_nutritionalPlan.dedupMealItems,
false,
false,
)),
MealWidget(
_nutritionalPlan.pseudoMealOthers('Other logs'),
_nutritionalPlan.dedupMealItems,
false,
true,
),
if (nutritionalGoals.isComplete())
Container(
padding: const EdgeInsets.all(15),
height: 220,
child: FlNutritionalPlanPieChartWidget(nutritionalGoals.toValues()),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: MacronutrientsTable(
nutritionalGoals: nutritionalGoals,
plannedValuesPercentage: nutritionalGoals.energyPercentage(),
nutritionalGoalsGperKg: nutritionalGoalsGperKg,
),
),
const Padding(padding: EdgeInsets.all(8.0)),
Text(
AppLocalizations.of(context).logged,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
delegate: SliverChildListDelegate([
SizedBox(
width: 300,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FlNutritionalPlanGoalWidget(nutritionalPlan: _nutritionalPlan),
),
),
const SizedBox(height: 10),
..._nutritionalPlan.meals.map(
(meal) => MealWidget(meal, _nutritionalPlan.dedupMealItems, false, false),
),
MealWidget(
_nutritionalPlan.pseudoMealOthers('Other logs'),
_nutritionalPlan.dedupMealItems,
false,
true,
),
if (nutritionalGoals.isComplete())
Container(
padding: const EdgeInsets.only(top: 16, left: 8, right: 8),
height: 300,
child: NutritionalDiaryChartWidgetFl(
nutritionalPlan: _nutritionalPlan,
padding: const EdgeInsets.all(15),
height: 220,
child: FlNutritionalPlanPieChartWidget(nutritionalGoals.toValues()),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: MacronutrientsTable(
nutritionalGoals: nutritionalGoals,
plannedValuesPercentage: nutritionalGoals.energyPercentage(),
nutritionalGoalsGperKg: nutritionalGoalsGperKg,
),
),
const Padding(padding: EdgeInsets.all(8.0)),
Text(
AppLocalizations.of(context).logged,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
),
Container(
padding: const EdgeInsets.only(top: 16, left: 8, right: 8),
height: 300,
child: NutritionalDiaryChartWidgetFl(nutritionalPlan: _nutritionalPlan),
),
if (_nutritionalPlan.logEntriesValues.isNotEmpty)
Padding(
padding: const EdgeInsets.only(bottom: 15, left: 15, right: 15),
child: Column(
children: [
Text(
AppLocalizations.of(context).nutritionalDiary,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
),
SizedBox(
height: 200,
child: SingleChildScrollView(
child: NutritionalDiaryTable(nutritionalPlan: _nutritionalPlan),
),
),
],
),
),
if (_nutritionalPlan.logEntriesValues.isNotEmpty)
Padding(
padding: const EdgeInsets.only(bottom: 15, left: 15, right: 15),
child: Column(
children: [
Text(
AppLocalizations.of(context).nutritionalDiary,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
),
SizedBox(
height: 200,
child: SingleChildScrollView(
child: NutritionalDiaryTable(
nutritionalPlan: _nutritionalPlan,
),
),
),
],
),
),
],
),
]),
);
}
}

View File

@@ -19,9 +19,9 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/screens/nutritional_plan_screen.dart';
@@ -39,8 +39,10 @@ class _NutritionalPlansListState extends State<NutritionalPlansList> {
@override
void initState() {
super.initState();
final stream =
Provider.of<NutritionPlansProvider>(context, listen: false).watchNutritionPlans();
final stream = Provider.of<NutritionPlansProvider>(
context,
listen: false,
).watchNutritionPlans();
_subscription = stream.listen((plans) {
if (!context.mounted) {
return;
@@ -71,10 +73,9 @@ class _NutritionalPlansListState extends State<NutritionalPlansList> {
return Card(
child: ListTile(
onTap: () {
Navigator.of(context).pushNamed(
NutritionalPlanScreen.routeName,
arguments: currentPlan.id,
);
Navigator.of(
context,
).pushNamed(NutritionalPlanScreen.routeName, arguments: currentPlan.id);
},
title: Text(currentPlan.getLabel(context)),
subtitle: Text(
@@ -82,53 +83,56 @@ class _NutritionalPlansListState extends State<NutritionalPlansList> {
Localizations.localeOf(context).languageCode,
).format(currentPlan.creationDate),
),
trailing: Row(mainAxisSize: MainAxisSize.min, children: [
const VerticalDivider(),
IconButton(
icon: const Icon(Icons.delete),
tooltip: AppLocalizations.of(context).delete,
onPressed: () async {
await showDialog(
context: context,
builder: (BuildContext contextDialog) {
return AlertDialog(
content: Text(
AppLocalizations.of(context).confirmDelete(currentPlan.description),
),
actions: [
TextButton(
child: Text(
MaterialLocalizations.of(context).cancelButtonLabel,
),
onPressed: () => Navigator.of(contextDialog).pop(),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
const VerticalDivider(),
IconButton(
icon: const Icon(Icons.delete),
tooltip: AppLocalizations.of(context).delete,
onPressed: () async {
await showDialog(
context: context,
builder: (BuildContext contextDialog) {
return AlertDialog(
content: Text(
AppLocalizations.of(
context,
).confirmDelete(currentPlan.description),
),
TextButton(
child: Text(
AppLocalizations.of(context).delete,
style: TextStyle(
color: Theme.of(context).colorScheme.error,
actions: [
TextButton(
child: Text(
MaterialLocalizations.of(context).cancelButtonLabel,
),
onPressed: () => Navigator.of(contextDialog).pop(),
),
onPressed: () {
provider.deletePlan(currentPlan.id!);
Navigator.of(contextDialog).pop();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context).successfullyDeleted,
textAlign: TextAlign.center,
TextButton(
child: Text(
AppLocalizations.of(context).delete,
style: TextStyle(color: Theme.of(context).colorScheme.error),
),
onPressed: () {
provider.deletePlan(currentPlan.id!);
Navigator.of(contextDialog).pop();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context).successfullyDeleted,
textAlign: TextAlign.center,
),
),
),
);
},
),
],
);
},
);
},
),
]),
);
},
),
],
);
},
);
},
),
],
),
),
);
},

View File

@@ -18,7 +18,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; //import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:flutter_zxing/flutter_zxing.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
@@ -27,6 +26,7 @@ import 'package:wger/helpers/consts.dart';
import 'package:wger/helpers/misc.dart';
import 'package:wger/helpers/platform.dart';
import 'package:wger/helpers/ui.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/ingredient_api.dart';
import 'package:wger/models/nutrition/ingredient.dart';
import 'package:wger/providers/nutrition.dart';
@@ -38,19 +38,19 @@ class ScanReader extends StatelessWidget {
const ScanReader();
@override
Widget build(BuildContext context) => Scaffold(
body: ReaderWidget(
onScan: (result) {
// notes:
// 1. even if result.isValid, result.error is always non-null (and set to "")
// 2. i've never encountered scan errors to see when they occur, and
// i wouldn't know what to do about them anyway, so we simply return
// result.text in such case (which presumably will be null, or "")
// 3. when user cancels (swipe left / back button) this code is no longer
// run and the caller receives null
Navigator.pop(context, result.text);
},
),
);
body: ReaderWidget(
onScan: (result) {
// notes:
// 1. even if result.isValid, result.error is always non-null (and set to "")
// 2. i've never encountered scan errors to see when they occur, and
// i wouldn't know what to do about them anyway, so we simply return
// result.text in such case (which presumably will be null, or "")
// 3. when user cancels (swipe left / back button) this code is no longer
// run and the caller receives null
Navigator.pop(context, result.text);
},
),
);
}
class IngredientTypeahead extends StatefulWidget {
@@ -92,8 +92,9 @@ class _IngredientTypeaheadState extends State<IngredientTypeahead> {
Future<String> readerscan(BuildContext context) async {
try {
final code = await Navigator.of(context)
.push<String?>(MaterialPageRoute(builder: (context) => const ScanReader()));
final code = await Navigator.of(
context,
).push<String?>(MaterialPageRoute(builder: (context) => const ScanReader()));
if (code == null) {
return '';
}
@@ -152,12 +153,8 @@ class _IngredientTypeaheadState extends State<IngredientTypeahead> {
final url = context.read<NutritionPlansProvider>().baseProvider.auth.serverUrl;
return ListTile(
leading: suggestion.data.image != null
? CircleAvatar(
backgroundImage: NetworkImage(url! + suggestion.data.image!),
)
: const CircleIconAvatar(
Icon(Icons.image, color: Colors.grey),
),
? CircleAvatar(backgroundImage: NetworkImage(url! + suggestion.data.image!))
: const CircleIconAvatar(Icon(Icons.image, color: Colors.grey)),
title: Text(suggestion.value),
// subtitle: Text(suggestion.data.id.toString()),
trailing: IconButton(
@@ -217,8 +214,10 @@ class _IngredientTypeaheadState extends State<IngredientTypeahead> {
showDialog(
context: context,
builder: (context) => FutureBuilder<Ingredient?>(
future: Provider.of<NutritionPlansProvider>(context, listen: false)
.searchIngredientWithCode(barcode),
future: Provider.of<NutritionPlansProvider>(
context,
listen: false,
).searchIngredientWithCode(barcode),
builder: (BuildContext context, AsyncSnapshot<Ingredient?> snapshot) {
return IngredientScanResultDialog(snapshot, barcode, widget.selectIngredient);
},
@@ -238,9 +237,7 @@ class IngredientAvatar extends StatelessWidget {
Widget build(BuildContext context) {
return ingredient.image != null
? GestureDetector(
child: CircleAvatar(
backgroundImage: NetworkImage(ingredient.image!.image),
),
child: CircleAvatar(backgroundImage: NetworkImage(ingredient.image!.image)),
onTap: () async {
if (ingredient.image!.objectUrl != '') {
return launchURL(ingredient.image!.objectUrl, context);

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/user/profile.dart';
import 'package:wger/providers/user.dart';
import 'package:wger/theme/theme.dart';
@@ -132,9 +132,7 @@ class _UserProfileFormState extends State<UserProfileForm> {
context.read<UserProvider>().saveProfile();
Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(AppLocalizations.of(context).successfullySaved),
),
SnackBar(content: Text(AppLocalizations.of(context).successfullySaved)),
);
},
child: Text(AppLocalizations.of(context).save),

View File

@@ -17,12 +17,12 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart';
import 'package:wger/exceptions/http_exception.dart';
import 'package:wger/helpers/json.dart';
import 'package:wger/helpers/ui.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/body_weight/weight_entry.dart';
import 'package:wger/providers/body_weight.dart';
@@ -52,10 +52,7 @@ class WeightForm extends StatelessWidget {
// Stop keyboard from appearing
decoration: InputDecoration(
labelText: AppLocalizations.of(context).date,
suffixIcon: const Icon(
Icons.calendar_today,
key: Key('calendarIcon'),
),
suffixIcon: const Icon(Icons.calendar_today, key: Key('calendarIcon')),
),
enableInteractiveSelection: false,
controller: dateController,

View File

@@ -17,9 +17,9 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/providers/user.dart';
@@ -38,8 +38,9 @@ class WeightOverview extends StatelessWidget {
final weightProvider = Provider.of<BodyWeightProvider>(context, listen: false);
final plan = Provider.of<NutritionPlansProvider>(context, listen: false).currentPlan;
final entriesAll =
weightProvider.items.map((e) => MeasurementChartEntry(e.weight, e.date)).toList();
final entriesAll = weightProvider.items
.map((e) => MeasurementChartEntry(e.weight, e.date))
.toList();
final entries7dAvg = moving7dAverage(entriesAll);
final unit = weightUnit(profile!.isMetric, context);
@@ -55,10 +56,7 @@ class WeightOverview extends StatelessWidget {
context,
),
TextButton(
onPressed: () => Navigator.pushNamed(
context,
MeasurementCategoriesScreen.routeName,
),
onPressed: () => Navigator.pushNamed(context, MeasurementCategoriesScreen.routeName),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [

View File

@@ -17,14 +17,11 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/screens/add_exercise_screen.dart';
import 'package:wger/screens/exercises_screen.dart';
enum _WorkoutAppBarOptions {
list,
contribute,
}
enum _WorkoutAppBarOptions { list, contribute }
class WorkoutOverviewAppBar extends StatelessWidget implements PreferredSizeWidget {
const WorkoutOverviewAppBar();

View File

@@ -18,10 +18,10 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:wger/helpers/charts.dart';
import 'package:wger/helpers/colors.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
class LogChartWidgetFl extends StatefulWidget {
final Map _data;
@@ -79,12 +79,8 @@ class _LogChartWidgetFlState extends State<LogChartWidgetFl> {
),
titlesData: FlTitlesData(
show: true,
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
@@ -116,10 +112,7 @@ class _LogChartWidgetFlState extends State<LogChartWidgetFl> {
),
),
),
borderData: FlBorderData(
show: true,
border: Border.all(color: const Color(0xff37434d)),
),
borderData: FlBorderData(show: true, border: Border.all(color: const Color(0xff37434d))),
lineBarsData: [
...widget._data['chart_data'].map((e) {
colors.moveNext();
@@ -138,11 +131,8 @@ class _LogChartWidgetFlState extends State<LogChartWidgetFl> {
isStrokeCapRound: true,
dotData: FlDotData(
show: true,
getDotPainter: (p0, p1, p2, p3) => FlDotCirclePainter(
radius: 2,
color: Colors.black,
strokeWidth: 0,
),
getDotPainter: (p0, p1, p2, p3) =>
FlDotCirclePainter(radius: 2, color: Colors.black, strokeWidth: 0),
),
);
}),

View File

@@ -17,9 +17,9 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/day.dart';
import 'package:wger/models/workouts/set.dart';
import 'package:wger/models/workouts/setting.dart';
@@ -57,15 +57,15 @@ class SettingWidget extends StatelessWidget {
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(setting.exerciseObj
.getExercise(Localizations.localeOf(context).languageCode)
.name),
title: Text(
setting.exerciseObj
.getExercise(Localizations.localeOf(context).languageCode)
.name,
),
content: ExerciseDetail(setting.exerciseObj),
actions: [
TextButton(
child: Text(
MaterialLocalizations.of(context).closeButtonLabel,
),
child: Text(MaterialLocalizations.of(context).closeButtonLabel),
onPressed: () {
Navigator.of(context).pop();
},
@@ -81,9 +81,7 @@ class SettingWidget extends StatelessWidget {
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
...set.getSmartRepr(setting.exerciseObj).map((e) => Text(e)),
],
children: [...set.getSmartRepr(setting.exerciseObj).map((e) => Text(e))],
),
);
}
@@ -149,10 +147,7 @@ class _WorkoutDayWidgetState extends State<WorkoutDayWidget> {
if (_editing)
ReorderableDragStartListener(
index: index,
child: const IconButton(
icon: Icon(Icons.drag_handle),
onPressed: null,
),
child: const IconButton(icon: Icon(Icons.drag_handle), onPressed: null),
),
],
);
@@ -167,11 +162,7 @@ class _WorkoutDayWidgetState extends State<WorkoutDayWidget> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DayHeader(
day: widget._day,
expanded: _editing,
toggle: _toggleExpanded,
),
DayHeader(day: widget._day, expanded: _editing, toggle: _toggleExpanded),
if (_editing)
Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
@@ -265,13 +256,10 @@ class DayHeader extends StatelessWidget {
final bool _editing;
final Function _toggle;
const DayHeader({
required Day day,
required bool expanded,
required Function toggle,
}) : _day = day,
_editing = expanded,
_toggle = toggle;
const DayHeader({required Day day, required bool expanded, required Function toggle})
: _day = day,
_editing = expanded,
_toggle = toggle;
@override
Widget build(BuildContext context) {
@@ -285,22 +273,24 @@ class DayHeader extends StatelessWidget {
subtitle: Text(_day.getDaysTextTranslated(Localizations.localeOf(context).languageCode)),
leading: const Icon(Icons.play_arrow),
minLeadingWidth: 8,
trailing: Row(mainAxisSize: MainAxisSize.min, children: [
const SizedBox(height: 40, width: 1, child: VerticalDivider()),
const SizedBox(width: 10),
IconButton(
icon: _editing ? const Icon(Icons.done) : const Icon(Icons.edit),
tooltip: _editing ? AppLocalizations.of(context).done : AppLocalizations.of(context).edit,
onPressed: () {
_toggle();
},
),
]),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 40, width: 1, child: VerticalDivider()),
const SizedBox(width: 10),
IconButton(
icon: _editing ? const Icon(Icons.done) : const Icon(Icons.edit),
tooltip: _editing
? AppLocalizations.of(context).done
: AppLocalizations.of(context).edit,
onPressed: () {
_toggle();
},
),
],
),
onTap: () {
Navigator.of(context).pushNamed(
GymModeScreen.routeName,
arguments: _day,
);
Navigator.of(context).pushNamed(GymModeScreen.routeName, arguments: _day);
},
);
}

View File

@@ -17,10 +17,10 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/workouts/day.dart';
import 'package:wger/models/workouts/repetition_unit.dart';
@@ -72,9 +72,7 @@ class WorkoutForm extends StatelessWidget {
),
TextFormField(
key: const Key('field-description'),
decoration: InputDecoration(
labelText: AppLocalizations.of(context).description,
),
decoration: InputDecoration(labelText: AppLocalizations.of(context).description),
minLines: 3,
maxLines: 10,
controller: workoutDescriptionController,
@@ -113,10 +111,9 @@ class WorkoutForm extends StatelessWidget {
listen: false,
).addWorkout(_plan);
if (context.mounted) {
Navigator.of(context).pushReplacementNamed(
WorkoutPlanScreen.routeName,
arguments: newPlan,
);
Navigator.of(
context,
).pushReplacementNamed(WorkoutPlanScreen.routeName, arguments: newPlan);
}
}
},
@@ -142,10 +139,9 @@ class _DayCheckboxState extends State<DayCheckbox> {
Widget build(BuildContext context) {
return CheckboxListTile(
key: Key('field-checkbox-${widget._dayNr}'),
title: Text(widget._day.getDayTranslated(
widget._dayNr,
Localizations.localeOf(context).languageCode,
)),
title: Text(
widget._day.getDayTranslated(widget._dayNr, Localizations.localeOf(context).languageCode),
),
value: widget._day.daysOfWeek.contains(widget._dayNr),
onChanged: (bool? newValue) {
setState(() {
@@ -223,14 +219,12 @@ class _DayFormWidgetState extends State<DayFormWidget> {
try {
if (widget._day.id == null) {
Provider.of<WorkoutPlansProvider>(context, listen: false).addDay(
widget._day,
widget.workout,
);
Provider.of<WorkoutPlansProvider>(
context,
listen: false,
).addDay(widget._day, widget.workout);
} else {
Provider.of<WorkoutPlansProvider>(context, listen: false).editDay(
widget._day,
);
Provider.of<WorkoutPlansProvider>(context, listen: false).editDay(widget._day);
}
widget.dayController.clear();
@@ -442,22 +436,16 @@ class _SetFormWidgetState extends State<SetFormWidget> {
return null;
}
return context.read<ExercisesProvider>().searchExercise(
pattern,
languageCode: Localizations.localeOf(context).languageCode,
searchEnglish: _searchEnglish,
);
pattern,
languageCode: Localizations.localeOf(context).languageCode,
searchEnglish: _searchEnglish,
);
},
itemBuilder: (
BuildContext context,
Exercise exerciseSuggestion,
) =>
ListTile(
itemBuilder: (BuildContext context, Exercise exerciseSuggestion) => ListTile(
key: Key('exercise-${exerciseSuggestion.id}'),
leading: SizedBox(
width: 45,
child: ExerciseImageWidget(
image: exerciseSuggestion.getMainImage,
),
child: ExerciseImageWidget(image: exerciseSuggestion.getMainImage),
),
title: Text(
exerciseSuggestion
@@ -487,10 +475,7 @@ class _SetFormWidgetState extends State<SetFormWidget> {
);
},
transitionBuilder: (context, animation, child) => FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.fastOutSlowIn,
),
opacity: CurvedAnimation(parent: animation, curve: Curves.fastOutSlowIn),
child: child,
),
onSelected: (Exercise exerciseSuggestion) {
@@ -538,8 +523,9 @@ class _SetFormWidgetState extends State<SetFormWidget> {
final index = entry.key;
final exercise = entry.value;
final showSupersetInfo = (index + 1) < widget._set.exerciseBasesObj.length;
final settings =
widget._set.settings.where((e) => e.exerciseObj.id == exercise.id).toList();
final settings = widget._set.settings
.where((e) => e.exerciseObj.id == exercise.id)
.toList();
return Column(
children: [
@@ -551,16 +537,10 @@ class _SetFormWidgetState extends State<SetFormWidget> {
removeExerciseBase,
),
if (showSupersetInfo)
const Padding(
padding: EdgeInsets.all(3.0),
child: Text('+'),
),
const Padding(padding: EdgeInsets.all(3.0), child: Text('+')),
if (showSupersetInfo) Text(AppLocalizations.of(context).supersetWith),
if (showSupersetInfo)
const Padding(
padding: EdgeInsets.all(3.0),
child: Text('+'),
),
const Padding(padding: EdgeInsets.all(3.0), child: Text('+')),
],
);
}),
@@ -648,29 +628,17 @@ class ExerciseSetting extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
flex: 2,
child: RepsInputWidget(setting, _detailed),
),
Flexible(flex: 2, child: RepsInputWidget(setting, _detailed)),
const SizedBox(width: 4),
Flexible(
flex: 3,
child: RepetitionUnitInputWidget(setting),
),
Flexible(flex: 3, child: RepetitionUnitInputWidget(setting)),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
flex: 2,
child: WeightInputWidget(setting, _detailed),
),
Flexible(flex: 2, child: WeightInputWidget(setting, _detailed)),
const SizedBox(width: 4),
Flexible(
flex: 3,
child: WeightUnitInputWidget(setting, key: Key(i.toString())),
),
Flexible(flex: 3, child: WeightUnitInputWidget(setting, key: Key(i.toString()))),
],
),
Flexible(flex: 2, child: RiRInputWidget(setting)),
@@ -919,15 +887,15 @@ class _WeightUnitInputWidgetState extends State<WeightUnitInputWidget> {
widget._setting.weightUnit = newValue;
});
},
items: Provider.of<WorkoutPlansProvider>(context, listen: false)
.weightUnits
items: Provider.of<WorkoutPlansProvider>(context, listen: false).weightUnits
.map<DropdownMenuItem<WeightUnit>>((WeightUnit value) {
return DropdownMenuItem<WeightUnit>(
key: Key(value.id.toString()),
value: value,
child: Text(value.name),
);
}).toList(),
return DropdownMenuItem<WeightUnit>(
key: Key(value.id.toString()),
value: value,
child: Text(value.name),
);
})
.toList(),
);
}
}
@@ -951,9 +919,7 @@ class _RepetitionUnitInputWidgetState extends State<RepetitionUnitInputWidget> {
return DropdownButtonFormField(
value: selectedWeightUnit,
decoration: InputDecoration(
labelText: AppLocalizations.of(context).repetitionUnit,
),
decoration: InputDecoration(labelText: AppLocalizations.of(context).repetitionUnit),
isDense: true,
onChanged: (RepetitionUnit? newValue) {
setState(() {
@@ -961,15 +927,15 @@ class _RepetitionUnitInputWidgetState extends State<RepetitionUnitInputWidget> {
widget._setting.repetitionUnit = newValue;
});
},
items: Provider.of<WorkoutPlansProvider>(context, listen: false)
.repetitionUnits
items: Provider.of<WorkoutPlansProvider>(context, listen: false).repetitionUnits
.map<DropdownMenuItem<RepetitionUnit>>((RepetitionUnit value) {
return DropdownMenuItem<RepetitionUnit>(
key: Key(value.id.toString()),
value: value,
child: Text(value.name),
);
}).toList(),
return DropdownMenuItem<RepetitionUnit>(
key: Key(value.id.toString()),
value: value,
child: Text(value.name),
);
})
.toList(),
);
}
}

View File

@@ -18,7 +18,6 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
@@ -27,8 +26,8 @@ import 'package:wger/helpers/consts.dart';
import 'package:wger/helpers/gym_mode.dart';
import 'package:wger/helpers/i18n.dart';
import 'package:wger/helpers/json.dart';
import 'package:wger/helpers/misc.dart';
import 'package:wger/helpers/ui.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/workouts/day.dart';
import 'package:wger/models/workouts/log.dart';
@@ -83,8 +82,10 @@ class _GymModeState extends State<GymMode> {
for (final set in widget._workoutDay.sets) {
var firstPage = true;
for (final setting in set.settingsComputed) {
final exerciseBase = Provider.of<ExercisesProvider>(context, listen: false)
.findExerciseById(setting.exerciseId);
final exerciseBase = Provider.of<ExercisesProvider>(
context,
listen: false,
).findExerciseById(setting.exerciseId);
if (firstPage) {
_exercisePages[exerciseBase] = currentPage;
@@ -116,23 +117,20 @@ class _GymModeState extends State<GymMode> {
currentElement++;
if (firstPage) {
out.add(ExerciseOverview(
_controller,
exerciseBase,
ratioCompleted,
_exercisePages,
));
out.add(ExerciseOverview(_controller, exerciseBase, ratioCompleted, _exercisePages));
}
out.add(LogPage(
_controller,
setting,
set,
exerciseBase,
workoutProvider.findById(widget._workoutDay.workoutId),
ratioCompleted,
_exercisePages,
));
out.add(
LogPage(
_controller,
setting,
set,
exerciseBase,
workoutProvider.findById(widget._workoutDay.workoutId),
ratioCompleted,
_exercisePages,
),
);
out.add(TimerWidget(_controller, ratioCompleted, _exercisePages));
firstPage = false;
}
@@ -149,8 +147,10 @@ class _GymModeState extends State<GymMode> {
StartPage(_controller, widget._workoutDay, _exercisePages),
...getContent(),
SessionPage(
Provider.of<WorkoutPlansProvider>(context, listen: false)
.findById(widget._workoutDay.workoutId),
Provider.of<WorkoutPlansProvider>(
context,
listen: false,
).findById(widget._workoutDay.workoutId),
_controller,
widget._start,
_exercisePages,
@@ -298,9 +298,7 @@ class _LogPageState extends State<LogPage> {
),
Expanded(
child: TextFormField(
decoration: InputDecoration(
labelText: AppLocalizations.of(context).repetitions,
),
decoration: InputDecoration(labelText: AppLocalizations.of(context).repetitions),
enabled: true,
controller: _repsController,
keyboardType: TextInputType.number,
@@ -353,9 +351,7 @@ class _LogPageState extends State<LogPage> {
),
Expanded(
child: TextFormField(
decoration: InputDecoration(
labelText: AppLocalizations.of(context).weight,
),
decoration: InputDecoration(labelText: AppLocalizations.of(context).weight),
controller: _weightController,
keyboardType: TextInputType.number,
onFieldSubmitted: (_) {},
@@ -512,9 +508,9 @@ class _LogPageState extends State<LogPage> {
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
),
...widget._workoutPlan
.filterLogsByExerciseBase(widget._exerciseBase, unique: true)
.map((log) {
...widget._workoutPlan.filterLogsByExerciseBase(widget._exerciseBase, unique: true).map((
log,
) {
return ListTile(
title: Text(log.singleLogRepTextNoNl),
subtitle: Text(
@@ -533,9 +529,9 @@ class _LogPageState extends State<LogPage> {
widget._log.weightUnit = log.weightUnitObj;
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(AppLocalizations.of(context).dataCopied),
));
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(AppLocalizations.of(context).dataCopied)));
});
},
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
@@ -584,9 +580,7 @@ class _LogPageState extends State<LogPage> {
alignment: Alignment.center,
child: Text(
key.toString(),
style: const TextStyle(
fontWeight: FontWeight.bold,
),
style: const TextStyle(fontWeight: FontWeight.bold),
),
),
),
@@ -598,9 +592,7 @@ class _LogPageState extends State<LogPage> {
),
],
)
: MutedText(
AppLocalizations.of(context).plateCalculatorNotDivisible,
),
: MutedText(AppLocalizations.of(context).plateCalculatorNotDivisible),
),
const SizedBox(height: 3),
],
@@ -676,20 +668,20 @@ class ExerciseOverview extends StatelessWidget {
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
),
..._exerciseBase.equipment.map((e) => Text(
getTranslation(e.name, context),
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
)),
..._exerciseBase.equipment.map(
(e) => Text(
getTranslation(e.name, context),
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
),
),
if (_exerciseBase.images.isNotEmpty)
SizedBox(
width: double.infinity,
height: 200,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
..._exerciseBase.images.map((e) => ExerciseImageWidget(image: e)),
],
children: [..._exerciseBase.images.map((e) => ExerciseImageWidget(image: e))],
),
),
Html(
@@ -712,12 +704,7 @@ class SessionPage extends StatefulWidget {
final TimeOfDay _start;
final Map<Exercise, int> _exercisePages;
const SessionPage(
this._workoutPlan,
this._controller,
this._start,
this._exercisePages,
);
const SessionPage(this._workoutPlan, this._controller, this._start, this._exercisePages);
@override
_SessionPageState createState() => _SessionPageState();
@@ -777,9 +764,11 @@ class _SessionPageState extends State<SessionPage> {
renderBorder: false,
onPressed: (int index) {
setState(() {
for (int buttonIndex = 0;
buttonIndex < selectedImpression.length;
buttonIndex++) {
for (
int buttonIndex = 0;
buttonIndex < selectedImpression.length;
buttonIndex++
) {
_session.impression = index + 1;
if (buttonIndex == index) {
@@ -798,9 +787,7 @@ class _SessionPageState extends State<SessionPage> {
],
),
TextFormField(
decoration: InputDecoration(
labelText: AppLocalizations.of(context).notes,
),
decoration: InputDecoration(labelText: AppLocalizations.of(context).notes),
maxLines: 3,
controller: notesController,
keyboardType: TextInputType.multiline,
@@ -922,11 +909,7 @@ class TimerWidget extends StatefulWidget {
final double _ratioCompleted;
final Map<Exercise, int> _exercisePages;
const TimerWidget(
this._controller,
this._ratioCompleted,
this._exercisePages,
);
const TimerWidget(this._controller, this._ratioCompleted, this._exercisePages);
@override
_TimerWidgetState createState() => _TimerWidgetState();
@@ -1054,18 +1037,11 @@ class NavigationHeader extends StatelessWidget {
final String _title;
final Map<Exercise, int> exercisePages;
const NavigationHeader(
this._title,
this._controller, {
required this.exercisePages,
});
const NavigationHeader(this._title, this._controller, {required this.exercisePages});
Widget getDialog(BuildContext context) {
return AlertDialog(
title: Text(
AppLocalizations.of(context).jumpTo,
textAlign: TextAlign.center,
),
title: Text(AppLocalizations.of(context).jumpTo, textAlign: TextAlign.center),
contentPadding: EdgeInsets.zero,
content: SingleChildScrollView(
child: Column(
@@ -1121,10 +1097,7 @@ class NavigationHeader extends StatelessWidget {
IconButton(
icon: const Icon(Icons.toc),
onPressed: () {
showDialog(
context: context,
builder: (ctx) => getDialog(context),
);
showDialog(context: context, builder: (ctx) => getDialog(context));
},
),
],

View File

@@ -17,9 +17,9 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/workouts/log.dart';
import 'package:wger/models/workouts/session.dart';
@@ -70,10 +70,7 @@ class _WorkoutLogsState extends State<WorkoutLogs> {
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
AppLocalizations.of(context).logHelpEntries,
textAlign: TextAlign.justify,
),
child: Text(AppLocalizations.of(context).logHelpEntries, textAlign: TextAlign.justify),
),
Padding(
padding: const EdgeInsets.all(8.0),
@@ -82,10 +79,7 @@ class _WorkoutLogsState extends State<WorkoutLogs> {
textAlign: TextAlign.justify,
),
),
SizedBox(
width: double.infinity,
child: WorkoutLogCalendar(widget._workoutPlan),
),
SizedBox(width: double.infinity, child: WorkoutLogCalendar(widget._workoutPlan)),
],
);
}

View File

@@ -17,7 +17,7 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/workout_plan.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/screens/workout_plan_screen.dart';
@@ -50,17 +50,11 @@ class _WorkoutPlanDetailState extends State<WorkoutPlanDetail> {
}
},
isSelected: const [true, false],
children: const [
Icon(Icons.table_chart),
Icon(Icons.show_chart),
],
children: const [Icon(Icons.table_chart), Icon(Icons.show_chart)],
),
),
if (widget._workoutPlan.description != '')
Padding(
padding: const EdgeInsets.all(15),
child: Text(widget._workoutPlan.description),
),
Padding(padding: const EdgeInsets.all(15), child: Text(widget._workoutPlan.description)),
...widget._workoutPlan.days.map((workoutDay) => WorkoutDayWidget(workoutDay)),
Column(
children: [

View File

@@ -17,9 +17,9 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/workout_plans.dart';
import 'package:wger/screens/workout_plan_screen.dart';
import 'package:wger/widgets/core/text_prompt.dart';
@@ -46,10 +46,9 @@ class WorkoutPlansList extends StatelessWidget {
onTap: () {
_workoutProvider.setCurrentPlan(currentWorkout.id!);
Navigator.of(context).pushNamed(
WorkoutPlanScreen.routeName,
arguments: currentWorkout,
);
Navigator.of(
context,
).pushNamed(WorkoutPlanScreen.routeName, arguments: currentWorkout);
},
title: Text(currentWorkout.name),
subtitle: Text(
@@ -57,62 +56,65 @@ class WorkoutPlansList extends StatelessWidget {
Localizations.localeOf(context).languageCode,
).format(currentWorkout.creationDate),
),
trailing: Row(mainAxisSize: MainAxisSize.min, children: [
const VerticalDivider(),
IconButton(
icon: const Icon(Icons.delete),
tooltip: AppLocalizations.of(context).delete,
onPressed: () async {
// Delete workout from DB
await showDialog(
context: context,
builder: (BuildContext contextDialog) {
return AlertDialog(
content: Text(
AppLocalizations.of(context).confirmDelete(currentWorkout.name),
),
actions: [
TextButton(
child: Text(
MaterialLocalizations.of(context).cancelButtonLabel,
),
onPressed: () => Navigator.of(contextDialog).pop(),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
const VerticalDivider(),
IconButton(
icon: const Icon(Icons.delete),
tooltip: AppLocalizations.of(context).delete,
onPressed: () async {
// Delete workout from DB
await showDialog(
context: context,
builder: (BuildContext contextDialog) {
return AlertDialog(
content: Text(
AppLocalizations.of(context).confirmDelete(currentWorkout.name),
),
TextButton(
child: Text(
AppLocalizations.of(context).delete,
style: TextStyle(
color: Theme.of(context).colorScheme.error,
actions: [
TextButton(
child: Text(
MaterialLocalizations.of(context).cancelButtonLabel,
),
onPressed: () => Navigator.of(contextDialog).pop(),
),
onPressed: () {
// Confirmed, delete the workout
Provider.of<WorkoutPlansProvider>(
context,
listen: false,
).deleteWorkout(currentWorkout.id!);
// Close the popup
Navigator.of(contextDialog).pop();
// and inform the user
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context).successfullyDeleted,
textAlign: TextAlign.center,
),
TextButton(
child: Text(
AppLocalizations.of(context).delete,
style: TextStyle(
color: Theme.of(context).colorScheme.error,
),
);
},
),
],
);
},
);
},
),
]),
),
onPressed: () {
// Confirmed, delete the workout
Provider.of<WorkoutPlansProvider>(
context,
listen: false,
).deleteWorkout(currentWorkout.id!);
// Close the popup
Navigator.of(contextDialog).pop();
// and inform the user
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context).successfullyDeleted,
textAlign: TextAlign.center,
),
),
);
},
),
],
);
},
);
},
),
],
),
),
);
},

View File

@@ -19,7 +19,6 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http/http.dart' as http;
import 'package:http/http.dart';
@@ -28,6 +27,7 @@ import 'package:mockito/mockito.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/auth.dart';
import 'package:wger/screens/auth_screen.dart';
@@ -38,17 +38,9 @@ void main() {
late AuthProvider authProvider;
late MockClient mockClient;
final Uri tRegistration = Uri(
scheme: 'https',
host: 'wger.de',
path: 'api/v2/register/',
);
final Uri tRegistration = Uri(scheme: 'https', host: 'wger.de', path: 'api/v2/register/');
final Uri tLogin = Uri(
scheme: 'https',
host: 'wger.de',
path: 'api/v2/login/',
);
final Uri tLogin = Uri(scheme: 'https', host: 'wger.de', path: 'api/v2/login/');
final responseLoginOk = {'token': 'b01c44d3e3e016a615d2f82b16d31f8b924fb936'};
@@ -85,19 +77,15 @@ void main() {
buildSignature: 'buildSignature',
);
when(mockClient.post(
tLogin,
headers: anyNamed('headers'),
body: anyNamed('body'),
)).thenAnswer((_) => Future(() => Response(json.encode(responseLoginOk), 200)));
when(
mockClient.post(tLogin, headers: anyNamed('headers'), body: anyNamed('body')),
).thenAnswer((_) => Future(() => Response(json.encode(responseLoginOk), 200)));
when(mockClient.get(any)).thenAnswer((_) => Future(() => Response('"1.2.3.4"', 200)));
when(mockClient.post(
tRegistration,
headers: anyNamed('headers'),
body: anyNamed('body'),
)).thenAnswer((_) => Future(() => Response(json.encode(responseRegistrationOk), 201)));
when(
mockClient.post(tRegistration, headers: anyNamed('headers'), body: anyNamed('body')),
).thenAnswer((_) => Future(() => Response(json.encode(responseRegistrationOk), 201)));
});
group('Login mode', () {
@@ -134,11 +122,13 @@ void main() {
// Assert
expect(find.textContaining('An Error Occurred'), findsNothing);
verify(mockClient.get(any));
verify(mockClient.post(
tLogin,
headers: anyNamed('headers'),
body: json.encode({'username': 'testuser', 'password': '123456789'}),
));
verify(
mockClient.post(
tLogin,
headers: anyNamed('headers'),
body: json.encode({'username': 'testuser', 'password': '123456789'}),
),
);
});
testWidgets('Login - wront username & password', (WidgetTester tester) async {
@@ -149,11 +139,9 @@ void main() {
'non_field_errors': ['Username or password unknown'],
};
when(mockClient.post(
tLogin,
headers: anyNamed('headers'),
body: anyNamed('body'),
)).thenAnswer((_) => Future(() => Response(json.encode(response), 400)));
when(
mockClient.post(tLogin, headers: anyNamed('headers'), body: anyNamed('body')),
).thenAnswer((_) => Future(() => Response(json.encode(response), 400)));
await tester.pumpWidget(getWidget());
// Act
@@ -166,11 +154,13 @@ void main() {
expect(find.textContaining('An Error Occurred'), findsOne);
expect(find.textContaining('Non field errors'), findsOne);
expect(find.textContaining('Username or password unknown'), findsOne);
verify(mockClient.post(
tLogin,
headers: anyNamed('headers'),
body: json.encode({'username': 'testuser', 'password': '123456789'}),
));
verify(
mockClient.post(
tLogin,
headers: anyNamed('headers'),
body: json.encode({'username': 'testuser', 'password': '123456789'}),
),
);
});
});
@@ -219,11 +209,13 @@ void main() {
// Assert
expect(find.textContaining('An Error Occurred'), findsNothing);
verify(mockClient.post(
tRegistration,
headers: anyNamed('headers'),
body: json.encode({'username': 'testuser', 'password': '123456789'}),
));
verify(
mockClient.post(
tRegistration,
headers: anyNamed('headers'),
body: json.encode({'username': 'testuser', 'password': '123456789'}),
),
);
});
testWidgets('Registration - password problems', (WidgetTester tester) async {
@@ -232,17 +224,12 @@ void main() {
tester.view.devicePixelRatio = 1.0;
final response = {
'username': ['This field must be unique.'],
'password': [
'This password is too common.',
'This password is entirely numeric.',
],
'password': ['This password is too common.', 'This password is entirely numeric.'],
};
when(mockClient.post(
tRegistration,
headers: anyNamed('headers'),
body: anyNamed('body'),
)).thenAnswer((_) => Future(() => Response(json.encode(response), 400)));
when(
mockClient.post(tRegistration, headers: anyNamed('headers'), body: anyNamed('body')),
).thenAnswer((_) => Future(() => Response(json.encode(response), 400)));
await tester.pumpWidget(getWidget());
// Act
@@ -259,11 +246,13 @@ void main() {
expect(find.textContaining('This password is entirely numeric'), findsOne);
expect(find.textContaining('This field must be unique'), findsOne);
verify(mockClient.post(
tRegistration,
headers: anyNamed('headers'),
body: json.encode({'username': 'testuser', 'password': '123456789'}),
));
verify(
mockClient.post(
tRegistration,
headers: anyNamed('headers'),
body: json.encode({'username': 'testuser', 'password': '123456789'}),
),
);
});
});
}

View File

@@ -17,11 +17,11 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/widgets/core/settings.dart';

View File

@@ -17,11 +17,11 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/add_exercise.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/user.dart';

View File

@@ -17,9 +17,9 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/widgets/exercises/exercises.dart';

View File

@@ -27,6 +27,7 @@ import 'package:wger/helpers/consts.dart';
import 'package:wger/models/gallery/image.dart' as gallery;
import 'package:wger/providers/gallery.dart';
import 'package:wger/widgets/gallery/forms.dart';
import '../../test_data/gallery.dart';
import 'gallery_form_test.mocks.dart';

View File

@@ -17,13 +17,13 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:network_image_mock/network_image_mock.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/gallery.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/widgets/gallery/overview.dart';

View File

@@ -17,11 +17,11 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/measurements/measurement_category.dart';
import 'package:wger/models/measurements/measurement_entry.dart';
import 'package:wger/providers/measurement.dart';
@@ -37,14 +37,24 @@ void main() {
setUp(() {
mockMeasurementProvider = MockMeasurementProvider();
when(mockMeasurementProvider.categories).thenReturn([
MeasurementCategory(id: 1, name: 'body fat', unit: '%', entries: [
MeasurementEntry(id: 1, category: 1, date: DateTime(2021, 9, 1), value: 10, notes: ''),
MeasurementEntry(id: 2, category: 1, date: DateTime(2021, 9, 5), value: 11, notes: ''),
]),
MeasurementCategory(id: 2, name: 'biceps', unit: 'cm', entries: [
MeasurementEntry(id: 3, category: 2, date: DateTime(2021, 9, 1), value: 30, notes: ''),
MeasurementEntry(id: 4, category: 2, date: DateTime(2021, 9, 5), value: 40, notes: ''),
]),
MeasurementCategory(
id: 1,
name: 'body fat',
unit: '%',
entries: [
MeasurementEntry(id: 1, category: 1, date: DateTime(2021, 9, 1), value: 10, notes: ''),
MeasurementEntry(id: 2, category: 1, date: DateTime(2021, 9, 5), value: 11, notes: ''),
],
),
MeasurementCategory(
id: 2,
name: 'biceps',
unit: 'cm',
entries: [
MeasurementEntry(id: 3, category: 2, date: DateTime(2021, 9, 1), value: 30, notes: ''),
MeasurementEntry(id: 4, category: 2, date: DateTime(2021, 9, 5), value: 40, notes: ''),
],
),
]);
});

View File

@@ -17,10 +17,10 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/measurements/measurement_category.dart';
import 'package:wger/models/measurements/measurement_entry.dart';
import 'package:wger/providers/measurement.dart';
@@ -37,10 +37,21 @@ void main() {
setUp(() {
mockMeasurementProvider = MockMeasurementProvider();
when(mockMeasurementProvider.findCategoryById(any)).thenReturn(
MeasurementCategory(id: 1, name: 'body fat', unit: '%', entries: [
MeasurementEntry(id: 1, category: 1, date: DateTime(2021, 8, 1), value: 10.2, notes: ''),
MeasurementEntry(id: 1, category: 1, date: DateTime(2021, 8, 10), value: 18.1, notes: 'a'),
]),
MeasurementCategory(
id: 1,
name: 'body fat',
unit: '%',
entries: [
MeasurementEntry(id: 1, category: 1, date: DateTime(2021, 8, 1), value: 10.2, notes: ''),
MeasurementEntry(
id: 1,
category: 1,
date: DateTime(2021, 8, 10),
value: 18.1,
notes: 'a',
),
],
),
);
mockNutritionPlansProvider = MockNutritionPlansProvider();

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/widgets/nutrition/charts.dart';
import 'package:wger/widgets/nutrition/nutritional_diary_detail.dart';

View File

@@ -18,13 +18,13 @@
import 'package:clock/clock.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/helpers/json.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/meal.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/providers/nutrition.dart';
@@ -61,9 +61,7 @@ void main() {
supportedLocales: AppLocalizations.supportedLocales,
navigatorKey: key,
home: Scaffold(body: MealForm("1", meal)),
routes: {
NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen(),
},
routes: {NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen()},
),
);
}
@@ -81,11 +79,7 @@ void main() {
await tester.pumpWidget(createFormScreen(meal1));
await tester.pumpAndSettle();
expect(
find.text('17:00'),
findsOneWidget,
reason: 'Time of existing meal is filled in',
);
expect(find.text('17:00'), findsOneWidget, reason: 'Time of existing meal is filled in');
expect(
find.text('Initial Name 1'),

View File

@@ -2,7 +2,6 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:http/http.dart' as http;
@@ -10,6 +9,7 @@ import 'package:mockito/mockito.dart';
import 'package:network_image_mock/network_image_mock.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/ingredient_api.dart';
import 'package:wger/models/nutrition/ingredient.dart';
import 'package:wger/models/nutrition/meal.dart';
@@ -74,14 +74,17 @@ void main() {
when(mockNutrition.searchIngredientWithCode('123')).thenAnswer((_) => Future.value(ingredient));
when(mockNutrition.searchIngredientWithCode('')).thenAnswer((_) => Future.value(null));
when(mockNutrition.searchIngredientWithCode('222')).thenAnswer((_) => Future.value(null));
when(mockNutrition.searchIngredient(
any,
languageCode: anyNamed('languageCode'),
searchEnglish: anyNamed('searchEnglish'),
)).thenAnswer(
when(
mockNutrition.searchIngredient(
any,
languageCode: anyNamed('languageCode'),
searchEnglish: anyNamed('searchEnglish'),
),
).thenAnswer(
(_) => Future.value(
IngredientApiSearch.fromJson(json.decode(fixture('nutrition/ingredient_suggestions')))
.suggestions,
IngredientApiSearch.fromJson(
json.decode(fixture('nutrition/ingredient_suggestions')),
).suggestions,
),
);
@@ -104,9 +107,7 @@ void main() {
MealItemForm(meal, const [], code, test),
),
),
routes: {
NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen(),
},
routes: {NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen()},
),
);
}
@@ -294,40 +295,41 @@ void main() {
expect(find.text('Please enter a valid number'), findsOneWidget);
});
testWidgets(
'save complete ingredient with correct weight input type',
(WidgetTester tester) async {
await tester.pumpWidget(createMealItemFormScreen(meal1, '123', true));
testWidgets('save complete ingredient with correct weight input type', (
WidgetTester tester,
) async {
await tester.pumpWidget(createMealItemFormScreen(meal1, '123', true));
final IngredientFormState formState = tester.state(find.byType(IngredientForm));
final IngredientFormState formState = tester.state(find.byType(IngredientForm));
await tester.tap(find.byKey(const Key('scan-button')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('scan-button')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('ingredient-scan-result-dialog')), findsOneWidget);
expect(find.byKey(const Key('ingredient-scan-result-dialog')), findsOneWidget);
await tester.tap(find.byKey(const Key('ingredient-scan-result-dialog-confirm-button')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('ingredient-scan-result-dialog-confirm-button')));
await tester.pumpAndSettle();
expect(formState.ingredientIdController.text, '1');
expect(formState.ingredientIdController.text, '1');
await tester.enterText(find.byKey(const Key('field-weight')), '2');
await tester.enterText(find.byKey(const Key('field-weight')), '2');
// once ID and weight are set, it'll fetchIngredient and show macros preview and ingredient image
when(mockNutrition.fetchIngredient(1)).thenAnswer((_) => Future.value(
Ingredient.fromJson(jsonDecode(fixture('nutrition/ingredientinfo_59887.json'))),
));
await mockNetworkImagesFor(() => tester.pumpAndSettle());
// once ID and weight are set, it'll fetchIngredient and show macros preview and ingredient image
when(mockNutrition.fetchIngredient(1)).thenAnswer(
(_) => Future.value(
Ingredient.fromJson(jsonDecode(fixture('nutrition/ingredientinfo_59887.json'))),
),
);
await mockNetworkImagesFor(() => tester.pumpAndSettle());
expect(find.byKey(const Key('ingredient-scan-result-dialog')), findsNothing);
expect(find.byKey(const Key('ingredient-scan-result-dialog')), findsNothing);
await tester.tap(find.byKey(const Key(SUBMIT_BUTTON_KEY_NAME)));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key(SUBMIT_BUTTON_KEY_NAME)));
await tester.pumpAndSettle();
expect(formState.mealItem.amount, 2);
expect(formState.mealItem.amount, 2);
verify(mockNutrition.addMealItem(any, meal1));
},
);
verify(mockNutrition.addMealItem(any, meal1));
});
});
}

View File

@@ -17,12 +17,12 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/screens/nutritional_plan_screen.dart';
@@ -59,9 +59,7 @@ void main() {
supportedLocales: AppLocalizations.supportedLocales,
navigatorKey: key,
home: Scaffold(body: PlanForm(plan)),
routes: {
NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen(),
},
routes: {NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen()},
),
);
}

View File

@@ -18,13 +18,13 @@
import 'package:drift/native.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:golden_toolkit/golden_toolkit.dart';
import 'package:http/http.dart' as http;
import 'package:mockito/annotations.dart';
import 'package:provider/provider.dart';
import 'package:wger/database/ingredients/ingredients_database.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/auth.dart';
import 'package:wger/providers/base_provider.dart';
import 'package:wger/providers/body_weight.dart';
@@ -54,11 +54,7 @@ void main() {
return MultiProvider(
providers: [
ChangeNotifierProvider<NutritionPlansProvider>(
create: (context) => NutritionPlansProvider(
mockBaseProvider,
[],
database: database,
),
create: (context) => NutritionPlansProvider(mockBaseProvider, [], database: database),
),
ChangeNotifierProvider<BodyWeightProvider>(
create: (context) => BodyWeightProvider(mockBaseProvider),
@@ -82,64 +78,59 @@ void main() {
);
}
testGoldens(
'Test the widgets on the nutritional plan screen',
(tester) async {
await loadAppFonts();
final globalKey = GlobalKey();
await tester.pumpWidgetBuilder(
Material(key: globalKey),
wrapper: materialAppWrapper(
localizations: [AppLocalizations.delegate],
),
surfaceSize: const Size(500, 1000),
);
await tester.pumpWidget(createNutritionalPlan());
await tester.tap(find.byType(TextButton));
await tester.pumpAndSettle();
testGoldens('Test the widgets on the nutritional plan screen', (tester) async {
await loadAppFonts();
final globalKey = GlobalKey();
await tester.pumpWidgetBuilder(
Material(key: globalKey),
wrapper: materialAppWrapper(localizations: [AppLocalizations.delegate]),
surfaceSize: const Size(500, 1000),
);
await tester.pumpWidget(createNutritionalPlan());
await tester.tap(find.byType(TextButton));
await tester.pumpAndSettle();
await screenMatchesGolden(tester, 'nutritional_plan_1_default_view');
await screenMatchesGolden(tester, 'nutritional_plan_1_default_view');
// Default view shows plan description, info button, and no ingredients
expect(find.text('Less fat, more protein'), findsOneWidget);
expect(find.byIcon(Icons.info_outline), findsNWidgets(3)); // 2 meals, 1 "other logs"
expect(find.byIcon(Icons.info), findsNothing);
expect(find.text('100g Water'), findsNothing);
expect(find.text('75g Burger soup'), findsNothing);
// Default view shows plan description, info button, and no ingredients
expect(find.text('Less fat, more protein'), findsOneWidget);
expect(find.byIcon(Icons.info_outline), findsNWidgets(3)); // 2 meals, 1 "other logs"
expect(find.byIcon(Icons.info), findsNothing);
expect(find.text('100g Water'), findsNothing);
expect(find.text('75g Burger soup'), findsNothing);
// tap the first info button changes it and reveals ingredients for the first meal
var infoOutlineButtons = find.byIcon(Icons.info_outline);
await tester.tap(infoOutlineButtons.first); // 2nd button shows up also, but is off-screen
await tester.pumpAndSettle();
await screenMatchesGolden(tester, 'nutritional_plan_2_one_meal_with_ingredients');
// tap the first info button changes it and reveals ingredients for the first meal
var infoOutlineButtons = find.byIcon(Icons.info_outline);
await tester.tap(infoOutlineButtons.first); // 2nd button shows up also, but is off-screen
await tester.pumpAndSettle();
await screenMatchesGolden(tester, 'nutritional_plan_2_one_meal_with_ingredients');
// Ingredients show up now
expect(find.text('100g Water'), findsOneWidget);
expect(find.text('75g Burger soup'), findsOneWidget);
// Ingredients show up now
expect(find.text('100g Water'), findsOneWidget);
expect(find.text('75g Burger soup'), findsOneWidget);
// .. and the button icon has changed
expect(find.byIcon(Icons.info_outline), findsNWidgets(2));
expect(find.byIcon(Icons.info), findsOneWidget);
// .. and the button icon has changed
expect(find.byIcon(Icons.info_outline), findsNWidgets(2));
expect(find.byIcon(Icons.info), findsOneWidget);
// the goals widget pushes this content down a bit.
// let's first find our icon (note: the previous icon no longer matches)
infoOutlineButtons = find.byIcon(Icons.info_outline);
// the goals widget pushes this content down a bit.
// let's first find our icon (note: the previous icon no longer matches)
infoOutlineButtons = find.byIcon(Icons.info_outline);
await tester.scrollUntilVisible(infoOutlineButtons.first, 30);
expect(find.text('300g Broccoli cake'), findsNothing);
await tester.scrollUntilVisible(infoOutlineButtons.first, 30);
expect(find.text('300g Broccoli cake'), findsNothing);
await tester.tap(infoOutlineButtons.first);
await tester.pumpAndSettle();
await screenMatchesGolden(tester, 'nutritional_plan_3_both_meals_with_ingredients');
expect(find.byIcon(Icons.info_outline), findsOneWidget);
expect(find.byIcon(Icons.info), findsNWidgets(2));
await tester.tap(infoOutlineButtons.first);
await tester.pumpAndSettle();
await screenMatchesGolden(tester, 'nutritional_plan_3_both_meals_with_ingredients');
expect(find.byIcon(Icons.info_outline), findsOneWidget);
expect(find.byIcon(Icons.info), findsNWidgets(2));
await tester.scrollUntilVisible(find.text('300g Broccoli cake'), 30);
expect(find.text('300g Broccoli cake'), findsOneWidget);
await tester.scrollUntilVisible(find.text('300g Broccoli cake'), 30);
expect(find.text('300g Broccoli cake'), findsOneWidget);
expect(find.byType(Card), findsNWidgets(3));
},
);
expect(find.byType(Card), findsNWidgets(3));
});
testWidgets('Tests the localization of times - EN', (WidgetTester tester) async {
await tester.pumpWidget(createNutritionalPlan());

View File

@@ -18,13 +18,13 @@
import 'package:drift/native.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http/http.dart' as http;
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/database/ingredients/ingredients_database.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/providers/auth.dart';
import 'package:wger/providers/base_provider.dart';
@@ -51,34 +51,29 @@ void main() {
});
Widget createHomeScreen({locale = 'en'}) {
when(client.delete(any, headers: anyNamed('headers')))
.thenAnswer((_) async => http.Response('', 200));
when(
client.delete(any, headers: anyNamed('headers')),
).thenAnswer((_) async => http.Response('', 200));
when(mockBaseProvider.deleteRequest(any, any)).thenAnswer(
(_) async => http.Response('', 200),
);
when(mockBaseProvider.deleteRequest(any, any)).thenAnswer((_) async => http.Response('', 200));
when(mockAuthProvider.token).thenReturn('1234');
when(mockAuthProvider.serverUrl).thenReturn('http://localhost');
when(mockAuthProvider.getAppNameHeader()).thenReturn('wger app');
return ChangeNotifierProvider<NutritionPlansProvider>(
create: (context) => NutritionPlansProvider(
mockBaseProvider,
[
NutritionalPlan(
id: 'deadbeefa',
description: 'test plan 1',
creationDate: DateTime(2021, 01, 01),
),
NutritionalPlan(
id: 'deadbeefb',
description: 'test plan 2',
creationDate: DateTime(2021, 01, 10),
),
],
database: database,
),
create: (context) => NutritionPlansProvider(mockBaseProvider, [
NutritionalPlan(
id: 'deadbeefa',
description: 'test plan 1',
creationDate: DateTime(2021, 01, 01),
),
NutritionalPlan(
id: 'deadbeefb',
description: 'test plan 2',
creationDate: DateTime(2021, 01, 10),
),
], database: database),
child: MaterialApp(
locale: Locale(locale),
localizationsDelegates: AppLocalizations.localizationsDelegates,

View File

@@ -17,8 +17,8 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/body_weight/weight_entry.dart';
import 'package:wger/widgets/weight/forms.dart';

View File

@@ -17,11 +17,11 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/providers/user.dart';

View File

@@ -17,11 +17,11 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/base_provider.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/workout_plans.dart';
@@ -45,11 +45,8 @@ void main() {
Widget createHomeScreen({locale = 'en'}) {
return ChangeNotifierProvider<WorkoutPlansProvider>(
create: (context) => WorkoutPlansProvider(
mockBaseProvider,
mockExerciseProvider,
[workoutPlan],
),
create: (context) =>
WorkoutPlansProvider(mockBaseProvider, mockExerciseProvider, [workoutPlan]),
child: ChangeNotifierProvider<ExercisesProvider>(
create: (context) => mockExerciseProvider,
child: MaterialApp(
@@ -66,9 +63,7 @@ void main() {
),
child: const SizedBox(),
),
routes: {
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
},
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
),
),
);

View File

@@ -17,11 +17,11 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/repetition_unit.dart';
import 'package:wger/models/workouts/setting.dart';
import 'package:wger/providers/workout_plans.dart';
@@ -65,9 +65,7 @@ void main() {
supportedLocales: AppLocalizations.supportedLocales,
navigatorKey: key,
home: Scaffold(body: RepetitionUnitInputWidget(setting1)),
routes: {
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
},
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
),
);
}

View File

@@ -17,11 +17,11 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/setting.dart';
import 'package:wger/models/workouts/weight_unit.dart';
import 'package:wger/providers/body_weight.dart';
@@ -66,9 +66,7 @@ void main() {
supportedLocales: AppLocalizations.supportedLocales,
navigatorKey: key,
home: Scaffold(body: WeightUnitInputWidget(setting1)),
routes: {
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
},
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
),
);
}

View File

@@ -17,12 +17,12 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/day.dart';
import 'package:wger/models/workouts/workout_plan.dart';
import 'package:wger/providers/workout_plans.dart';

View File

@@ -17,12 +17,12 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/workout_plan.dart';
import 'package:wger/providers/workout_plans.dart';
import 'package:wger/screens/workout_plan_screen.dart';
@@ -45,8 +45,9 @@ void main() {
setUp(() {
mockWorkoutPlans = MockWorkoutPlansProvider();
when(mockWorkoutPlans.editWorkout(any)).thenAnswer((_) => Future.value(existingPlan));
when(mockWorkoutPlans.fetchAndSetWorkoutPlanFull(any))
.thenAnswer((_) => Future.value(existingPlan));
when(
mockWorkoutPlans.fetchAndSetWorkoutPlanFull(any),
).thenAnswer((_) => Future.value(existingPlan));
});
Widget createHomeScreen(WorkoutPlan workoutPlan, {locale = 'en'}) {
@@ -60,9 +61,7 @@ void main() {
supportedLocales: AppLocalizations.supportedLocales,
navigatorKey: key,
home: Scaffold(body: WorkoutForm(workoutPlan)),
routes: {
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
},
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
),
);
}
@@ -79,11 +78,7 @@ void main() {
await tester.pumpWidget(createHomeScreen(existingPlan));
await tester.pumpAndSettle();
expect(
find.text('test 1'),
findsOneWidget,
reason: 'Name of existing workout plan',
);
expect(find.text('test 1'), findsOneWidget, reason: 'Name of existing workout plan');
expect(
find.text('description 1'),
findsOneWidget,

View File

@@ -18,11 +18,11 @@
import 'package:drift/native.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:provider/provider.dart';
import 'package:wger/database/exercises/exercise_database.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/base_provider.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/workout_plans.dart';
@@ -57,9 +57,7 @@ void main() {
),
child: const SizedBox(),
),
routes: {
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
},
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
),
);
}

View File

@@ -18,13 +18,13 @@
import 'package:drift/native.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http/http.dart' as http;
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/database/exercises/exercise_database.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/workout_plan.dart';
import 'package:wger/providers/base_provider.dart';
import 'package:wger/providers/exercises.dart';
@@ -49,23 +49,15 @@ void main() {
});
Widget createHomeScreen({locale = 'en'}) {
final uri = Uri(
scheme: 'https',
host: 'localhost',
path: 'api/v2/workout/',
);
final uri = Uri(scheme: 'https', host: 'localhost', path: 'api/v2/workout/');
when(mockBaseProvider.makeUrl('workout', query: anyNamed('query'))).thenReturn(uri);
when(mockBaseProvider.deleteRequest(any, any)).thenAnswer((_) async => http.Response('', 204));
return ChangeNotifierProvider<WorkoutPlansProvider>(
create: (context) => WorkoutPlansProvider(
mockBaseProvider,
testExercisesProvider,
[
WorkoutPlan(id: 1, creationDate: DateTime(2021, 01, 01), name: 'test 1'),
WorkoutPlan(id: 2, creationDate: DateTime(2021, 02, 12), name: 'test 2'),
],
),
create: (context) => WorkoutPlansProvider(mockBaseProvider, testExercisesProvider, [
WorkoutPlan(id: 1, creationDate: DateTime(2021, 01, 01), name: 'test 1'),
WorkoutPlan(id: 2, creationDate: DateTime(2021, 02, 12), name: 'test 2'),
]),
child: MaterialApp(
locale: Locale(locale),
localizationsDelegates: AppLocalizations.localizationsDelegates,

View File

@@ -17,12 +17,12 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/day.dart';
import 'package:wger/models/workouts/set.dart';
import 'package:wger/models/workouts/setting.dart';
@@ -51,11 +51,8 @@ void main() {
Widget createHomeScreen({locale = 'en'}) {
return ChangeNotifierProvider<WorkoutPlansProvider>(
create: (context) => WorkoutPlansProvider(
mockBaseProvider,
mockExerciseProvider,
[workoutPlan],
),
create: (context) =>
WorkoutPlansProvider(mockBaseProvider, mockExerciseProvider, [workoutPlan]),
child: ChangeNotifierProvider<ExercisesProvider>(
create: (context) => mockExerciseProvider,
child: MaterialApp(
@@ -84,11 +81,13 @@ void main() {
when(mockWorkoutPlans.addSet(any)).thenAnswer((_) => Future.value(Set.empty()));
when(mockWorkoutPlans.addSetting(any)).thenAnswer((_) => Future.value(Setting.empty()));
when(mockWorkoutPlans.fetchSmartText(any, any)).thenAnswer((_) => Future.value('2 x 10'));
when(mockExerciseProvider.searchExercise(
any,
languageCode: anyNamed('languageCode'),
searchEnglish: anyNamed('searchEnglish'),
)).thenAnswer((_) => Future.value([getTestExercises().first]));
when(
mockExerciseProvider.searchExercise(
any,
languageCode: anyNamed('languageCode'),
searchEnglish: anyNamed('searchEnglish'),
),
).thenAnswer((_) => Future.value([getTestExercises().first]));
await tester.pumpWidget(createHomeScreen());
await tester.pumpAndSettle();