diff --git a/integration_test/3_gym_mode.dart b/integration_test/3_gym_mode.dart index 16fdfbdda..7e14c3d4d 100644 --- a/integration_test/3_gym_mode.dart +++ b/integration_test/3_gym_mode.dart @@ -92,7 +92,7 @@ Widget createGymModeResultsScreen({String locale = 'en'}) { gymStateProvider.overrideWithValue( GymModeState( routine: routine, - dayId: routine.days.first.id!, + dayId: routine.days.first.id, iteration: 1, showExercisePages: true, showTimerPages: true, diff --git a/lib/helpers/i18n.dart b/lib/helpers/i18n.dart index 4da3c04d4..b1732d396 100644 --- a/lib/helpers/i18n.dart +++ b/lib/helpers/i18n.dart @@ -1,4 +1,5 @@ /// This code is autogenerated in the backend repo in extract-i18n.py do not edit! +library; /// Translate dynamic strings that are returned from the server /// These strings such as categories or equipment are returned by the server diff --git a/lib/models/exercises/exercise.dart b/lib/models/exercises/exercise.dart index dca5341d0..30f95d47b 100644 --- a/lib/models/exercises/exercise.dart +++ b/lib/models/exercises/exercise.dart @@ -205,7 +205,7 @@ class Exercise extends Equatable { (e) => e.languageObj.shortName == LANGUAGE_SHORT_ENGLISH, orElse: () { _logger.info( - 'Could not find fallback english translation for exercise-ID ${id}, returning ' + 'Could not find fallback english translation for exercise-ID $id, returning ' 'first language (${translations.first.languageObj.shortName}) instead.', ); return translations.first; diff --git a/lib/models/measurements/measurement_category.dart b/lib/models/measurements/measurement_category.dart index e5c8cdfd3..526a8e044 100644 --- a/lib/models/measurements/measurement_category.dart +++ b/lib/models/measurements/measurement_category.dart @@ -57,6 +57,6 @@ class MeasurementCategory extends Equatable { List get props => [id, name, unit, entries]; // Helper function which makes the entries list of the toJson output null, as it isn't needed - //ignore: always_declare_return_types - static _nullValue(_) => null; + static List? _nullValue(_) => null; } + diff --git a/lib/models/workouts/base_config.dart b/lib/models/workouts/base_config.dart index a7ffbd7bb..f195ffbbc 100644 --- a/lib/models/workouts/base_config.dart +++ b/lib/models/workouts/base_config.dart @@ -55,7 +55,7 @@ class BaseConfig { required this.value, this.operation = 'r', this.step = 'abs', - this.requirements = null, + this.requirements, }); BaseConfig.firstIteration(this.value, this.slotEntryId) { diff --git a/lib/providers/nutrition.dart b/lib/providers/nutrition.dart index 12435e372..7ae238dd3 100644 --- a/lib/providers/nutrition.dart +++ b/lib/providers/nutrition.dart @@ -360,7 +360,7 @@ class NutritionPlansProvider with ChangeNotifier { (database.delete(database.ingredients)..where((i) => i.id.equals(ingredientId))).go(); } } else { - _logger.info("Fetching ingredient ID $ingredientId from server"); + _logger.info('Fetching ingredient ID $ingredientId from server'); final data = await baseProvider.fetch( baseProvider.makeUrl(_ingredientInfoPath, id: ingredientId), ); diff --git a/lib/providers/plate_weights.dart b/lib/providers/plate_weights.dart index 493bad04c..7df2f97a4 100644 --- a/lib/providers/plate_weights.dart +++ b/lib/providers/plate_weights.dart @@ -55,9 +55,6 @@ class PlateCalculatorState { final List availablePlatesKg = const [0.5, 1, 1.25, 2, 2.5, 5, 10, 15, 20, 25]; final List availablePlatesLb = const [2.5, 5, 10, 25, 35, 45]; - final availableBarWeightsKg = [10, 15, 20]; - final availableBarWeightsLb = [15, 20, 25, 33, 45]; - PlateCalculatorState({ this.useColors = true, num? barWeight, @@ -106,10 +103,6 @@ class PlateCalculatorState { return isMetric ? availablePlatesKg : availablePlatesLb; } - List get availableBarsWeights { - return isMetric ? availableBarWeightsKg : availableBarWeightsLb; - } - List get platesList { return plateCalculator(totalWeight, barWeight, selectedPlates); } diff --git a/lib/providers/routines.dart b/lib/providers/routines.dart index 692c36ceb..7072afe66 100644 --- a/lib/providers/routines.dart +++ b/lib/providers/routines.dart @@ -691,7 +691,7 @@ class RoutinesProvider with ChangeNotifier { }*/ Future deleteLog(int logId, int routineId) async { - _logger.fine('Deleting log ${logId}'); + _logger.fine('Deleting log $logId'); await baseProvider.deleteRequest(_logsUrlPath, logId); await fetchAndSetRoutineFull(routineId); } diff --git a/lib/widgets/add_exercise/add_exercise_dropdown_button.dart b/lib/widgets/add_exercise/add_exercise_dropdown_button.dart index 7b8d71dd7..2b82ff0c1 100644 --- a/lib/widgets/add_exercise/add_exercise_dropdown_button.dart +++ b/lib/widgets/add_exercise/add_exercise_dropdown_button.dart @@ -37,7 +37,7 @@ class _AddExerciseDropdownButtonState extends State { }); widget.onChange(value); }, - value: _selectedItem, + initialValue: _selectedItem, decoration: InputDecoration( contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), border: const OutlineInputBorder( diff --git a/lib/widgets/add_exercise/license_info_widget.dart b/lib/widgets/add_exercise/license_info_widget.dart index 59e9609b2..9324df7af 100644 --- a/lib/widgets/add_exercise/license_info_widget.dart +++ b/lib/widgets/add_exercise/license_info_widget.dart @@ -11,7 +11,7 @@ import 'package:wger/l10n/generated/app_localizations.dart'; /// Being a separate widget allows Flutter to optimize rendering since /// this content never changes. class LicenseInfoWidget extends StatelessWidget { - const LicenseInfoWidget({Key? key}) : super(key: key); + const LicenseInfoWidget({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/widgets/add_exercise/preview_images.dart b/lib/widgets/add_exercise/preview_images.dart index 3da95b587..60de475b9 100644 --- a/lib/widgets/add_exercise/preview_images.dart +++ b/lib/widgets/add_exercise/preview_images.dart @@ -89,7 +89,7 @@ class PreviewExerciseImages extends StatelessWidget { height: 120, margin: const EdgeInsets.only(right: 8), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceVariant, + color: Theme.of(context).colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(8), border: Border.all( color: Theme.of(context).colorScheme.outline, diff --git a/lib/widgets/add_exercise/steps/step_2_variations.dart b/lib/widgets/add_exercise/steps/step_2_variations.dart index 4fcb639ba..3ab25e65d 100644 --- a/lib/widgets/add_exercise/steps/step_2_variations.dart +++ b/lib/widgets/add_exercise/steps/step_2_variations.dart @@ -50,7 +50,7 @@ class Step2Variations extends StatelessWidget { ), ), Consumer( - builder: (ctx, provider, __) => Switch( + builder: (ctx, provider, _) => Switch( value: provider.variationId == key, onChanged: (state) => provider.variationId = key, ), @@ -83,7 +83,7 @@ class Step2Variations extends StatelessWidget { ), ), Consumer( - builder: (ctx, provider, __) => Switch( + builder: (ctx, provider, _) => Switch( value: provider.variationConnectToExercise == base.id, onChanged: (state) => provider.variationConnectToExercise = base.id, ), diff --git a/lib/widgets/add_exercise/steps/step_4_translations.dart b/lib/widgets/add_exercise/steps/step_4_translations.dart index d8f4a778f..fdfc6d559 100644 --- a/lib/widgets/add_exercise/steps/step_4_translations.dart +++ b/lib/widgets/add_exercise/steps/step_4_translations.dart @@ -61,7 +61,7 @@ class _Step4TranslationState extends State { AddExerciseTextArea( title: '${i18n.name}*', validator: (name) => validateName(name, context), - onSaved: (String? name) => addExerciseProvider.exerciseNameTrans = name!, + onSaved: (String? name) => addExerciseProvider.exerciseNameTrans = name, ), AddExerciseTextArea( title: i18n.alternativeNames, @@ -86,14 +86,14 @@ class _Step4TranslationState extends State { addExerciseProvider.alternateNamesTrans = alternateName!.split('\n'), ), Consumer( - builder: (ctx, provider, __) => AddExerciseTextArea( + builder: (ctx, provider, _) => AddExerciseTextArea( onChange: (value) => {}, title: '${i18n.description}*', helperText: i18n.enterTextInLanguage, isMultiline: true, validator: (name) => validateExerciseDescription(name, context), onSaved: (String? description) => - addExerciseProvider.descriptionTrans = description!, + addExerciseProvider.descriptionTrans = description, ), ), ], diff --git a/lib/widgets/add_exercise/steps/step_5_images.dart b/lib/widgets/add_exercise/steps/step_5_images.dart index 6d4361225..95246139e 100644 --- a/lib/widgets/add_exercise/steps/step_5_images.dart +++ b/lib/widgets/add_exercise/steps/step_5_images.dart @@ -179,7 +179,7 @@ class _Step5ImagesState extends State with ExerciseImagePickerMixin // Image picker or preview - shown when not entering metadata if (_currentImageToAdd == null) Consumer( - builder: (ctx, provider, __) { + builder: (ctx, provider, _) { if (provider.exerciseImages.isNotEmpty) { // Show preview of images that have been added with metadata return Column( diff --git a/lib/widgets/dashboard/widgets/measurements.dart b/lib/widgets/dashboard/widgets/measurements.dart index ed7fbd8f9..c38124803 100644 --- a/lib/widgets/dashboard/widgets/measurements.dart +++ b/lib/widgets/dashboard/widgets/measurements.dart @@ -55,7 +55,7 @@ class _DashboardMeasurementWidgetState extends State ); } return Consumer( - builder: (context, _, __) => Card( + builder: (context, _, _) => Card( child: Column( mainAxisSize: MainAxisSize.min, children: [ diff --git a/lib/widgets/exercises/forms.dart b/lib/widgets/exercises/forms.dart index d07577280..0465e7061 100644 --- a/lib/widgets/exercises/forms.dart +++ b/lib/widgets/exercises/forms.dart @@ -58,7 +58,7 @@ class _ExerciseCategoryInputWidgetState extends State { return BarChart( BarChartData( alignment: BarChartAlignment.center, - barTouchData: BarTouchData(enabled: false), + barTouchData: const BarTouchData(enabled: false), titlesData: FlTitlesData( show: true, bottomTitles: AxisTitles( diff --git a/lib/widgets/nutrition/nutrition_tile.dart b/lib/widgets/nutrition/nutrition_tile.dart index 4e1cc5b48..22de42b3c 100644 --- a/lib/widgets/nutrition/nutrition_tile.dart +++ b/lib/widgets/nutrition/nutrition_tile.dart @@ -32,8 +32,8 @@ class NutritionTile extends StatelessWidget { Expanded( child: Column( children: [ - if (title != null) title!, - if (subtitle != null) subtitle!, + ?title, + ?subtitle, ], ), ), diff --git a/lib/widgets/routines/forms/weight.dart b/lib/widgets/routines/forms/weight.dart index 51987ce96..4c49ee14d 100644 --- a/lib/widgets/routines/forms/weight.dart +++ b/lib/widgets/routines/forms/weight.dart @@ -139,6 +139,7 @@ class _WeightInputWidgetState extends ConsumerState { final base = currentWeight ?? 0; final newValue = base - widget.valueChange; if (newValue >= 0 && log != null) { + plateProvider.setWeight(newValue); logProvider.setWeight(newValue); } }, @@ -181,6 +182,7 @@ class _WeightInputWidgetState extends ConsumerState { final base = currentWeight ?? 0; final newValue = base + widget.valueChange; if (log != null) { + plateProvider.setWeight(newValue); logProvider.setWeight(newValue); } }, diff --git a/lib/widgets/routines/gym_mode/log_page.dart b/lib/widgets/routines/gym_mode/log_page.dart index cd0eef568..2ffeff95e 100644 --- a/lib/widgets/routines/gym_mode/log_page.dart +++ b/lib/widgets/routines/gym_mode/log_page.dart @@ -61,6 +61,17 @@ class LogPage extends ConsumerWidget { } final setConfigData = slotEntryPage.setConfigData!; + // Calculate weightRounding as 2 times the smallest available plate weight + final plateProvider = ref.read(plateCalculatorProvider.notifier); + final selectedPlates = plateProvider.state.selectedPlates; + final minPlate = selectedPlates.isNotEmpty ? selectedPlates.reduce((a, b) => a < b ? a : b) : 1.25; + final calculatedWeightRounding = 2 * minPlate; + + // Create a new SetConfigData with the calculated weightRounding + final updatedConfigData = setConfigData.copyWith( + weightRounding: calculatedWeightRounding, + ); + final log = ref.read(gymLogProvider); // Mark done sets @@ -84,17 +95,17 @@ class LogPage extends ConsumerWidget { children: [ Column( children: [ - Text( - setConfigData.textRepr, - textAlign: TextAlign.center, + Text( + updatedConfigData.textRepr, + textAlign: TextAlign.center, style: theme.textTheme.headlineMedium?.copyWith( color: Theme.of(context).colorScheme.primary, decoration: decorationStyle, - ), - ), - if (setConfigData.type != SlotEntryType.normal) + ), + ), + if (updatedConfigData.type != SlotEntryType.normal) Text( - setConfigData.type.name.toUpperCase(), + updatedConfigData.type.name.toUpperCase(), textAlign: TextAlign.center, style: theme.textTheme.headlineSmall?.copyWith( color: Theme.of(context).colorScheme.primary, @@ -115,8 +126,8 @@ class LogPage extends ConsumerWidget { ), ), if (log.exercise.showPlateCalculator) const LogsPlatesWidget(), - if (slotEntryPage.setConfigData!.comment.isNotEmpty) - Text(slotEntryPage.setConfigData!.comment, textAlign: TextAlign.center), + if (updatedConfigData.comment.isNotEmpty) + Text(updatedConfigData.comment, textAlign: TextAlign.center), const SizedBox(height: 10), Expanded( child: (gymState.routine.filterLogsByExercise(log.exerciseId).isNotEmpty) @@ -135,7 +146,7 @@ class LogPage extends ConsumerWidget { padding: const EdgeInsets.symmetric(vertical: 5), child: LogFormWidget( controller: _controller, - configData: setConfigData, + configData: updatedConfigData, key: ValueKey('log-form-${slotEntryPage.uuid}'), ), ), diff --git a/lib/widgets/routines/logs/session_info.dart b/lib/widgets/routines/logs/session_info.dart index a8293010f..4110d26be 100644 --- a/lib/widgets/routines/logs/session_info.dart +++ b/lib/widgets/routines/logs/session_info.dart @@ -57,7 +57,7 @@ class _SessionInfoState extends State { ), if (editMode) SessionForm( - widget._session.routineId!, + widget._session.routineId, onSaved: () => setState(() => editMode = false), session: widget._session, ) diff --git a/lib/widgets/routines/plate_calculator.dart b/lib/widgets/routines/plate_calculator.dart index 4e5c06b73..c8778c969 100644 --- a/lib/widgets/routines/plate_calculator.dart +++ b/lib/widgets/routines/plate_calculator.dart @@ -108,24 +108,26 @@ class _AddPlateWeightsState extends ConsumerState { ), Padding( padding: const EdgeInsets.all(10), - child: DropdownMenu( - key: const ValueKey('barWeightDropdown'), - width: double.infinity, - initialSelection: plateWeightsState.barWeight, - requestFocusOnTap: true, - label: Text(i18n.barWeight), - onSelected: (num? value) { - if (value == null) { - return; + child: TextField( + key: const ValueKey('barWeightTextField'), + controller: TextEditingController(text: plateWeightsState.barWeight.toString()), + keyboardType: TextInputType.number, + decoration: InputDecoration( + labelText: i18n.barWeight, + suffix: Text(plateWeightsState.isMetric ? i18n.kg : i18n.lb), + ), + onChanged: (text) { + final parsed = num.tryParse(text); + if (parsed != null) { + plateWeightsNotifier.setBarWeight(parsed); + } + }, + onSubmitted: (text) { + final parsed = num.tryParse(text); + if (parsed != null) { + plateWeightsNotifier.setBarWeight(parsed); } - plateWeightsNotifier.setBarWeight(value); }, - dropdownMenuEntries: plateWeightsState.availableBarsWeights.map((value) { - return DropdownMenuEntry( - value: value, - label: value.toString(), - ); - }).toList(), ), ), SwitchListTile( diff --git a/test/exercises/contribute_exercise_test.dart b/test/exercises/contribute_exercise_test.dart index df1c3b4ba..3c303130e 100644 --- a/test/exercises/contribute_exercise_test.dart +++ b/test/exercises/contribute_exercise_test.dart @@ -284,7 +284,7 @@ void main() { await tester.pumpAndSettle(); // Verify initial step is 0 - var stepper = tester.widget(find.byType(Stepper)); + final stepper = tester.widget(find.byType(Stepper)); expect(stepper.currentStep, equals(0)); // Get localized text for UI elements