Merge pull request #791 from wger-project/fix/delete-workout-logs

Properly update the UI when deleting workout logs
This commit is contained in:
Roland Geider
2025-04-17 15:27:21 +02:00
committed by GitHub
25 changed files with 172 additions and 200 deletions

View File

@@ -1,4 +1,4 @@
import 'dart:ui';
import 'package:flutter/material.dart';
const LIST_OF_COLORS8 = [
Color(0xFF2A4C7D),
@@ -41,4 +41,9 @@ Iterable<Color> generateChartColors(int nrOfItems) sync* {
for (final color in colors) {
yield color;
}
// Always return black after generating nrOfItems colors
while (true) {
yield Colors.black;
}
}

View File

@@ -21,8 +21,6 @@ import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
import 'package:wger/exceptions/http_exception.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/exercises/translation.dart';
import 'package:wger/models/workouts/log.dart';
import 'package:wger/providers/routines.dart';
@@ -108,13 +106,7 @@ void showHttpExceptionErrorDialog(
showDialog(context: context, builder: (context) => Container());
}
dynamic showDeleteDialog(
BuildContext context,
String confirmDeleteName,
Log log,
Translation exercise,
Map<Exercise, List<Log>> exerciseData,
) async {
void showDeleteDialog(BuildContext context, String confirmDeleteName, Log log) async {
final res = await showDialog(
context: context,
builder: (BuildContext contextDialog) {
@@ -124,19 +116,18 @@ dynamic showDeleteDialog(
),
actions: [
TextButton(
key: const ValueKey('cancel-button'),
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
onPressed: () => Navigator.of(contextDialog).pop(),
),
TextButton(
key: const ValueKey('delete-button'),
child: Text(
AppLocalizations.of(context).delete,
style: TextStyle(color: Theme.of(context).colorScheme.error),
),
onPressed: () {
exerciseData[exercise]!.removeWhere((el) => el.id == log.id);
Provider.of<RoutinesProvider>(context, listen: false).deleteLog(
log,
);
context.read<RoutinesProvider>().deleteLog(log.id!, log.routineId);
Navigator.of(contextDialog).pop();

View File

@@ -19,7 +19,6 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:wger/helpers/json.dart';
import 'package:wger/helpers/misc.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/workouts/day.dart';
import 'package:wger/models/workouts/day_data.dart';
import 'package:wger/models/workouts/log.dart';
@@ -177,28 +176,4 @@ class Routine {
return groupedLogs;
}
/// Massages the log data to more easily present on the log overview
///
Map<DateTime, Map<String, dynamic>> get logData {
final out = <DateTime, Map<String, dynamic>>{};
for (final sessionData in sessions) {
final date = sessionData.session.date;
if (!out.containsKey(date)) {
out[date] = {
'session': sessionData.session,
'exercises': <Exercise, List<Log>>{},
};
}
for (final log in sessionData.logs) {
final exercise = log.exercise;
if (!out[date]!['exercises']!.containsKey(exercise)) {
out[date]!['exercises']![exercise] = <Log>[];
}
out[date]!['exercises']![exercise].add(log);
}
}
return out;
}
}

View File

@@ -17,6 +17,7 @@
*/
import 'package:json_annotation/json_annotation.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/workouts/log.dart';
import 'package:wger/models/workouts/session.dart';
@@ -32,6 +33,17 @@ class WorkoutSessionApi {
WorkoutSessionApi({required this.session, this.logs = const []});
/// Returns all different exercises in the session
///
/// This is used to display the exercises in the session
List<Exercise> get exercises {
final Set<Exercise> exerciseSet = {};
for (final log in logs) {
exerciseSet.add(log.exercise);
}
return exerciseSet.toList();
}
// Boilerplate
factory WorkoutSessionApi.fromJson(Map<String, dynamic> json) =>
_$WorkoutSessionApiFromJson(json);

View File

@@ -673,13 +673,9 @@ class RoutinesProvider with ChangeNotifier {
notifyListeners();
}*/
Future<void> deleteLog(Log log) async {
await baseProvider.deleteRequest(_logsUrlPath, log.id!);
for (final workout in _routines) {
for (final sessionData in workout.sessions) {
sessionData.session.logs.removeWhere((element) => element.id == log.id);
}
}
notifyListeners();
Future<void> deleteLog(int logId, int routineId) async {
_logger.fine('Deleting log ${logId}');
await baseProvider.deleteRequest(_logsUrlPath, logId);
await fetchAndSetRoutineFull(routineId);
}
}

View File

@@ -18,9 +18,8 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:wger/models/workouts/routine.dart';
import 'package:wger/providers/routines.dart';
import 'package:wger/widgets/routines/app_bar.dart';
import 'package:wger/widgets/core/app_bar.dart';
import 'package:wger/widgets/routines/workout_logs.dart';
class WorkoutLogsScreen extends StatelessWidget {
@@ -30,13 +29,12 @@ class WorkoutLogsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final routine = ModalRoute.of(context)!.settings.arguments as Routine;
final routineId = ModalRoute.of(context)!.settings.arguments as int;
final routine = Provider.of<RoutinesProvider>(context).findById(routineId);
return Scaffold(
appBar: RoutineDetailAppBar(routine),
body: Consumer<RoutinesProvider>(
builder: (context, value, child) => WorkoutLogs(routine),
),
appBar: EmptyAppBar(routine.name),
body: WorkoutLogs(routine),
);
}
}

View File

@@ -238,15 +238,10 @@ class MealItemEditableFullTile extends StatelessWidget {
return NutritionTile(
leading: IngredientAvatar(ingredient: _item.ingredient),
title: Row(
mainAxisSize: MainAxisSize.max,
children: [
Text(
'${_item.amount.toStringAsFixed(0)}$unit ${_item.ingredient.name}',
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.left,
),
],
title: Text(
'${_item.amount.toStringAsFixed(0)}$unit ${_item.ingredient.name}',
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.left,
),
subtitle: (_viewMode != viewMode.withAllDetails && !_editing)
? null

View File

@@ -122,7 +122,7 @@ class RoutineDetailAppBar extends StatelessWidget implements PreferredSizeWidget
Navigator.pushNamed(
context,
WorkoutLogsScreen.routeName,
arguments: routine,
arguments: routine.id,
);
case _RoutineDetailBarOptions.delete:

View File

@@ -22,7 +22,6 @@ import 'package:wger/helpers/colors.dart';
import 'package:wger/helpers/misc.dart';
import 'package:wger/helpers/ui.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/workouts/log.dart';
import 'package:wger/models/workouts/routine.dart';
import 'package:wger/models/workouts/session.dart';
@@ -116,18 +115,22 @@ class ExerciseLogChart extends StatelessWidget {
mainAxisSize: MainAxisSize.max,
children: [
LogChartWidgetFl(_logs, _selectedDate),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
..._logs.keys.map((reps) {
colors.moveNext();
return Indicator(
color: colors.current,
text: formatNum(reps).toString(),
isSquare: false,
);
}),
],
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
..._logs.keys.map((reps) {
colors.moveNext();
return Indicator(
color: colors.current,
text: formatNum(reps).toString(),
isSquare: false,
);
}),
],
),
),
const SizedBox(height: 15),
],
@@ -139,49 +142,42 @@ class DayLogWidget extends StatelessWidget {
final DateTime _date;
final Routine _routine;
final WorkoutSession _session;
final Map<Exercise, List<Log>> _exerciseMap;
const DayLogWidget(this._date, this._exerciseMap, this._session, this._routine);
const DayLogWidget(this._date, this._routine);
@override
Widget build(BuildContext context) {
final sessionApi =
_routine.sessions.firstWhere((sessionApi) => sessionApi.session.date.isSameDayAs(_date));
final exercises = sessionApi.exercises;
return Card(
child: Column(
children: [
SessionInfo(_session),
..._exerciseMap.keys.map((exercise) {
SessionInfo(sessionApi.session),
...exercises.map((exercise) {
final translation =
exercise.getTranslation(Localizations.localeOf(context).languageCode);
return Column(
children: [
if (_exerciseMap[exercise]!.isNotEmpty)
Text(
translation.name,
style: Theme.of(context).textTheme.headlineSmall,
)
else
Container(),
..._exerciseMap[exercise]!.map(
(log) => Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(log.singleLogRepTextNoNl),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
showDeleteDialog(
context,
translation.name,
log,
translation,
_exerciseMap,
);
},
),
],
),
Text(
translation.name,
style: Theme.of(context).textTheme.titleMedium,
),
...sessionApi.logs.where((l) => l.exerciseId == exercise.id).map(
(log) => Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(log.singleLogRepTextNoNl),
IconButton(
icon: const Icon(Icons.delete),
key: ValueKey('delete-log-${log.id}'),
onPressed: () {
showDeleteDialog(context, translation.name, log);
},
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: ExerciseLogChart(

View File

@@ -21,10 +21,7 @@ import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/workouts/log.dart';
import 'package:wger/models/workouts/routine.dart';
import 'package:wger/models/workouts/session.dart';
import 'package:wger/theme/theme.dart';
import 'package:wger/widgets/routines/log.dart';
@@ -49,27 +46,19 @@ class _WorkoutLogsState extends State<WorkoutLogs> {
@override
Widget build(BuildContext context) {
return ListView(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8),
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(
AppLocalizations.of(context).labelWorkoutLogs,
style: Theme.of(context).textTheme.headlineSmall,
),
Text(
AppLocalizations.of(context).labelWorkoutLogs,
style: Theme.of(context).textTheme.headlineSmall,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
AppLocalizations.of(context).logHelpEntries,
textAlign: TextAlign.justify,
),
Text(
AppLocalizations.of(context).logHelpEntries,
textAlign: TextAlign.justify,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
AppLocalizations.of(context).logHelpEntriesUnits,
textAlign: TextAlign.justify,
),
Text(
AppLocalizations.of(context).logHelpEntriesUnits,
textAlign: TextAlign.justify,
),
SizedBox(
width: double.infinity,
@@ -83,10 +72,8 @@ class _WorkoutLogsState extends State<WorkoutLogs> {
/// An event in the workout log calendar
class WorkoutLogEvent {
final DateTime dateTime;
final WorkoutSession session;
final Map<Exercise, List<Log>> exercises;
const WorkoutLogEvent(this.dateTime, this.session, this.exercises);
const WorkoutLogEvent(this.dateTime);
}
class WorkoutLogCalendar extends StatefulWidget {
@@ -101,8 +88,8 @@ class WorkoutLogCalendar extends StatefulWidget {
class _WorkoutLogCalendarState extends State<WorkoutLogCalendar> {
DateTime _focusedDay = clock.now();
DateTime? _selectedDay;
late final ValueNotifier<List<WorkoutLogEvent>> _selectedEvents;
late Map<String, List<WorkoutLogEvent>> _events;
late final ValueNotifier<List<DateTime>> _selectedEvents;
late Map<String, List<DateTime>> _events;
@override
void initState() {
@@ -121,18 +108,16 @@ class _WorkoutLogCalendarState extends State<WorkoutLogCalendar> {
}
void loadEvents() {
for (final date in widget._routine.logData.keys) {
final entry = widget._routine.logData[date]!;
_events[DateFormatLists.format(date)] = [
WorkoutLogEvent(date, entry['session'], entry['exercises']),
for (final sessionApi in widget._routine.sessions) {
_events[DateFormatLists.format(sessionApi.session.date)] = [
sessionApi.session.date,
];
}
// Add initial selected day to events list
_selectedEvents.value = _getEventsForDay(_selectedDay!);
}
List<WorkoutLogEvent> _getEventsForDay(DateTime day) {
List<DateTime> _getEventsForDay(DateTime day) {
return _events[DateFormatLists.format(day)] ?? [];
}
@@ -165,23 +150,17 @@ class _WorkoutLogCalendarState extends State<WorkoutLogCalendar> {
availableCalendarFormats: const {CalendarFormat.month: ''},
onDaySelected: _onDaySelected,
onPageChanged: (focusedDay) {
// No need to call `setState()` here
_focusedDay = focusedDay;
},
),
const SizedBox(height: 8.0),
SizedBox(
child: ValueListenableBuilder<List<WorkoutLogEvent>>(
child: ValueListenableBuilder<List<DateTime>>(
valueListenable: _selectedEvents,
builder: (context, logEvents, _) {
// At the moment there is only one "event" per day
return logEvents.isNotEmpty
? DayLogWidget(
logEvents.first.dateTime,
logEvents.first.exercises,
logEvents.first.session,
widget._routine,
)
? DayLogWidget(logEvents.first, widget._routine)
: Container();
},
),

View File

@@ -398,14 +398,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_calendar_carousel:
dependency: "direct main"
description:
name: flutter_calendar_carousel
sha256: "2fd1b58cefbefe0504ca7d0080a9e63be96041acc93b0c7f340ef0a55b9808fe"
url: "https://pub.dev"
source: hosted
version: "2.5.3"
flutter_driver:
dependency: transitive
description: flutter

View File

@@ -41,7 +41,6 @@ dependencies:
fl_chart: ^0.69.2
flex_color_scheme: ^8.1.1
flex_seed_scheme: ^3.5.1
flutter_calendar_carousel: ^2.4.4
flutter_html: ^3.0.0
flutter_staggered_grid_view: ^0.7.0
flutter_svg: ^2.0.17

View File

@@ -1,78 +1,88 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:wger/helpers/colors.dart';
void main() {
group('generateChartColors', () {
test('should generate 3 colors for 3 items using iterator', () {
test('should generate 3 colors for 3 items', () {
final iterator = generateChartColors(3).iterator;
final expectedColors = LIST_OF_COLORS3.iterator;
while (iterator.moveNext() && expectedColors.moveNext()) {
while (expectedColors.moveNext()) {
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(expectedColors.current));
}
expect(iterator.moveNext(), isFalse);
expect(expectedColors.moveNext(), isFalse);
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(Colors.black));
});
test('should generate 5 colors for 5 items using iterator', () {
test('should generate 5 colors for 5 items', () {
final iterator = generateChartColors(5).iterator;
final expectedColors = LIST_OF_COLORS5.iterator;
while (iterator.moveNext() && expectedColors.moveNext()) {
while (expectedColors.moveNext()) {
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(expectedColors.current));
}
expect(iterator.moveNext(), isFalse);
expect(expectedColors.moveNext(), isFalse);
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(Colors.black));
});
test('should generate 8 colors for 8 items using iterator', () {
test('should generate 8 colors for 8 items', () {
final iterator = generateChartColors(8).iterator;
final expectedColors = LIST_OF_COLORS8.iterator;
while (iterator.moveNext() && expectedColors.moveNext()) {
while (expectedColors.moveNext()) {
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(expectedColors.current));
}
expect(iterator.moveNext(), isFalse);
expect(expectedColors.moveNext(), isFalse);
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(Colors.black));
});
test('should generate 8 colors for more than 8 items using iterator', () {
test('should generate surplus color for more than 8 items', () {
final iterator = generateChartColors(10).iterator;
final expectedColors = LIST_OF_COLORS8.iterator;
while (iterator.moveNext() && expectedColors.moveNext()) {
while (expectedColors.moveNext()) {
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(expectedColors.current));
}
expect(iterator.moveNext(), isFalse);
expect(expectedColors.moveNext(), isFalse);
// After exhausting the 8 colors, it should always return black
for (int i = 0; i < 12; i++) {
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(Colors.black));
}
});
test('should generate 8 colors for 0 items using iterator', () {
test('should generate 3 colors for 0 items', () {
final iterator = generateChartColors(0).iterator;
final expectedColors = LIST_OF_COLORS3.iterator;
while (iterator.moveNext() && expectedColors.moveNext()) {
while (expectedColors.moveNext()) {
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(expectedColors.current));
}
expect(iterator.moveNext(), isFalse);
expect(expectedColors.moveNext(), isFalse);
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(Colors.black));
});
test('should generate 8 colors for negative items using iterator', () {
test('should generate 3 colors for negative number of items', () {
final iterator = generateChartColors(-5).iterator;
final expectedColors = LIST_OF_COLORS3.iterator;
while (iterator.moveNext() && expectedColors.moveNext()) {
while (expectedColors.moveNext()) {
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(expectedColors.current));
}
expect(iterator.moveNext(), isFalse);
expect(expectedColors.moveNext(), isFalse);
expect(iterator.moveNext(), isTrue);
expect(iterator.current, equals(Colors.black));
});
});
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -478,8 +478,8 @@ class MockRoutinesProvider extends _i1.Mock implements _i12.RoutinesProvider {
) as _i13.Future<_i11.Log>);
@override
_i13.Future<void> deleteLog(_i11.Log? log) => (super.noSuchMethod(
Invocation.method(#deleteLog, [log]),
_i13.Future<void> deleteLog(int? logId, int? routineId) => (super.noSuchMethod(
Invocation.method(#deleteLog, [logId, routineId]),
returnValue: _i13.Future<void>.value(),
returnValueForMissingStub: _i13.Future<void>.value(),
) as _i13.Future<void>);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -478,8 +478,8 @@ class MockRoutinesProvider extends _i1.Mock implements _i12.RoutinesProvider {
) as _i13.Future<_i11.Log>);
@override
_i13.Future<void> deleteLog(_i11.Log? log) => (super.noSuchMethod(
Invocation.method(#deleteLog, [log]),
_i13.Future<void> deleteLog(int? logId, int? routineId) => (super.noSuchMethod(
Invocation.method(#deleteLog, [logId, routineId]),
returnValue: _i13.Future<void>.value(),
returnValueForMissingStub: _i13.Future<void>.value(),
) as _i13.Future<void>);

View File

@@ -478,8 +478,8 @@ class MockRoutinesProvider extends _i1.Mock implements _i12.RoutinesProvider {
) as _i13.Future<_i11.Log>);
@override
_i13.Future<void> deleteLog(_i11.Log? log) => (super.noSuchMethod(
Invocation.method(#deleteLog, [log]),
_i13.Future<void> deleteLog(int? logId, int? routineId) => (super.noSuchMethod(
Invocation.method(#deleteLog, [logId, routineId]),
returnValue: _i13.Future<void>.value(),
returnValueForMissingStub: _i13.Future<void>.value(),
) as _i13.Future<void>);

View File

@@ -478,8 +478,8 @@ class MockRoutinesProvider extends _i1.Mock implements _i12.RoutinesProvider {
) as _i13.Future<_i11.Log>);
@override
_i13.Future<void> deleteLog(_i11.Log? log) => (super.noSuchMethod(
Invocation.method(#deleteLog, [log]),
_i13.Future<void> deleteLog(int? logId, int? routineId) => (super.noSuchMethod(
Invocation.method(#deleteLog, [logId, routineId]),
returnValue: _i13.Future<void>.value(),
returnValueForMissingStub: _i13.Future<void>.value(),
) as _i13.Future<void>);

View File

@@ -478,8 +478,8 @@ class MockRoutinesProvider extends _i1.Mock implements _i12.RoutinesProvider {
) as _i13.Future<_i11.Log>);
@override
_i13.Future<void> deleteLog(_i11.Log? log) => (super.noSuchMethod(
Invocation.method(#deleteLog, [log]),
_i13.Future<void> deleteLog(int? logId, int? routineId) => (super.noSuchMethod(
Invocation.method(#deleteLog, [logId, routineId]),
returnValue: _i13.Future<void>.value(),
returnValueForMissingStub: _i13.Future<void>.value(),
) as _i13.Future<void>);

View File

@@ -22,6 +22,7 @@ import 'package:clock/clock.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/workouts/routine.dart';
@@ -40,7 +41,9 @@ void main() {
setUp(() {
routine = getTestRoutine();
routine.logs[0].date = DateTime.now();
routine.sessions[0].session.date = DateTime(2025, 3, 29);
when(mockRoutinesProvider.findById(any)).thenAnswer((_) => routine);
});
Widget renderWidget({locale = 'en'}) {
@@ -56,7 +59,7 @@ void main() {
home: TextButton(
onPressed: () => key.currentState!.push(
MaterialPageRoute<void>(
settings: RouteSettings(arguments: routine),
settings: RouteSettings(arguments: routine.id),
builder: (_) => const WorkoutLogsScreen(),
),
),
@@ -89,8 +92,29 @@ void main() {
expect(find.text('Training logs'), findsOneWidget);
expect(find.byType(WorkoutLogCalendar), findsOneWidget);
expect(find.text('Bench press'), findsOneWidget);
expect(find.byKey(const ValueKey('delete-log-1')), findsOneWidget);
expect(find.byKey(const ValueKey('delete-log-2')), findsOneWidget);
expect(find.byKey(const ValueKey('delete-log-3')), findsNothing);
});
},
tags: ['golden'],
);
testWidgets('Test deleting log entries', (WidgetTester tester) async {
await withClock(Clock.fixed(DateTime(2025, 3, 29)), () async {
await tester.pumpWidget(renderWidget());
await tester.tap(find.byType(TextButton));
await tester.pumpAndSettle();
await tester.drag(find.byType(ListView), const Offset(0, -500));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const ValueKey('delete-log-1')));
await tester.pumpAndSettle();
expect(find.byKey(const ValueKey('delete-button')), findsOneWidget);
expect(find.byKey(const ValueKey('cancel-button')), findsOneWidget);
await tester.tap(find.byKey(const ValueKey('delete-button')));
verify(mockRoutinesProvider.deleteLog(1, 1)).called(1);
});
});
}

View File

@@ -478,8 +478,8 @@ class MockRoutinesProvider extends _i1.Mock implements _i12.RoutinesProvider {
) as _i13.Future<_i11.Log>);
@override
_i13.Future<void> deleteLog(_i11.Log? log) => (super.noSuchMethod(
Invocation.method(#deleteLog, [log]),
_i13.Future<void> deleteLog(int? logId, int? routineId) => (super.noSuchMethod(
Invocation.method(#deleteLog, [logId, routineId]),
returnValue: _i13.Future<void>.value(),
returnValueForMissingStub: _i13.Future<void>.value(),
) as _i13.Future<void>);

View File

@@ -478,8 +478,8 @@ class MockRoutinesProvider extends _i1.Mock implements _i12.RoutinesProvider {
) as _i13.Future<_i11.Log>);
@override
_i13.Future<void> deleteLog(_i11.Log? log) => (super.noSuchMethod(
Invocation.method(#deleteLog, [log]),
_i13.Future<void> deleteLog(int? logId, int? routineId) => (super.noSuchMethod(
Invocation.method(#deleteLog, [logId, routineId]),
returnValue: _i13.Future<void>.value(),
returnValueForMissingStub: _i13.Future<void>.value(),
) as _i13.Future<void>);

View File

@@ -478,8 +478,8 @@ class MockRoutinesProvider extends _i1.Mock implements _i12.RoutinesProvider {
) as _i13.Future<_i11.Log>);
@override
_i13.Future<void> deleteLog(_i11.Log? log) => (super.noSuchMethod(
Invocation.method(#deleteLog, [log]),
_i13.Future<void> deleteLog(int? logId, int? routineId) => (super.noSuchMethod(
Invocation.method(#deleteLog, [logId, routineId]),
returnValue: _i13.Future<void>.value(),
returnValueForMissingStub: _i13.Future<void>.value(),
) as _i13.Future<void>);