Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 62 additions & 18 deletions lib/widgets/routines/plate_calculator.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/plate_weights.dart';
Expand Down Expand Up @@ -63,6 +64,10 @@ class ConfigureAvailablePlates extends ConsumerStatefulWidget {
}

class _AddPlateWeightsState extends ConsumerState<ConfigureAvailablePlates> {
final TextEditingController _barWeightController = TextEditingController();
bool _barWeightInitialized = false;
String? _barWeightError;

@override
void initState() {
super.initState();
Expand All @@ -71,14 +76,35 @@ class _AddPlateWeightsState extends ConsumerState<ConfigureAvailablePlates> {
});
}

@override
void dispose() {
_barWeightController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
final i18n = AppLocalizations.of(context);
final numberFormat = NumberFormat.decimalPattern(Localizations.localeOf(context).toString());

final plateWeightsState = ref.watch(plateCalculatorProvider);
final plateWeightsNotifier = ref.read(plateCalculatorProvider.notifier);
// final userProvider = provider.Provider.of<UserProvider>(context);

// Initialise the field with the current value and keep it in sync when the
// bar weight changes from outside the field (data loaded from prefs, unit
// switch, preset chips), without clobbering what the user is typing.
if (!_barWeightInitialized) {
_barWeightController.text = numberFormat.format(plateWeightsState.barWeight);
_barWeightInitialized = true;
}
ref.listen(plateCalculatorProvider.select((s) => s.barWeight), (_, barWeight) {
if (numberFormat.tryParse(_barWeightController.text) != barWeight) {
_barWeightController.text = numberFormat.format(barWeight);
_barWeightError = null;
}
});

return Column(
mainAxisSize: MainAxisSize.max,
children: [
Expand Down Expand Up @@ -108,24 +134,42 @@ class _AddPlateWeightsState extends ConsumerState<ConfigureAvailablePlates> {
),
Padding(
padding: const EdgeInsets.all(10),
child: DropdownMenu<num>(
key: const ValueKey('barWeightDropdown'),
width: double.infinity,
initialSelection: plateWeightsState.barWeight,
requestFocusOnTap: true,
label: Text(i18n.barWeight),
onSelected: (num? value) {
if (value == null) {
return;
}
plateWeightsNotifier.setBarWeight(value);
},
dropdownMenuEntries: plateWeightsState.availableBarsWeights.map((value) {
return DropdownMenuEntry<num>(
value: value,
label: value.toString(),
);
}).toList(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
key: const ValueKey('barWeightField'),
controller: _barWeightController,
keyboardType: const TextInputType.numberWithOptions(decimal: true),
decoration: InputDecoration(
labelText: i18n.barWeight,
errorText: _barWeightError,
),
onChanged: (value) {
final parsed = numberFormat.tryParse(value);
setState(() {
if (parsed == null || parsed <= 0) {
_barWeightError = i18n.enterValidNumber;
} else {
_barWeightError = null;
plateWeightsNotifier.setBarWeight(parsed);
}
});
},
),
const SizedBox(height: 8),
Wrap(
spacing: 8,
children: plateWeightsState.availableBarsWeights.map((value) {
return ChoiceChip(
key: ValueKey('barWeightChip-$value'),
label: Text(value.toString()),
selected: plateWeightsState.barWeight == value,
onSelected: (_) => plateWeightsNotifier.setBarWeight(value),
);
}).toList(),
),
],
),
),
SwitchListTile(
Expand Down
16 changes: 7 additions & 9 deletions test/widgets/routines/plate_calculator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,17 @@ void main() {
await tester.pumpAndSettle();
expect(notifier.state.isMetric, isFalse);

// Correctly changes the bar weight
// Correctly changes the bar weight via a preset chip
expect(notifier.state.barWeight, 45);
await tester.tap(find.byKey(const ValueKey('barWeightDropdown')));
await tester.pumpAndSettle();
final menuItem = find.ancestor(
of: find.text('25'),
matching: find.byType(InkWell),
);
expect(menuItem, findsOneWidget);
await tester.tap(menuItem);
await tester.tap(find.byKey(const ValueKey('barWeightChip-25')));
await tester.pumpAndSettle();
expect(notifier.state.barWeight, 25);

// Correctly accepts a custom bar weight typed into the field
await tester.enterText(find.byKey(const ValueKey('barWeightField')), '7.5');
await tester.pumpAndSettle();
expect(notifier.state.barWeight, 7.5);

// Correctly toggles the useColors switch
expect(notifier.state.useColors, isFalse);
await tester.tap(find.byKey(const ValueKey('useColorsSwitch')));
Expand Down