diff --git a/AUTHORS.md b/AUTHORS.md index fa2d2b87..c33249f4 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -10,6 +10,7 @@ * Khushbu Bora - * Patrick Witter - * Tomer Ben-Rachel - +* Thilina Herath - ## Translators diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 1ab7d1e8..3f1e32ed 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -475,5 +475,9 @@ "takePicture": "Take a picture", "chooseFromLibrary": "Choose from photo library", "gallery": "Gallery", - "addImage": "Add image" + "addImage": "Add image", + "dataCopied": "Data copied to new entry", + "@dataCopied": { + "description": "Snackbar message to show on copying data to a new log entry" + } } diff --git a/lib/l10n/app_he.arb b/lib/l10n/app_he.arb new file mode 100644 index 00000000..f11ed425 --- /dev/null +++ b/lib/l10n/app_he.arb @@ -0,0 +1,490 @@ +{ + "sameRepetitions": "אם אתם משתמשים באותה כמות של חזרות ומשקל עבור כל הסטים, ניתן למלא רק שורה אחת. למשל עבור 4 סטים, הזינו 10 עבור חזרות, ואוטומטית הערך יהיה \"4x10\".", + "@sameRepetitions": {}, + "equipment": "ציוד", + "@equipment": { + "description": "Equipment needed to perform an exercise" + }, + "login": "כניסה", + "@login": { + "description": "Text for login button" + }, + "logout": "יציאה", + "@logout": { + "description": "Text for logout button" + }, + "useCustomServer": "שימוש בשרת מותאם אישית", + "@useCustomServer": { + "description": "Toggle button allowing users to switch between the default and a custom wger server" + }, + "invalidUrl": "אנא הכנס/י כתובת URL תקינה", + "@invalidUrl": { + "description": "Error message when the user enters an invalid URL, e.g. in the login form" + }, + "usernameValidChars": "שם משתמש יכול רק להכיל אותיות, ספרות ואת התווים @, +, ., - ו _", + "@usernameValidChars": { + "description": "Error message when the user tries to register a username with forbidden characters" + }, + "passwordTooShort": "הסיסמא קצרה מדי", + "@passwordTooShort": { + "description": "Error message when the user a password that is too short" + }, + "password": "סיסמא", + "@password": {}, + "confirmPassword": "אשר סיסמא", + "@confirmPassword": {}, + "customServerUrl": "כתובת של ישות ווגר", + "@customServerUrl": { + "description": "Label in the form where the users can enter their own wger instance" + }, + "invalidUsername": "אנא הכנס שם משתמש תקין", + "@invalidUsername": { + "description": "Error message when the user enters an invalid username" + }, + "customServerHint": "הכנס את הכתובת של השרת שלך, אחת שרת ברירת המחדל יהיה בשימוש", + "@customServerHint": { + "description": "Hint text for the form where the users can enter their own wger instance" + }, + "labelWorkoutLogs": "יומני אימון", + "@labelWorkoutLogs": { + "description": "(Workout) logs" + }, + "labelWorkoutPlan": "תוכנית כושר", + "@labelWorkoutPlan": { + "description": "Title for screen workout plan" + }, + "labelDashboard": "לוח פעולות", + "@labelDashboard": { + "description": "Title for screen dashboard" + }, + "successfullyDeleted": "נמחק", + "@successfullyDeleted": { + "description": "Message when an item was successfully deleted" + }, + "successfullySaved": "נשמר", + "@successfullySaved": { + "description": "Message when an item was successfully saved" + }, + "exercise": "תרגיל כושר", + "@exercise": { + "description": "An exercise for a workout" + }, + "searchExercise": "חיפוש תרגיל כושר להוספה", + "@searchExercise": { + "description": "Label on set form. Selected exercises are added to the set" + }, + "supersetWith": "סט תרגילים ראשי עם", + "@supersetWith": { + "description": "Text used between exercise cards when adding a new set. Translate as something like 'in a superset with'" + }, + "muscles": "שרירים", + "@muscles": { + "description": "(main) muscles trained by an exercise" + }, + "musclesSecondary": "שרירים משניים", + "@musclesSecondary": { + "description": "secondary muscles trained by an exercise" + }, + "category": "קטגוריה", + "@category": { + "description": "Category for an exercise, ingredient, etc." + }, + "newWorkout": "תוכנית כושר חדשה", + "@newWorkout": { + "description": "Header when adding a new workout" + }, + "noWorkoutPlans": "אין לך תוכניות כושר", + "@noWorkoutPlans": { + "description": "Message shown when the user has no workout plans" + }, + "repetitions": "חזרות", + "@repetitions": { + "description": "Repetitions for an exercise set" + }, + "reps": "חזרות", + "@reps": { + "description": "Shorthand for repetitions, used when space constraints are tighter" + }, + "rir": "חזרות בעתודה", + "@rir": { + "description": "Shorthand for Repetitions In Reserve" + }, + "rirNotUsed": "חזרות בעתודה שלא שומשו", + "@rirNotUsed": { + "description": "Label used in RiR slider when the RiR value is not used/saved for the current setting or log" + }, + "weightUnit": "יחידת משקל", + "@weightUnit": {}, + "repetitionUnit": "יחידת חזרה", + "@repetitionUnit": {}, + "set": "סט", + "@set": { + "description": "A set in a workout plan" + }, + "dayDescriptionHelp": "תיאור של מה נעשה ביום זה (למשל ,יום משיכה') או אילו חלקי גוף יהיו באימון (למשל 'חזה וכתפיים')", + "@dayDescriptionHelp": {}, + "setNr": "סט מספר", + "@setNr": { + "description": "Header in form indicating the number of the current set. Can also be translated as something like 'Set Nr. xy'.", + "type": "text", + "placeholders": { + "nr": {} + } + }, + "impression": "התרשמות", + "@impression": { + "description": "General impression (e.g. for a workout session) such as good, bad, etc." + }, + "notes": "הערות", + "@notes": { + "description": "Personal notes, e.g. for a workout session" + }, + "workoutSession": "אימון", + "@workoutSession": { + "description": "A (logged) workout session" + }, + "newDay": "יום חדש", + "@newDay": {}, + "newSet": "סט חדש", + "@newSet": { + "description": "Header when adding a new set to a workout day" + }, + "plateCalculator": "צלחות", + "@plateCalculator": { + "description": "Label used for the plate calculator in the gym mode" + }, + "pause": "השהה", + "@pause": { + "description": "Noun, not an imperative! Label used for the pause when using the gym mode" + }, + "jumpTo": "עבור ל", + "@jumpTo": { + "description": "Imperative. Label used in popup allowing the user to jump to a specific exercise while in the gym mode" + }, + "todaysWorkout": "האימון שלך היום", + "@todaysWorkout": {}, + "description": "תיאור", + "@description": {}, + "addSet": "הוספת סט", + "@addSet": { + "description": "Label for the button that adds a set (to a workout day)" + }, + "addMeal": "הוספת ארוחה", + "@addMeal": {}, + "mealLogged": "ארוחה הוכנסה ליומן", + "@mealLogged": {}, + "addIngredient": "הוספת מרכיב", + "@addIngredient": {}, + "nutritionalPlan": "תוכנית תזונה", + "@nutritionalPlan": {}, + "nutritionalDiary": "יומן תזונה", + "@nutritionalDiary": {}, + "nutritionalPlans": "תוכניות תזונה", + "@nutritionalPlans": {}, + "noNutritionalPlans": "אין לך תוכניות תזונה", + "@noNutritionalPlans": { + "description": "Message shown when the user has no nutritional plans" + }, + "anErrorOccurred": "שגיאה קרתה!", + "@anErrorOccurred": {}, + "weight": "משקל", + "@weight": { + "description": "The weight of a workout log or body weight entry" + }, + "measurement": "מדידה", + "@measurement": {}, + "measurements": "מדידות", + "@measurements": { + "description": "Categories for the measurements such as biceps size, body fat, etc." + }, + "measurementCategoriesHelpText": "קטגורית מדידה, כמו 'שריר הזרוע' או 'שומן גוף'", + "@measurementCategoriesHelpText": {}, + "measurementEntriesHelpText": "היחידה שמשתמשים למדוד את הקטגוריה כגון 'ס\"מ' או '%'", + "@measurementEntriesHelpText": {}, + "date": "תאריך", + "@date": { + "description": "The date of a workout log or body weight entry" + }, + "value": "ערך", + "@value": { + "description": "The value of a measurement entry" + }, + "start": "התחל", + "@start": { + "description": "Label on button to start the gym mode (i.e., an imperative)" + }, + "time": "זמן", + "@time": { + "description": "The time of a meal or workout" + }, + "timeStart": "זמן התחלה", + "@timeStart": { + "description": "The starting time of a workout" + }, + "timeEnd": "זמן סיום", + "@timeEnd": { + "description": "The end time of a workout" + }, + "timeStartAhead": "זמן התחלה לא יכול להיות אחרי זמן סיום", + "@timeStartAhead": {}, + "ingredient": "מרכיב", + "@ingredient": {}, + "energy": "אנרגיה", + "@energy": { + "description": "Energy in a meal, ingredient etc. e.g. in kJ" + }, + "logMeal": "רשום את הארוחה הזאת", + "@logMeal": {}, + "logHelpEntriesUnits": "שים לב שרק רשומות עם יחידת משקל (ק\"ג או ליברות) וחזרות הן ממופות, ישנה התעלמות משילובים אחרים כגון זמן או עד כשלון.", + "@logHelpEntriesUnits": {}, + "kcal": "kcal", + "@kcal": { + "description": "Energy in a meal in kilocalories, kcal" + }, + "kJ": "kJ", + "@kJ": { + "description": "Energy in a meal in kilo joules, kJ" + }, + "planned": "מתוכנן", + "@planned": { + "description": "Header for the column of 'planned' nutritional values, i.e. what should be eaten" + }, + "difference": "הבדל", + "@difference": {}, + "percentEnergy": "אחוז של אנרגיה", + "@percentEnergy": {}, + "total": "סה\"כ", + "@total": { + "description": "Label used for total sums of e.g. calories or similar" + }, + "g": "גרם", + "@g": { + "description": "Abbreviation for gram" + }, + "protein": "חלבון", + "@protein": {}, + "logged": "נרשם", + "@logged": { + "description": "Header for the column of 'logged' nutritional values, i.e. what was eaten" + }, + "carbohydrates": "פחמימות", + "@carbohydrates": {}, + "sugars": "סוכרים", + "@sugars": {}, + "fat": "שומן", + "@fat": {}, + "saturatedFat": "שומן רווי", + "@saturatedFat": {}, + "fibres": "סיבים", + "@fibres": {}, + "sodium": "נתרן", + "@sodium": {}, + "amount": "כמות", + "@amount": { + "description": "The amount (e.g. in grams) of an ingredient in a meal" + }, + "unit": "יחידה", + "@unit": { + "description": "The unit used for a repetition (kg, time, etc.)" + }, + "newEntry": "רשומה חדשה", + "@newEntry": { + "description": "Title when adding a new entry such as a weight or log entry" + }, + "noWeightEntries": "אין לך רשומות של משקל", + "@noWeightEntries": { + "description": "Message shown when the user has no logged weight entries" + }, + "edit": "עריכה", + "@edit": {}, + "delete": "מחיקה", + "@delete": {}, + "confirmDelete": "האם את/ה בטוח/ה שאת/ה רוצה למחוק את '{אלמנט למחיקה}'?", + "@confirmDelete": { + "description": "Confirmation text before the user deletes an object", + "type": "text", + "placeholders": { + "toDelete": {} + } + }, + "newNutritionalPlan": "תוכנית תזונה חדשה", + "@newNutritionalPlan": {}, + "toggleDetails": "הסתר/הצג פירוט", + "@toggleDetails": { + "description": "Switch to toggle detail / overview" + }, + "goToDetailPage": "עבור לדף פירוט", + "@goToDetailPage": {}, + "aboutSourceTitle": "קוד מקור", + "@aboutSourceTitle": { + "description": "Title for source code section in the about dialog" + }, + "aboutContactUsTitle": "אמור שלום!", + "@aboutContactUsTitle": { + "description": "Title for contact us section in the about dialog" + }, + "aboutTranslationTitle": "תרגום", + "@aboutTranslationTitle": { + "description": "Title for translation section in the about dialog" + }, + "calendar": "לוח שנה", + "@calendar": {}, + "goToToday": "עבור להיום", + "@goToToday": { + "description": "Label on button to jump back to 'today' in the calendar widget" + }, + "enterValue": "אנא הכנס ערך", + "@enterValue": { + "description": "Error message when the user hasn't entered a value on a required field" + }, + "aboutSourceText": "לקבלת קוד המקור של אפליקציה זאת והשרת שלה בגיטהאב", + "@aboutSourceText": { + "description": "Text for source code section in the about dialog" + }, + "enterRepetitionsOrWeight": "אנא מלאו את החזרות או את המשקל בלפחות אחד מהסטים", + "@enterRepetitionsOrWeight": { + "description": "Error message when the user hasn't filled in the forms for exercise sets" + }, + "setUnitsAndRir": "יחידות סט וחזרות בעתודה", + "@setUnitsAndRir": { + "description": "Label shown on the slider where the user can toggle showing units and RiR", + "type": "text" + }, + "reset": "אתחול", + "@reset": { + "description": "Button text allowing the user to reset the entered values to the default" + }, + "loginInstead": "הכנס במקום", + "@loginInstead": {}, + "selectExercise": "אנא בחר/י אימון", + "@selectExercise": { + "description": "Error message when the user hasn't selected an exercise in the form" + }, + "enterCharacters": "אנא בחר/י ערך בין {מינימום} ו-{מקסימום} תווים", + "@enterCharacters": { + "description": "Error message when the user hasn't entered the correct number of characters in a form", + "type": "text", + "placeholders": { + "min": {}, + "max": {} + } + }, + "nrOfSets": "כמות סטים לאימון: {כמות}", + "@nrOfSets": { + "description": "Label shown on the slider where the user selects the nr of sets", + "type": "text", + "placeholders": { + "nrOfSets": {} + } + }, + "enterValidNumber": "אנא הכנס מספר תקין", + "@enterValidNumber": { + "description": "Error message when the user has submitted an invalid number (e.g. '3,.,.,.')" + }, + "selectIngredient": "אנא בחר מרכיב", + "@selectIngredient": { + "description": "Error message when the user hasn't selected an ingredient from the autocompleter" + }, + "selectImage": "אנא בחר תמונה", + "@selectImage": { + "description": "Label and error message when the user hasn't selected an image to save" + }, + "optionsLabel": "אפשרויות", + "@optionsLabel": { + "description": "Label for the popup with general app options" + }, + "takePicture": "צלם תמונה", + "@takePicture": {}, + "chooseFromLibrary": "בחר מספריית תמונות", + "@chooseFromLibrary": {}, + "gallery": "גלריה", + "@gallery": {}, + "addImage": "הוסף תמונה", + "@addImage": {}, + "email": "כתובת מייל", + "@email": {}, + "username": "שם משתמש", + "@username": {}, + "labelBottomNavNutrition": "תזונה", + "@labelBottomNavNutrition": { + "description": "Label used in bottom navigation, use a short word" + }, + "register": "הרשמה", + "@register": { + "description": "Text for registration button" + }, + "useDefaultServer": "שימוש בשרת ברירת מחדל", + "@useDefaultServer": { + "description": "Toggle button allowing users to switch between the default and a custom wger server" + }, + "passwordsDontMatch": "הסיסמאות לא תואמות", + "@passwordsDontMatch": { + "description": "Error message when the user enters two different passwords during registration" + }, + "invalidEmail": "אנא הכנס/י כתובת מייל תקינה", + "@invalidEmail": { + "description": "Error message when the user enters an invalid email" + }, + "registerInstead": "הרשם במקום", + "@registerInstead": {}, + "labelWorkoutPlans": "תוכניות כושר", + "@labelWorkoutPlans": { + "description": "Title for screen workout plans" + }, + "labelBottomNavWorkout": "כושר", + "@labelBottomNavWorkout": { + "description": "Label used in bottom navigation, use a short word" + }, + "comment": "הערה", + "@comment": { + "description": "Comment, additional information" + }, + "name": "שם", + "@name": { + "description": "Name for a workout or nutritional plan" + }, + "save": "שמירה", + "@save": {}, + "gymMode": "מצב חדש כושר", + "@gymMode": { + "description": "Label when starting the gym mode" + }, + "plateCalculatorNotDivisible": "לא אפשרי להגיע למשקל עם הצלחות הפנויות", + "@plateCalculatorNotDivisible": { + "description": "Error message when the current weight is not reachable with plates (e.g. 33.1 kg)" + }, + "macronutrients": "מקרונוטריאנטים", + "@macronutrients": {}, + "gPerBodyKg": "גרם עבור ק\"ג של משקל גוף", + "@gPerBodyKg": { + "description": "Label used for total sums of e.g. calories or similar in grams per Kg of body weight" + }, + "loadingText": "טוען...", + "@loadingText": { + "description": "Text to show when entries are being loaded in the background: Loading..." + }, + "aboutBugsTitle": "נתקלת בבעיה או יש לך רעיון?", + "@aboutBugsTitle": { + "description": "Title for bugs section in the about dialog" + }, + "aboutDescription": "תודה לך על השימוש בווגר! ווגר הוא פרויקט קוד פתוח שנעשה על ידי אוהבי כושר מרחבי העולם.", + "@aboutDescription": { + "description": "Text in the about dialog" + }, + "selectExercises": "אם ברצונך לבצע סופר סט ניתן לחפש כמה אימונים כך שהם יהיו מקובצים ביחד", + "@selectExercises": {}, + "logHelpEntries": "אם ביום אחד ישנה יותר מרשומה אחת עם אותה כמות חזרות, אבל משקל שונה, רק הרשומה עם המשקל הגבוה יותר תופיע בדיאגרמה.", + "@logHelpEntries": {}, + "aboutBugsText": "צרו קשר אם משהו לא מתנהג כצפוי או אם יש תכונה שאתם מרגישים בחוסרה.", + "@aboutBugsText": { + "description": "Text for bugs section in the about dialog" + }, + "aboutTranslationText": "האפליקציה הזאת מתורגמת ב-weblate. אם גם אתם רוצים לעזור, לחצו על הקישור ותתחילו לתרגם", + "@aboutTranslationText": { + "description": "Text for translation section in the about dialog" + }, + "aboutContactUsText": "אם אתם רוצים לדבר עמנו, אתם מוזמנים לגשת לשרת הדיסקורד וליצור עמנו קשר שם", + "@aboutContactUsText": { + "description": "Text for contact us section in the about dialog" + } +} diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index ed4e0e58..7edc9c26 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -122,5 +122,37 @@ "login": "Giriş yap", "@login": { "description": "Text for login button" - } + }, + "noWorkoutPlans": "Antrenman planınız yok", + "@noWorkoutPlans": { + "description": "Message shown when the user has no workout plans" + }, + "repetitions": "Tekrarlar", + "@repetitions": { + "description": "Repetitions for an exercise set" + }, + "reps": "Temsilciler", + "@reps": { + "description": "Shorthand for repetitions, used when space constraints are tighter" + }, + "repetitionUnit": "Tekrarlama birimi", + "@repetitionUnit": {}, + "set": "Ayarla", + "@set": { + "description": "A set in a workout plan" + }, + "supersetWith": "süper set ile", + "@supersetWith": { + "description": "Text used between exercise cards when adding a new set. Translate as something like 'in a superset with'" + }, + "newWorkout": "Yeni antrenman planı", + "@newWorkout": { + "description": "Header when adding a new workout" + }, + "rirNotUsed": "RiR kullanılmadı", + "@rirNotUsed": { + "description": "Label used in RiR slider when the RiR value is not used/saved for the current setting or log" + }, + "weightUnit": "Ağırlık birimi", + "@weightUnit": {} } diff --git a/lib/models/nutrition/meal.dart b/lib/models/nutrition/meal.dart index 433698aa..6b5f6543 100644 --- a/lib/models/nutrition/meal.dart +++ b/lib/models/nutrition/meal.dart @@ -36,6 +36,9 @@ class Meal { @JsonKey(toJson: timeToString, fromJson: stringToTime) TimeOfDay? time; + @JsonKey(name: 'name') + late String name; + @JsonKey(ignore: true, name: 'meal_items', defaultValue: []) List mealItems = []; @@ -43,6 +46,7 @@ class Meal { this.id, int? plan, TimeOfDay? time, + String? name, List? mealItems, }) { if (plan != null) { @@ -52,10 +56,12 @@ class Meal { this.mealItems = mealItems ?? []; this.time = time ?? TimeOfDay.now(); + this.name = name ?? ''; } // Boilerplate factory Meal.fromJson(Map json) => _$MealFromJson(json); + Map toJson() => _$MealToJson(this); /// Calculations diff --git a/lib/models/nutrition/meal.g.dart b/lib/models/nutrition/meal.g.dart index 20ced4e7..3d079787 100644 --- a/lib/models/nutrition/meal.g.dart +++ b/lib/models/nutrition/meal.g.dart @@ -10,6 +10,7 @@ Meal _$MealFromJson(Map json) { return Meal( id: json['id'] as int?, time: stringToTime(json['time'] as String?), + name: json['name'] as String?, )..planId = json['plan'] as int; } @@ -17,4 +18,5 @@ Map _$MealToJson(Meal instance) => { 'id': instance.id, 'plan': instance.planId, 'time': timeToString(instance.time), + 'name': instance.name, }; diff --git a/lib/widgets/nutrition/forms.dart b/lib/widgets/nutrition/forms.dart index 4c40ae68..f87aa94e 100644 --- a/lib/widgets/nutrition/forms.dart +++ b/lib/widgets/nutrition/forms.dart @@ -36,10 +36,12 @@ class MealForm extends StatelessWidget { final _form = GlobalKey(); final _timeController = TextEditingController(); + final _nameController = TextEditingController(); MealForm(this._planId, [meal]) { _meal = meal ?? Meal(plan: _planId); _timeController.text = timeToString(_meal.time)!; + _nameController.text = _meal.name; } @override @@ -71,6 +73,16 @@ class MealForm extends StatelessWidget { }, onFieldSubmitted: (_) {}, ), + TextFormField( + maxLength: 25, + key: Key('field-name'), + decoration: InputDecoration(labelText: AppLocalizations.of(context).name), + controller: _nameController, + onSaved: (newValue) { + _meal.name = newValue as String; + }, + onFieldSubmitted: (_) {}, + ), ElevatedButton( key: Key(SUBMIT_BUTTON_KEY_NAME), child: Text(AppLocalizations.of(context).save), diff --git a/lib/widgets/nutrition/meal.dart b/lib/widgets/nutrition/meal.dart index 32cd3bf4..b9300276 100644 --- a/lib/widgets/nutrition/meal.dart +++ b/lib/widgets/nutrition/meal.dart @@ -41,6 +41,7 @@ class MealWidget extends StatefulWidget { class _MealWidgetState extends State { bool _expanded = false; + void _toggleExpanded() { setState(() { _expanded = !_expanded; @@ -221,20 +222,30 @@ class DismissibleMealHeader extends StatelessWidget { child: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration(color: Colors.white), - child: Row( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Text( - _meal.time!.format(context), + if (_meal.name != '') + Text( + _meal.name, style: Theme.of(context).textTheme.headline5, ), - ), - IconButton( - visualDensity: VisualDensity.compact, - icon: _expanded ? Icon(Icons.unfold_less) : Icon(Icons.unfold_more), - onPressed: () { - _toggle(); - }, + Row( + children: [ + Expanded( + child: Text( + _meal.time!.format(context), + style: Theme.of(context).textTheme.headline5, + ), + ), + IconButton( + visualDensity: VisualDensity.compact, + icon: _expanded ? Icon(Icons.unfold_less) : Icon(Icons.unfold_more), + onPressed: () { + _toggle(); + }, + ), + ], ), ], ), diff --git a/lib/widgets/workouts/gym_mode.dart b/lib/widgets/workouts/gym_mode.dart index 164fd200..c3ba73e2 100644 --- a/lib/widgets/workouts/gym_mode.dart +++ b/lib/widgets/workouts/gym_mode.dart @@ -81,8 +81,7 @@ class _GymModeState extends State { for (final set in widget._workoutDay.sets) { var firstPage = true; for (final setting in set.settingsComputed) { - final exercise = - Provider.of(context, listen: false).findById(setting.exerciseId); + final exercise = Provider.of(context, listen: false).findById(setting.exerciseId); if (firstPage) { _exercisePages[exercise.name] = currentPage; @@ -151,8 +150,7 @@ class _GymModeState extends State { ), ...getContent(), SessionPage( - Provider.of(context, listen: false) - .findById(widget._workoutDay.workoutId), + Provider.of(context, listen: false).findById(widget._workoutDay.workoutId), _controller, widget._start, _exercisePages, @@ -506,8 +504,7 @@ class _LogPageState extends State { ...widget._workoutPlan.filterLogsByExercise(widget._exercise, unique: true).map((log) { return ListTile( title: Text(log.singleLogRepTextNoNl), - subtitle: - Text(DateFormat.yMd(Localizations.localeOf(context).languageCode).format(log.date)), + subtitle: Text(DateFormat.yMd(Localizations.localeOf(context).languageCode).format(log.date)), trailing: Icon(Icons.copy), onTap: () { setState(() { @@ -519,6 +516,10 @@ class _LogPageState extends State { widget._log.rir = log.rir; widget._log.repetitionUnit = log.repetitionUnitObj; widget._log.weightUnit = log.weightUnitObj; + + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(AppLocalizations.of(context).dataCopied))); }); }, contentPadding: EdgeInsets.symmetric(horizontal: 40), @@ -611,12 +612,10 @@ class _LogPageState extends State { ), SizedBox(height: 10), Expanded( - child: (widget._workoutPlan.filterLogsByExercise(widget._exercise).isNotEmpty) - ? getPastLogs() - : Container()), + child: + (widget._workoutPlan.filterLogsByExercise(widget._exercise).isNotEmpty) ? getPastLogs() : Container()), // Only show calculator for barbell - if (widget._log.exerciseObj.equipment.map((e) => e.id).contains(ID_EQUIPMENT_BARBELL)) - getPlates(), + if (widget._log.exerciseObj.equipment.map((e) => e.id).contains(ID_EQUIPMENT_BARBELL)) getPlates(), Padding( padding: const EdgeInsets.symmetric(horizontal: 15), child: Card( @@ -763,9 +762,7 @@ class _SessionPageState extends State { 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) { @@ -830,8 +827,7 @@ class _SessionPageState extends State { SizedBox(width: 10), Flexible( child: TextFormField( - decoration: - InputDecoration(labelText: AppLocalizations.of(context).timeEnd), + decoration: InputDecoration(labelText: AppLocalizations.of(context).timeEnd), controller: timeEndController, onFieldSubmitted: (_) {}, onTap: () async { @@ -869,8 +865,7 @@ class _SessionPageState extends State { // Save the entry on the server try { - await Provider.of(context, listen: false) - .addSession(_session); + await Provider.of(context, listen: false).addSession(_session); Navigator.of(context).pop(); } on WgerHttpException catch (error) { showHttpExceptionErrorDialog(error, context); @@ -977,8 +972,7 @@ class NavigationFooter extends StatelessWidget { final bool showPrevious; final bool showNext; - const NavigationFooter(this._controller, this._ratioCompleted, - {this.showPrevious = true, this.showNext = true}); + const NavigationFooter(this._controller, this._ratioCompleted, {this.showPrevious = true, this.showNext = true}); @override Widget build(BuildContext context) { diff --git a/test/nutritional_meal_form_test.dart b/test/nutritional_meal_form_test.dart index 6f351a3c..0c74c145 100644 --- a/test/nutritional_meal_form_test.dart +++ b/test/nutritional_meal_form_test.dart @@ -72,7 +72,7 @@ void main() { await tester.pumpWidget(createHomeScreen(meal1)); await tester.pumpAndSettle(); - expect(find.byType(TextFormField), findsOneWidget); + expect(find.byType(TextFormField), findsNWidgets(2)); expect(find.byType(ElevatedButton), findsOneWidget); expect(find.byKey(Key(SUBMIT_BUTTON_KEY_NAME)), findsOneWidget); }); @@ -86,7 +86,15 @@ void main() { findsOneWidget, reason: 'Time of existing meal is filled in', ); + + expect( + find.text(('Initial Name 1')), + findsOneWidget, + reason: 'Time of existing meal is filled in', + ); + await tester.enterText(find.byKey(Key('field-time')), '12:34'); + await tester.enterText(find.byKey(Key('field-name')), 'test meal'); await tester.tap(find.byKey(Key(SUBMIT_BUTTON_KEY_NAME))); // Correct method was called @@ -105,6 +113,7 @@ void main() { ); await tester.enterText(find.byKey(Key('field-time')), '08:00'); + await tester.enterText(find.byKey(Key('field-name')), 'test meal'); await tester.tap(find.byKey(Key(SUBMIT_BUTTON_KEY_NAME))); // Correct method was called diff --git a/test_data/nutritional_plans.dart b/test_data/nutritional_plans.dart index 488ee77a..3983b92b 100644 --- a/test_data/nutritional_plans.dart +++ b/test_data/nutritional_plans.dart @@ -86,6 +86,7 @@ NutritionalPlan getNutritionalPlan() { id: 1, plan: 1, time: TimeOfDay(hour: 17, minute: 0), + name: 'Initial Name 1', ); meal1.mealItems = [mealItem1, mealItem2]; @@ -93,6 +94,7 @@ NutritionalPlan getNutritionalPlan() { id: 2, plan: 1, time: TimeOfDay(hour: 22, minute: 5), + name: 'Initial Name 2', ); meal2.mealItems = [mealItem3];