diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4652ce6e..83d28538 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,8 +30,7 @@ jobs: - name: Test app run: flutter test --coverage - #- name: Upload coverage to Codecov - # uses: codecov/codecov-action@v1 - # with: - # token: ${{ secrets.CODECOV_TOKEN }} - # file: coverage/lcov.info + - name: Coveralls + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index a6c12794..293740c6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Mobile app for wger Workout Manager -wger is a free, open source flutter application that manages and tracks/logs -your exercises and personal workouts, weight and diet plans. This is the mobile +wger is a free, open-source flutter application that manages and tracks/logs +your exercises and personal workouts, weight, and diet plans. This is the mobile app written with Flutter, it talks via REST with the main server. If you want to contribute, hop on the Discord server and say hi! @@ -26,13 +26,13 @@ If you want to contribute, hop on the Discord server and say hi! ## Development ### 1 -Install the wger server, the easiest way is starting the development docker-compose: +Install the wger server, the easiest way is to start the development docker-compose: Alternatively, you can use one of our test servers, just ask us for access. ### 2 -Install Flutter, all its dependencies and create a new virtual device: +Install Flutter, and all its dependencies, and create a new virtual device: . The app currently uses flutter 2.10 @@ -45,10 +45,10 @@ WGER_API_KEY=123456 ``` To just run/develop the app it only needs to have any value for WGER_API_KEY, but -you need a correct value if you want to register via the app. For this you need -to allow (a probably dedicated) user on the wger server to register users in its +you need a correct value if you want to register via the app. For this, you need +to allow (a probably dedicated) user on the wger server to register users on its behalf. For this, generate an API KEY by visiting -on your local instance and then run ``python3 manage.py add-user-rest theusername`` +on your local instance and then run ``python3 manage.py add-user-rest the username`` You can later list all the registered users with: ``python3 manage.py list-users-api`` @@ -58,10 +58,10 @@ You can later list all the registered users with: ``python3 manage.py list-users ### 4 Start the application with ``flutter run`` or use your IDE -(please note that depending on how you run your emulator you will need to change the -IP address of the server) +(please note that depending on how you run your emulator you will need to change the IP address of the server) + +You can run the tests with the ``flutter test`` -You can run the tests with ``flutter test`` ## Translation Translate the app to your language on [Weblate](https://hosted.weblate.org/engage/wger/). @@ -70,7 +70,7 @@ Translate the app to your language on [Weblate](https://hosted.weblate.org/enga ## Contact -Feel free to get in touch if you found this useful or something didn't behave +Feel free to get in touch if you found this useful or if something didn't behave as expected. We can't fix what we don't know about, so please report liberally. If you're not sure if something is a bug or not, feel free to file a bug anyway. @@ -83,7 +83,7 @@ If you're not sure if something is a bug or not, feel free to file a bug anyway. The application is licensed under the GNU Affero General Public License 3 or later (AGPL 3+) with an app store exception. -As an additional permission under section 7, you are allowed to distribute the +As additional permission under section 7, you are allowed to distribute the software through an app store, even if that store has restrictive terms and conditions that are incompatible with the AGPL, provided that the source is also available under the AGPL with or without this permission through a channel without @@ -92,3 +92,4 @@ those restrictive terms and conditions. The initial exercise and ingredient data is licensed additionally under one of the Creative Commons licenses, see the individual exercises for more details. + diff --git a/fastlane/metadata/android/README.md b/fastlane/metadata/android/README.md index 934ba465..4b436265 100644 --- a/fastlane/metadata/android/README.md +++ b/fastlane/metadata/android/README.md @@ -1,6 +1,14 @@ # Release process -## 1. Dry-run release before uploading +## 1. Update flutter version + +If we use a new version, update the version used by + +* Github Actions in `android-release.yaml` in this repository +* Fdroid build recipe in [their repo](https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/de.wger.flutter.yml). + Since this can potentially take some time, it should happen well in advance + +## 2. Dry-run release before uploading * Increase build nr in pubspec.yaml * `flutter build appbundle --release` @@ -13,7 +21,7 @@ Also note that if a language was added over the weblate UI, it might be necessar to set the correct language code: -## 2. Push tags to trigger release +## 3. Push tags to trigger release Make sure that the commit that will be tagged was already pushed or didn't change any dart code, otherwise the automatic linter might push a "correction" commit @@ -25,6 +33,6 @@ by github actions. `TAG=vX.Y.Z && git tag $TAG && git push origin $TAG && git tag -d $TAG` -## 3. Edit release +## 4. Edit release I necessary, edit the created release on github diff --git a/lib/l10n/app_uk.arb b/lib/l10n/app_uk.arb index 8a27b681..44401795 100644 --- a/lib/l10n/app_uk.arb +++ b/lib/l10n/app_uk.arb @@ -38,5 +38,519 @@ "date": "Дата", "@date": { "description": "The date of a workout log or body weight entry" + }, + "usernameValidChars": "Ім'я користувача може містити лише літери, цифри й символи @, +, ., - та _", + "@usernameValidChars": { + "description": "Error message when the user tries to register a username with forbidden characters" + }, + "passwordsDontMatch": "Паролі не збігаються", + "@passwordsDontMatch": { + "description": "Error message when the user enters two different passwords during registration" + }, + "confirmPassword": "Підтвердьте пароль", + "@confirmPassword": {}, + "email": "Адреса електронної пошти", + "@email": {}, + "invalidUsername": "Будь ласка, введіть припустиме ім'я користувача", + "@invalidUsername": { + "description": "Error message when the user enters an invalid username" + }, + "username": "Ім'я користувача", + "@username": {}, + "customServerHint": "Введіть адресу свого власного сервера, інакше буде використовуватися сервер за промовчанням", + "@customServerHint": { + "description": "Hint text for the form where the users can enter their own wger instance" + }, + "reset": "Скинути", + "@reset": { + "description": "Button text allowing the user to reset the entered values to the default" + }, + "loginInstead": "Натомість увійти", + "@loginInstead": {}, + "labelWorkoutPlans": "Плани тренувань", + "@labelWorkoutPlans": { + "description": "Title for screen workout plans" + }, + "labelBottomNavWorkout": "Тренування", + "@labelBottomNavWorkout": { + "description": "Label used in bottom navigation, use a short word" + }, + "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" + }, + "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'" + }, + "equipment": "Обладнання", + "@equipment": { + "description": "Equipment needed to perform an exercise" + }, + "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" + }, + "repetitions": "Повторень", + "@repetitions": { + "description": "Repetitions for an exercise set" + }, + "reps": "Повтор", + "@reps": { + "description": "Shorthand for repetitions, used when space constraints are tighter" + }, + "rirNotUsed": "RiR не використовується", + "@rirNotUsed": { + "description": "Label used in RiR slider when the RiR value is not used/saved for the current setting or log" + }, + "repetitionUnit": "Одиниця повторень", + "@repetitionUnit": {}, + "set": "Набір", + "@set": { + "description": "A set in a workout plan" + }, + "setNr": "Набір {nr}", + "@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": {} + } + }, + "sameRepetitions": "Якщо ви робите однакові повторення та вагу для всіх наборів, то ви можете просто заповнити один рядок. Наприклад, для 4 наборів просто введіть 10 для повторень, це автоматично стане «4 x 10».", + "@sameRepetitions": {}, + "comment": "Коментар", + "@comment": { + "description": "Comment, additional information" + }, + "impression": "Враження", + "@impression": { + "description": "General impression (e.g. for a workout session) such as good, bad, etc." + }, + "newDay": "Новий день", + "@newDay": {}, + "selectExercises": "Якщо ви хочете зробити супер-набір, ви можете пошукати декілька вправ, вони будуть згруповані разом", + "@selectExercises": {}, + "gymMode": "Режим тренажерного залу", + "@gymMode": { + "description": "Label when starting the gym mode" + }, + "plateCalculator": "Пластини", + "@plateCalculator": { + "description": "Label used for the plate calculator in the gym mode" + }, + "plateCalculatorNotDivisible": "Неможливо досягти ваги з наявними пластинами", + "@plateCalculatorNotDivisible": { + "description": "Error message when the current weight is not reachable with plates (e.g. 33.1 kg)" + }, + "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": {}, + "password": "Пароль", + "@password": {}, + "passwordTooShort": "Пароль занадто короткий", + "@passwordTooShort": { + "description": "Error message when the user a password that is too short" + }, + "invalidEmail": "Будь ласка, введіть прийнятну адресу електронної пошти", + "@invalidEmail": { + "description": "Error message when the user enters an invalid email" + }, + "customServerUrl": "URL-адреса екземпляра wger", + "@customServerUrl": { + "description": "Label in the form where the users can enter their own wger instance" + }, + "successfullySaved": "Збережено", + "@successfullySaved": { + "description": "Message when an item was successfully saved" + }, + "registerInstead": "Натомість зареєструватися", + "@registerInstead": {}, + "labelBottomNavNutrition": "Харчування", + "@labelBottomNavNutrition": { + "description": "Label used in bottom navigation, use a short word" + }, + "weightUnit": "Одиниця ваги", + "@weightUnit": {}, + "noWorkoutPlans": "У вас немає планів тренувань", + "@noWorkoutPlans": { + "description": "Message shown when the user has no workout plans" + }, + "dayDescriptionHelp": "Опис того, що робиться в цей день (наприклад, «день підтягування») або які частини тіла тренуються (наприклад, «груди та плечі»)", + "@dayDescriptionHelp": {}, + "workoutSession": "Сеанс тренування", + "@workoutSession": { + "description": "A (logged) workout session" + }, + "notes": "Нотатки", + "@notes": { + "description": "Personal notes, e.g. for a workout session" + }, + "newSet": "Новий набір", + "@newSet": { + "description": "Header when adding a new set to a workout day" + }, + "measurementCategoriesHelpText": "Категорія вимірювання, така як \"біцепс\" або \"жир тіла\"", + "@measurementCategoriesHelpText": {}, + "time": "Час", + "@time": { + "description": "The time of a meal or workout" + }, + "value": "Значення", + "@value": { + "description": "The value of a measurement entry" + }, + "timeStart": "Час початку", + "@timeStart": { + "description": "The starting time of a workout" + }, + "timeEnd": "Час закінчення", + "@timeEnd": { + "description": "The end time of a workout" + }, + "kcal": "ккал", + "@kcal": { + "description": "Energy in a meal in kilocalories, kcal" + }, + "fat": "Жири", + "@fat": {}, + "newNutritionalPlan": "Новий план харчування", + "@newNutritionalPlan": {}, + "sugars": "Цукри", + "@sugars": {}, + "aboutDescription": "Дякуємо за використання wger! wger - це спільний проєкт з відкритим кодом, створений ентузіастами фітнесу з усього світу.", + "@aboutDescription": { + "description": "Text in the about dialog" + }, + "aboutBugsText": "Зв'яжіться з нами, якщо щось відбувається не так, як очікувалося, або якщо є функція, яка, на вашу думку, відсутня.", + "@aboutBugsText": { + "description": "Text for bugs section in the about dialog" + }, + "selectExercise": "Будь ласка, виберіть вправу", + "@selectExercise": { + "description": "Error message when the user hasn't selected an exercise in the form" + }, + "calendar": "Календар", + "@calendar": {}, + "enterValue": "Будь ласка, введіть значення", + "@enterValue": { + "description": "Error message when the user hasn't entered a value on a required field" + }, + "selectIngredient": "Будь ласка, оберіть інгредієнт", + "@selectIngredient": { + "description": "Error message when the user hasn't selected an ingredient from the autocompleter" + }, + "productFoundDescription": "Штрих-код відповідає цьому виробу: {productName}. Бажаєте продовжити?", + "@productFoundDescription": { + "description": "Dialog info when product is found with barcode", + "type": "text", + "placeholders": { + "productName": {} + } + }, + "description": "Опис", + "@description": {}, + "name": "Ім'я", + "@name": { + "description": "Name for a workout or nutritional plan" + }, + "save": "Зберегти", + "@save": {}, + "addSet": "Додати набір", + "@addSet": { + "description": "Label for the button that adds a set (to a workout day)" + }, + "addMeal": "Додати страву", + "@addMeal": {}, + "mealLogged": "Страву записано в щоденник", + "@mealLogged": {}, + "logMeal": "Записати цю страву", + "@logMeal": {}, + "addIngredient": "Додати інгредієнт", + "@addIngredient": {}, + "logIngredient": "Зберегти в щоденник харчування", + "@logIngredient": {}, + "searchIngredient": "Пошук інгредієнта", + "@searchIngredient": { + "description": "Label on ingredient search form" + }, + "nutritionalDiary": "Щоденник харчування", + "@nutritionalDiary": {}, + "nutritionalPlans": "Плани харчування", + "@nutritionalPlans": {}, + "noNutritionalPlans": "Ви не маєте планів харчування", + "@noNutritionalPlans": { + "description": "Message shown when the user has no nutritional plans" + }, + "anErrorOccurred": "Сталася помилка!", + "@anErrorOccurred": {}, + "measurement": "Вимірювання", + "@measurement": {}, + "logHelpEntries": "Якщо на один день припадає більше одного запису з однаковою кількістю повторень, але різними вагами, то на графіку буде показано тільки запис з більшою вагою.", + "@logHelpEntries": {}, + "logHelpEntriesUnits": "Зверніть увагу, що на графіку відображаються тільки записи з одиницями ваги (кг або lb) і повтореннями. Інші комбінації, такі як час або \"до відмови\", тут ігноруються.", + "@logHelpEntriesUnits": {}, + "measurements": "Вимірювання", + "@measurements": { + "description": "Categories for the measurements such as biceps size, body fat, etc." + }, + "measurementEntriesHelpText": "Одиниця вимірювання, яка використовується для вимірювання категорії, як от \"см\" або \"%\"", + "@measurementEntriesHelpText": {}, + "start": "Почати", + "@start": { + "description": "Label on button to start the gym mode (i.e., an imperative)" + }, + "timeStartAhead": "Час початку не може передувати часу завершення", + "@timeStartAhead": {}, + "ingredient": "Інгредієнт", + "@ingredient": {}, + "energy": "Енергія", + "@energy": { + "description": "Energy in a meal, ingredient etc. e.g. in kJ" + }, + "energyShort": "Е", + "@energyShort": { + "description": "The first letter or short name of the word 'Energy', used in overviews" + }, + "macronutrients": "Макроелементи", + "@macronutrients": {}, + "planned": "Заплановано", + "@planned": { + "description": "Header for the column of 'planned' nutritional values, i.e. what should be eaten" + }, + "logged": "Записано", + "@logged": { + "description": "Header for the column of 'logged' nutritional values, i.e. what was eaten" + }, + "weekAverage": "В середньому за 7 днів", + "@weekAverage": { + "description": "Header for the column of '7 day average' nutritional values, i.e. what was logged last week" + }, + "percentEnergy": "Відсоток енергії", + "@percentEnergy": {}, + "gPerBodyKg": "г на кг тіла", + "@gPerBodyKg": { + "description": "Label used for total sums of e.g. calories or similar in grams per Kg of body weight" + }, + "total": "Усього", + "@total": { + "description": "Label used for total sums of e.g. calories or similar" + }, + "kJ": "кДж", + "@kJ": { + "description": "Energy in a meal in kilo joules, kJ" + }, + "g": "г", + "@g": { + "description": "Abbreviation for gram" + }, + "protein": "Білок", + "@protein": {}, + "proteinShort": "Б", + "@proteinShort": { + "description": "The first letter or short name of the word 'Protein', used in overviews" + }, + "carbohydrates": "Вуглеводи", + "@carbohydrates": {}, + "carbohydratesShort": "В", + "@carbohydratesShort": { + "description": "The first letter or short name of the word 'Carbohydrates', used in overviews" + }, + "fatShort": "Ж", + "@fatShort": { + "description": "The first letter or short name of the word 'Fat', used in overviews" + }, + "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" + }, + "loadingText": "Завантаження...", + "@loadingText": { + "description": "Text to show when entries are being loaded in the background: Loading..." + }, + "confirmDelete": "Ви впевнені, що бажаєте видалити '{toDelete}'?", + "@confirmDelete": { + "description": "Confirmation text before the user deletes an object", + "type": "text", + "placeholders": { + "toDelete": {} + } + }, + "toggleDetails": "Перемкнути відомості", + "@toggleDetails": { + "description": "Switch to toggle detail / overview" + }, + "goToDetailPage": "Перейти до сторінки відомостей", + "@goToDetailPage": {}, + "aboutSourceTitle": "Джерельний код", + "@aboutSourceTitle": { + "description": "Title for source code section in the about dialog" + }, + "aboutSourceText": "Отримайте джерельний код цього додатка та його сервера на github", + "@aboutSourceText": { + "description": "Text for source code section in the about dialog" + }, + "aboutBugsTitle": "У вас є проблема чи ідея?", + "@aboutBugsTitle": { + "description": "Title for bugs section in the about dialog" + }, + "aboutContactUsTitle": "Привітайтеся!", + "@aboutContactUsTitle": { + "description": "Title for contact us section in the about dialog" + }, + "aboutContactUsText": "Якщо ви хочете поспілкуватися з нами, зайдіть на сервер Discord і зв'яжіться з нами", + "@aboutContactUsText": { + "description": "Text for contact us section in the about dialog" + }, + "aboutTranslationTitle": "Перекладання", + "@aboutTranslationTitle": { + "description": "Title for translation section in the about dialog" + }, + "aboutTranslationText": "Цей додаток перекладено на Weblate. Якщо ви також хочете допомогти, клацніть на посилання та почніть переклад", + "@aboutTranslationText": { + "description": "Text for translation section in the about dialog" + }, + "goToToday": "Перейти до сьогодні", + "@goToToday": { + "description": "Label on button to jump back to 'today' in the calendar widget" + }, + "enterRepetitionsOrWeight": "Будь ласка, заповніть кількість повторень або вагу принаймні для одного з наборів", + "@enterRepetitionsOrWeight": { + "description": "Error message when the user hasn't filled in the forms for exercise sets" + }, + "enterCharacters": "Будь ласка, введіть між{min} та {max} символами", + "@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}", + "@nrOfSets": { + "description": "Label shown on the slider where the user selects the nr of sets", + "type": "text", + "placeholders": { + "nrOfSets": {} + } + }, + "setUnitsAndRir": "Встановіть одиниці вимірювання та RiR", + "@setUnitsAndRir": { + "description": "Label shown on the slider where the user can toggle showing units and RiR", + "type": "text" + }, + "enterValidNumber": "Будь ласка, введіть прийнятний номер", + "@enterValidNumber": { + "description": "Error message when the user has submitted an invalid number (e.g. '3,.,.,.')" + }, + "recentlyUsedIngredients": "Останні інгредієнти", + "@recentlyUsedIngredients": { + "description": "A message when a user adds a new ingredient to a meal." + }, + "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": {}, + "dataCopied": "Дані скопійовано до нового запису", + "@dataCopied": { + "description": "Snackbar message to show on copying data to a new log entry" + }, + "appUpdateTitle": "Потрібне оновлення", + "@appUpdateTitle": {}, + "appUpdateContent": "Ця версія програми несумісна з сервером, будь ласка, оновіть додаток.", + "@appUpdateContent": {}, + "productFound": "Виріб знайдено", + "@productFound": { + "description": "Header label for dialog when product is found with barcode" + }, + "productNotFound": "Виріб не знайдено", + "@productNotFound": { + "description": "Header label for dialog when product is not found with barcode" + }, + "productNotFoundDescription": "Виріб із відсканованим штрих-кодом {barcode} не знайдено в базі даних Wger", + "@productNotFoundDescription": { + "description": "Dialog info when product is not found with barcode", + "type": "text", + "placeholders": { + "barcode": {} + } + }, + "scanBarcode": "Сканувати штрих-код", + "@scanBarcode": { + "description": "Label for scan barcode button" + }, + "close": "Закрити", + "@close": { + "description": "Translation for close" } } diff --git a/lib/models/body_weight/weight_entry.g.dart b/lib/models/body_weight/weight_entry.g.dart index 60ee02c9..d1152d20 100644 --- a/lib/models/body_weight/weight_entry.g.dart +++ b/lib/models/body_weight/weight_entry.g.dart @@ -18,8 +18,7 @@ WeightEntry _$WeightEntryFromJson(Map json) { ); } -Map _$WeightEntryToJson(WeightEntry instance) => - { +Map _$WeightEntryToJson(WeightEntry instance) => { 'id': instance.id, 'weight': numToString(instance.weight), 'date': toDate(instance.date), diff --git a/lib/models/exercises/category.g.dart b/lib/models/exercises/category.g.dart index 19383107..915120d1 100644 --- a/lib/models/exercises/category.g.dart +++ b/lib/models/exercises/category.g.dart @@ -17,8 +17,7 @@ ExerciseCategory _$ExerciseCategoryFromJson(Map json) { ); } -Map _$ExerciseCategoryToJson(ExerciseCategory instance) => - { +Map _$ExerciseCategoryToJson(ExerciseCategory instance) => { 'id': instance.id, 'name': instance.name, }; diff --git a/lib/models/exercises/image.g.dart b/lib/models/exercises/image.g.dart index 1240dc38..6ef7c62e 100644 --- a/lib/models/exercises/image.g.dart +++ b/lib/models/exercises/image.g.dart @@ -20,8 +20,7 @@ ExerciseImage _$ExerciseImageFromJson(Map json) { ); } -Map _$ExerciseImageToJson(ExerciseImage instance) => - { +Map _$ExerciseImageToJson(ExerciseImage instance) => { 'id': instance.id, 'uuid': instance.uuid, 'exercise_base': instance.exerciseBaseId, diff --git a/lib/models/measurements/measurement_category.g.dart b/lib/models/measurements/measurement_category.g.dart index ef4ebcd3..eb887b2e 100644 --- a/lib/models/measurements/measurement_category.g.dart +++ b/lib/models/measurements/measurement_category.g.dart @@ -22,9 +22,7 @@ MeasurementCategory _$MeasurementCategoryFromJson(Map json) { ); } -Map _$MeasurementCategoryToJson( - MeasurementCategory instance) => - { +Map _$MeasurementCategoryToJson(MeasurementCategory instance) => { 'id': instance.id, 'name': instance.name, 'unit': instance.unit, diff --git a/lib/models/measurements/measurement_entry.g.dart b/lib/models/measurements/measurement_entry.g.dart index 4b096960..7f6e346a 100644 --- a/lib/models/measurements/measurement_entry.g.dart +++ b/lib/models/measurements/measurement_entry.g.dart @@ -20,8 +20,7 @@ MeasurementEntry _$MeasurementEntryFromJson(Map json) { ); } -Map _$MeasurementEntryToJson(MeasurementEntry instance) => - { +Map _$MeasurementEntryToJson(MeasurementEntry instance) => { 'id': instance.id, 'category': instance.category, 'date': toDate(instance.date), diff --git a/lib/models/nutrition/ingredient.g.dart b/lib/models/nutrition/ingredient.g.dart index c4afcabb..5c19de59 100644 --- a/lib/models/nutrition/ingredient.g.dart +++ b/lib/models/nutrition/ingredient.g.dart @@ -40,8 +40,7 @@ Ingredient _$IngredientFromJson(Map json) { ); } -Map _$IngredientToJson(Ingredient instance) => - { +Map _$IngredientToJson(Ingredient instance) => { 'id': instance.id, 'code': instance.code, 'name': instance.name, diff --git a/lib/models/nutrition/ingredient_weight_unit.g.dart b/lib/models/nutrition/ingredient_weight_unit.g.dart index 74b1f101..f147a2ee 100644 --- a/lib/models/nutrition/ingredient_weight_unit.g.dart +++ b/lib/models/nutrition/ingredient_weight_unit.g.dart @@ -13,16 +13,14 @@ IngredientWeightUnit _$IngredientWeightUnitFromJson(Map json) { ); return IngredientWeightUnit( id: json['id'] as int, - weightUnit: - WeightUnit.fromJson(json['weight_unit'] as Map), + weightUnit: WeightUnit.fromJson(json['weight_unit'] as Map), ingredient: Ingredient.fromJson(json['ingredient'] as Map), grams: json['grams'] as int, amount: (json['amount'] as num).toDouble(), ); } -Map _$IngredientWeightUnitToJson( - IngredientWeightUnit instance) => +Map _$IngredientWeightUnitToJson(IngredientWeightUnit instance) => { 'id': instance.id, 'weight_unit': instance.weightUnit, diff --git a/lib/models/nutrition/log.g.dart b/lib/models/nutrition/log.g.dart index 39068768..61690155 100644 --- a/lib/models/nutrition/log.g.dart +++ b/lib/models/nutrition/log.g.dart @@ -9,14 +9,7 @@ part of 'log.dart'; Log _$LogFromJson(Map json) { $checkKeys( json, - requiredKeys: const [ - 'id', - 'plan', - 'datetime', - 'ingredient', - 'weight_unit', - 'amount' - ], + requiredKeys: const ['id', 'plan', 'datetime', 'ingredient', 'weight_unit', 'amount'], ); return Log( id: json['id'] as int?, diff --git a/lib/models/nutrition/nutritional_plan.g.dart b/lib/models/nutrition/nutritional_plan.g.dart index 9b10d8a5..661a9f47 100644 --- a/lib/models/nutrition/nutritional_plan.g.dart +++ b/lib/models/nutrition/nutritional_plan.g.dart @@ -18,8 +18,7 @@ NutritionalPlan _$NutritionalPlanFromJson(Map json) { ); } -Map _$NutritionalPlanToJson(NutritionalPlan instance) => - { +Map _$NutritionalPlanToJson(NutritionalPlan instance) => { 'id': instance.id, 'description': instance.description, 'creation_date': toDate(instance.creationDate), diff --git a/lib/models/nutrition/weight_unit.g.dart b/lib/models/nutrition/weight_unit.g.dart index 74e1f0cf..6f2b9607 100644 --- a/lib/models/nutrition/weight_unit.g.dart +++ b/lib/models/nutrition/weight_unit.g.dart @@ -17,8 +17,7 @@ WeightUnit _$WeightUnitFromJson(Map json) { ); } -Map _$WeightUnitToJson(WeightUnit instance) => - { +Map _$WeightUnitToJson(WeightUnit instance) => { 'id': instance.id, 'name': instance.name, }; diff --git a/lib/models/workouts/repetition_unit.g.dart b/lib/models/workouts/repetition_unit.g.dart index 115dc338..33e6a815 100644 --- a/lib/models/workouts/repetition_unit.g.dart +++ b/lib/models/workouts/repetition_unit.g.dart @@ -17,8 +17,7 @@ RepetitionUnit _$RepetitionUnitFromJson(Map json) { ); } -Map _$RepetitionUnitToJson(RepetitionUnit instance) => - { +Map _$RepetitionUnitToJson(RepetitionUnit instance) => { 'id': instance.id, 'name': instance.name, }; diff --git a/lib/models/workouts/session.g.dart b/lib/models/workouts/session.g.dart index e16affad..79f4fee4 100644 --- a/lib/models/workouts/session.g.dart +++ b/lib/models/workouts/session.g.dart @@ -9,14 +9,7 @@ part of 'session.dart'; WorkoutSession _$WorkoutSessionFromJson(Map json) { $checkKeys( json, - requiredKeys: const [ - 'id', - 'workout', - 'date', - 'impression', - 'time_start', - 'time_end' - ], + requiredKeys: const ['id', 'workout', 'date', 'impression', 'time_start', 'time_end'], ); return WorkoutSession() ..id = json['id'] as int? @@ -28,8 +21,7 @@ WorkoutSession _$WorkoutSessionFromJson(Map json) { ..timeEnd = stringToTime(json['time_end'] as String?); } -Map _$WorkoutSessionToJson(WorkoutSession instance) => - { +Map _$WorkoutSessionToJson(WorkoutSession instance) => { 'id': instance.id, 'workout': instance.workoutId, 'date': toDate(instance.date), diff --git a/lib/models/workouts/weight_unit.g.dart b/lib/models/workouts/weight_unit.g.dart index 74e1f0cf..6f2b9607 100644 --- a/lib/models/workouts/weight_unit.g.dart +++ b/lib/models/workouts/weight_unit.g.dart @@ -17,8 +17,7 @@ WeightUnit _$WeightUnitFromJson(Map json) { ); } -Map _$WeightUnitToJson(WeightUnit instance) => - { +Map _$WeightUnitToJson(WeightUnit instance) => { 'id': instance.id, 'name': instance.name, }; diff --git a/lib/models/workouts/workout_plan.g.dart b/lib/models/workouts/workout_plan.g.dart index ef156e3e..ac1d6fa9 100644 --- a/lib/models/workouts/workout_plan.g.dart +++ b/lib/models/workouts/workout_plan.g.dart @@ -19,8 +19,7 @@ WorkoutPlan _$WorkoutPlanFromJson(Map json) { ); } -Map _$WorkoutPlanToJson(WorkoutPlan instance) => - { +Map _$WorkoutPlanToJson(WorkoutPlan instance) => { 'id': instance.id, 'creation_date': instance.creationDate.toIso8601String(), 'name': instance.name, diff --git a/lib/widgets/dashboard/widgets.dart b/lib/widgets/dashboard/widgets.dart index 5471259b..123e4e5e 100644 --- a/lib/widgets/dashboard/widgets.dart +++ b/lib/widgets/dashboard/widgets.dart @@ -242,66 +242,68 @@ class _DashboardWeightWidgetState extends State { Widget build(BuildContext context) { weightEntriesData = Provider.of(context, listen: false); - return Card( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ListTile( - title: Text( - AppLocalizations.of(context).weight, - style: Theme.of(context).textTheme.headline4, + return Consumer( + builder: (context, workoutProvider, child) => Card( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + title: Text( + AppLocalizations.of(context).weight, + style: Theme.of(context).textTheme.headline4, + ), + leading: const FaIcon( + FontAwesomeIcons.weight, + color: Colors.black, + ), + trailing: IconButton( + icon: const Icon(Icons.add), + onPressed: () async { + Navigator.pushNamed( + context, + FormScreen.routeName, + arguments: FormScreenArguments( + AppLocalizations.of(context).newEntry, + WeightForm(), + ), + ); + }, + ), ), - leading: const FaIcon( - FontAwesomeIcons.weight, - color: Colors.black, - ), - trailing: IconButton( - icon: const Icon(Icons.add), - onPressed: () async { - Navigator.pushNamed( - context, - FormScreen.routeName, - arguments: FormScreenArguments( + Column( + children: [ + if (weightEntriesData.items.isNotEmpty) + Column( + children: [ + Container( + padding: const EdgeInsets.all(15), + height: 180, + child: MeasurementChartWidget(weightEntriesData.items + .map((e) => MeasurementChartEntry(e.weight, e.date)) + .toList()), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + child: Text(AppLocalizations.of(context).goToDetailPage), + onPressed: () { + Navigator.of(context).pushNamed(WeightScreen.routeName); + }), + ], + ), + ], + ) + else + NothingFound( + AppLocalizations.of(context).noWeightEntries, AppLocalizations.of(context).newEntry, WeightForm(), ), - ); - }, + ], ), - ), - Column( - children: [ - if (weightEntriesData.items.isNotEmpty) - Column( - children: [ - Container( - padding: const EdgeInsets.all(15), - height: 180, - child: MeasurementChartWidget(weightEntriesData.items - .map((e) => MeasurementChartEntry(e.weight, e.date)) - .toList()), - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - child: Text(AppLocalizations.of(context).goToDetailPage), - onPressed: () { - Navigator.of(context).pushNamed(WeightScreen.routeName); - }), - ], - ), - ], - ) - else - NothingFound( - AppLocalizations.of(context).noWeightEntries, - AppLocalizations.of(context).newEntry, - WeightForm(), - ), - ], - ), - ], + ], + ), ), ); } diff --git a/lib/widgets/nutrition/nutritional_plans_list.dart b/lib/widgets/nutrition/nutritional_plans_list.dart index 2e43a103..c74683c6 100644 --- a/lib/widgets/nutrition/nutritional_plans_list.dart +++ b/lib/widgets/nutrition/nutritional_plans_list.dart @@ -23,16 +23,16 @@ import 'package:wger/providers/nutrition.dart'; import 'package:wger/screens/nutritional_plan_screen.dart'; class NutritionalPlansList extends StatelessWidget { - final NutritionPlansProvider _nutritrionProvider; - const NutritionalPlansList(this._nutritrionProvider); + final NutritionPlansProvider _nutritionProvider; + const NutritionalPlansList(this._nutritionProvider); @override Widget build(BuildContext context) { return ListView.builder( padding: const EdgeInsets.all(10.0), - itemCount: _nutritrionProvider.items.length, + itemCount: _nutritionProvider.items.length, itemBuilder: (context, index) { - final currentPlan = _nutritrionProvider.items[index]; + final currentPlan = _nutritionProvider.items[index]; return Dismissible( key: Key(currentPlan.id.toString()), confirmDismiss: (direction) async { @@ -56,7 +56,7 @@ class NutritionalPlansList extends StatelessWidget { ), onPressed: () { // Confirmed, delete the workout - _nutritrionProvider.deletePlan(currentPlan.id!); + _nutritionProvider.deletePlan(currentPlan.id!); // Close the popup Navigator.of(contextDialog).pop(); diff --git a/pubspec.yaml b/pubspec.yaml index 1dff79ad..fc1a890e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,28 +32,28 @@ dependencies: sdk: flutter android_metadata: ^0.2.1 - camera: ^0.9.4+16 + camera: ^0.9.8 charts_flutter: ^0.12.0 collection: ^1.15.0-nullsafety.4 - cupertino_icons: ^1.0.0 + cupertino_icons: ^1.0.5 equatable: ^2.0.3 - flutter_calendar_carousel: ^2.0.3 + flutter_calendar_carousel: ^2.2.0 flutter_html: ^2.1.2 flutter_typeahead: ^3.2.5 font_awesome_flutter: ">=9.1.0 <11.0.0" http: ^0.13.3 - image_picker: ^0.8.4+11 + image_picker: ^0.8.4+9 intl: ^0.17.0 json_annotation: ^4.5.0 - version: ^2.0.0 + version: ^3.0.2 package_info: ^2.0.2 - provider: ^6.0.1 - rive: ^0.8.1 - shared_preferences: ^2.0.13 - table_calendar: ^3.0.2 - url_launcher: ^6.1.0 + provider: ^6.0.3 + rive: ^0.9.0 + shared_preferences: ^2.0.15 + table_calendar: ^3.0.6 + url_launcher: ^6.1.4 flutter_barcode_scanner: ^2.0.0 - video_player: ^2.4.0 + video_player: ^2.4.5 multi_select_flutter: ^4.0.0 flutter_svg: ^0.23.0+1 @@ -62,10 +62,10 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter - build_runner: ^2.1.2 - flutter_launcher_icons: ^0.9.1 + build_runner: ^2.1.11 + flutter_launcher_icons: ^0.9.3 json_serializable: ^6.2.0 - mockito: ^5.1.0 + mockito: ^5.2.0 network_image_mock: ^2.0.1 flutter_lints: ^1.0.4 cider: ^0.1.1 diff --git a/test/measurements/measurement_categories_screen_test.mocks.dart b/test/measurements/measurement_categories_screen_test.mocks.dart index 46e5a2e8..7f04fbe1 100644 --- a/test/measurements/measurement_categories_screen_test.mocks.dart +++ b/test/measurements/measurement_categories_screen_test.mocks.dart @@ -21,41 +21,36 @@ import 'package:wger/providers/measurement.dart' as _i4; // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types -class _FakeWgerBaseProvider_0 extends _i1.Fake implements _i2.WgerBaseProvider { -} +class _FakeWgerBaseProvider_0 extends _i1.Fake implements _i2.WgerBaseProvider {} -class _FakeMeasurementCategory_1 extends _i1.Fake - implements _i3.MeasurementCategory {} +class _FakeMeasurementCategory_1 extends _i1.Fake implements _i3.MeasurementCategory {} /// A class which mocks [MeasurementProvider]. /// /// See the documentation for Mockito's code generation for more information. -class MockMeasurementProvider extends _i1.Mock - implements _i4.MeasurementProvider { +class MockMeasurementProvider extends _i1.Mock implements _i4.MeasurementProvider { MockMeasurementProvider() { _i1.throwOnMissingStub(this); } @override _i2.WgerBaseProvider get baseProvider => - (super.noSuchMethod(Invocation.getter(#baseProvider), - returnValue: _FakeWgerBaseProvider_0()) as _i2.WgerBaseProvider); + (super.noSuchMethod(Invocation.getter(#baseProvider), returnValue: _FakeWgerBaseProvider_0()) + as _i2.WgerBaseProvider); @override List<_i3.MeasurementCategory> get categories => - (super.noSuchMethod(Invocation.getter(#categories), - returnValue: <_i3.MeasurementCategory>[]) + (super.noSuchMethod(Invocation.getter(#categories), returnValue: <_i3.MeasurementCategory>[]) as List<_i3.MeasurementCategory>); @override bool get hasListeners => - (super.noSuchMethod(Invocation.getter(#hasListeners), returnValue: false) - as bool); + (super.noSuchMethod(Invocation.getter(#hasListeners), returnValue: false) as bool); @override - void clear() => super.noSuchMethod(Invocation.method(#clear, []), - returnValueForMissingStub: null); + void clear() => + super.noSuchMethod(Invocation.method(#clear, []), returnValueForMissingStub: null); @override - _i3.MeasurementCategory findCategoryById(int? id) => (super.noSuchMethod( - Invocation.method(#findCategoryById, [id]), - returnValue: _FakeMeasurementCategory_1()) as _i3.MeasurementCategory); + _i3.MeasurementCategory findCategoryById(int? id) => + (super.noSuchMethod(Invocation.method(#findCategoryById, [id]), + returnValue: _FakeMeasurementCategory_1()) as _i3.MeasurementCategory); @override _i5.Future fetchAndSetCategories() => (super.noSuchMethod(Invocation.method(#fetchAndSetCategories, []), @@ -67,10 +62,10 @@ class MockMeasurementProvider extends _i1.Mock returnValue: Future.value(), returnValueForMissingStub: Future.value()) as _i5.Future); @override - _i5.Future fetchAndSetAllCategoriesAndEntries() => (super.noSuchMethod( - Invocation.method(#fetchAndSetAllCategoriesAndEntries, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i5.Future); + _i5.Future fetchAndSetAllCategoriesAndEntries() => + (super.noSuchMethod(Invocation.method(#fetchAndSetAllCategoriesAndEntries, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i5.Future); @override _i5.Future addCategory(_i3.MeasurementCategory? category) => (super.noSuchMethod(Invocation.method(#addCategory, [category]), @@ -83,8 +78,7 @@ class MockMeasurementProvider extends _i1.Mock returnValueForMissingStub: Future.value()) as _i5.Future); @override _i5.Future editCategory(int? id, String? newName, String? newUnit) => - (super.noSuchMethod( - Invocation.method(#editCategory, [id, newName, newUnit]), + (super.noSuchMethod(Invocation.method(#editCategory, [id, newName, newUnit]), returnValue: Future.value(), returnValueForMissingStub: Future.value()) as _i5.Future); @override @@ -98,26 +92,23 @@ class MockMeasurementProvider extends _i1.Mock returnValue: Future.value(), returnValueForMissingStub: Future.value()) as _i5.Future); @override - _i5.Future editEntry(int? id, int? categoryId, num? newValue, - String? newNotes, DateTime? newDate) => + _i5.Future editEntry( + int? id, int? categoryId, num? newValue, String? newNotes, DateTime? newDate) => (super.noSuchMethod( - Invocation.method( - #editEntry, [id, categoryId, newValue, newNotes, newDate]), + Invocation.method(#editEntry, [id, categoryId, newValue, newNotes, newDate]), returnValue: Future.value(), returnValueForMissingStub: Future.value()) as _i5.Future); @override - void addListener(_i7.VoidCallback? listener) => - super.noSuchMethod(Invocation.method(#addListener, [listener]), - returnValueForMissingStub: null); + void addListener(_i7.VoidCallback? listener) => super + .noSuchMethod(Invocation.method(#addListener, [listener]), returnValueForMissingStub: null); @override void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod(Invocation.method(#removeListener, [listener]), returnValueForMissingStub: null); @override - void dispose() => super.noSuchMethod(Invocation.method(#dispose, []), - returnValueForMissingStub: null); + void dispose() => + super.noSuchMethod(Invocation.method(#dispose, []), returnValueForMissingStub: null); @override void notifyListeners() => - super.noSuchMethod(Invocation.method(#notifyListeners, []), - returnValueForMissingStub: null); + super.noSuchMethod(Invocation.method(#notifyListeners, []), returnValueForMissingStub: null); } diff --git a/test/other/base_provider_test.mocks.dart b/test/other/base_provider_test.mocks.dart index f6327b35..89990ffe 100644 --- a/test/other/base_provider_test.mocks.dart +++ b/test/other/base_provider_test.mocks.dart @@ -24,8 +24,7 @@ import 'package:mockito/mockito.dart' as _i1; class _FakeResponse_0 extends _i1.Fake implements _i2.Response {} -class _FakeStreamedResponse_1 extends _i1.Fake implements _i3.StreamedResponse { -} +class _FakeStreamedResponse_1 extends _i1.Fake implements _i3.StreamedResponse {} /// A class which mocks [Client]. /// @@ -38,71 +37,49 @@ class MockClient extends _i1.Mock implements _i4.Client { @override _i5.Future<_i2.Response> head(Uri? url, {Map? headers}) => (super.noSuchMethod(Invocation.method(#head, [url], {#headers: headers}), - returnValue: Future<_i2.Response>.value(_FakeResponse_0())) - as _i5.Future<_i2.Response>); + returnValue: Future<_i2.Response>.value(_FakeResponse_0())) as _i5.Future<_i2.Response>); @override _i5.Future<_i2.Response> get(Uri? url, {Map? headers}) => (super.noSuchMethod(Invocation.method(#get, [url], {#headers: headers}), - returnValue: Future<_i2.Response>.value(_FakeResponse_0())) - as _i5.Future<_i2.Response>); + returnValue: Future<_i2.Response>.value(_FakeResponse_0())) as _i5.Future<_i2.Response>); @override _i5.Future<_i2.Response> post(Uri? url, - {Map? headers, - Object? body, - _i6.Encoding? encoding}) => + {Map? headers, Object? body, _i6.Encoding? encoding}) => (super.noSuchMethod( - Invocation.method(#post, [url], - {#headers: headers, #body: body, #encoding: encoding}), - returnValue: Future<_i2.Response>.value(_FakeResponse_0())) - as _i5.Future<_i2.Response>); + Invocation.method(#post, [url], {#headers: headers, #body: body, #encoding: encoding}), + returnValue: Future<_i2.Response>.value(_FakeResponse_0())) as _i5.Future<_i2.Response>); @override _i5.Future<_i2.Response> put(Uri? url, - {Map? headers, - Object? body, - _i6.Encoding? encoding}) => + {Map? headers, Object? body, _i6.Encoding? encoding}) => (super.noSuchMethod( - Invocation.method(#put, [url], - {#headers: headers, #body: body, #encoding: encoding}), - returnValue: Future<_i2.Response>.value(_FakeResponse_0())) - as _i5.Future<_i2.Response>); + Invocation.method(#put, [url], {#headers: headers, #body: body, #encoding: encoding}), + returnValue: Future<_i2.Response>.value(_FakeResponse_0())) as _i5.Future<_i2.Response>); @override _i5.Future<_i2.Response> patch(Uri? url, - {Map? headers, - Object? body, - _i6.Encoding? encoding}) => + {Map? headers, Object? body, _i6.Encoding? encoding}) => (super.noSuchMethod( - Invocation.method(#patch, [url], - {#headers: headers, #body: body, #encoding: encoding}), - returnValue: Future<_i2.Response>.value(_FakeResponse_0())) - as _i5.Future<_i2.Response>); + Invocation.method(#patch, [url], {#headers: headers, #body: body, #encoding: encoding}), + returnValue: Future<_i2.Response>.value(_FakeResponse_0())) as _i5.Future<_i2.Response>); @override _i5.Future<_i2.Response> delete(Uri? url, - {Map? headers, - Object? body, - _i6.Encoding? encoding}) => + {Map? headers, Object? body, _i6.Encoding? encoding}) => (super.noSuchMethod( - Invocation.method(#delete, [url], - {#headers: headers, #body: body, #encoding: encoding}), - returnValue: Future<_i2.Response>.value(_FakeResponse_0())) - as _i5.Future<_i2.Response>); + Invocation.method(#delete, [url], {#headers: headers, #body: body, #encoding: encoding}), + returnValue: Future<_i2.Response>.value(_FakeResponse_0())) as _i5.Future<_i2.Response>); @override _i5.Future read(Uri? url, {Map? headers}) => (super.noSuchMethod(Invocation.method(#read, [url], {#headers: headers}), returnValue: Future.value('')) as _i5.Future); @override - _i5.Future<_i7.Uint8List> readBytes(Uri? url, - {Map? headers}) => - (super.noSuchMethod( - Invocation.method(#readBytes, [url], {#headers: headers}), - returnValue: Future<_i7.Uint8List>.value(_i7.Uint8List(0))) - as _i5.Future<_i7.Uint8List>); + _i5.Future<_i7.Uint8List> readBytes(Uri? url, {Map? headers}) => + (super.noSuchMethod(Invocation.method(#readBytes, [url], {#headers: headers}), + returnValue: Future<_i7.Uint8List>.value(_i7.Uint8List(0))) as _i5.Future<_i7.Uint8List>); @override _i5.Future<_i3.StreamedResponse> send(_i8.BaseRequest? request) => (super.noSuchMethod(Invocation.method(#send, [request]), - returnValue: - Future<_i3.StreamedResponse>.value(_FakeStreamedResponse_1())) + returnValue: Future<_i3.StreamedResponse>.value(_FakeStreamedResponse_1())) as _i5.Future<_i3.StreamedResponse>); @override - void close() => super.noSuchMethod(Invocation.method(#close, []), - returnValueForMissingStub: null); + void close() => + super.noSuchMethod(Invocation.method(#close, []), returnValueForMissingStub: null); }