mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
Load context data for PR trophies
This allows us to show for which sets the user achieved new PRs
This commit is contained in:
@@ -263,6 +263,7 @@
|
||||
},
|
||||
"selectExercises": "If you want to do a superset you can search for several exercises, they will be grouped together",
|
||||
"@selectExercises": {},
|
||||
"personalRecords": "Personal records",
|
||||
"gymMode": "Gym mode",
|
||||
"@gymMode": {
|
||||
"description": "Label when starting the gym mode"
|
||||
|
||||
@@ -20,6 +20,7 @@ import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:wger/helpers/json.dart';
|
||||
|
||||
import 'trophy.dart';
|
||||
import 'user_trophy_context_data.dart';
|
||||
|
||||
part 'user_trophy.g.dart';
|
||||
|
||||
@@ -42,12 +43,16 @@ class UserTrophy {
|
||||
@JsonKey(required: true, name: 'is_notified')
|
||||
final bool isNotified;
|
||||
|
||||
@JsonKey(required: true, name: 'context_data')
|
||||
final ContextData? contextData;
|
||||
|
||||
UserTrophy({
|
||||
required this.id,
|
||||
required this.trophy,
|
||||
required this.earnedAt,
|
||||
required this.progress,
|
||||
required this.isNotified,
|
||||
this.contextData,
|
||||
});
|
||||
|
||||
// Boilerplate
|
||||
|
||||
@@ -15,6 +15,7 @@ UserTrophy _$UserTrophyFromJson(Map<String, dynamic> json) {
|
||||
'earned_at',
|
||||
'progress',
|
||||
'is_notified',
|
||||
'context_data',
|
||||
],
|
||||
);
|
||||
return UserTrophy(
|
||||
@@ -23,6 +24,9 @@ UserTrophy _$UserTrophyFromJson(Map<String, dynamic> json) {
|
||||
earnedAt: utcIso8601ToLocalDate(json['earned_at'] as String),
|
||||
progress: json['progress'] as num,
|
||||
isNotified: json['is_notified'] as bool,
|
||||
contextData: json['context_data'] == null
|
||||
? null
|
||||
: ContextData.fromJson(json['context_data'] as Map<String, dynamic>),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -32,4 +36,5 @@ Map<String, dynamic> _$UserTrophyToJson(UserTrophy instance) => <String, dynamic
|
||||
'earned_at': instance.earnedAt.toIso8601String(),
|
||||
'progress': instance.progress,
|
||||
'is_notified': instance.isNotified,
|
||||
'context_data': instance.contextData,
|
||||
};
|
||||
|
||||
75
lib/models/trophies/user_trophy_context_data.dart
Normal file
75
lib/models/trophies/user_trophy_context_data.dart
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of wger Workout Manager <https://github.com/wger-project>.
|
||||
* Copyright (c) 2025 wger Team
|
||||
*
|
||||
* wger Workout Manager is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:wger/helpers/json.dart';
|
||||
|
||||
part 'user_trophy_context_data.g.dart';
|
||||
|
||||
/// A trophy awarded to a user for achieving a specific milestone.
|
||||
|
||||
@JsonSerializable()
|
||||
class ContextData {
|
||||
@JsonKey(required: true, name: 'log_id')
|
||||
final int logId;
|
||||
|
||||
@JsonKey(required: true, fromJson: utcIso8601ToLocalDate)
|
||||
final DateTime date;
|
||||
|
||||
@JsonKey(required: true, name: 'session_id')
|
||||
final int sessionId;
|
||||
|
||||
@JsonKey(required: true, name: 'exercise_id')
|
||||
final int exerciseId;
|
||||
|
||||
@JsonKey(required: true, name: 'repetitions_unit_id')
|
||||
final int repetitionsUnitId;
|
||||
|
||||
@JsonKey(required: true)
|
||||
final num repetitions;
|
||||
|
||||
@JsonKey(required: true, name: 'weight_unit_id')
|
||||
final int weightUnitId;
|
||||
|
||||
@JsonKey(required: true)
|
||||
final num weight;
|
||||
|
||||
@JsonKey(required: true)
|
||||
final int? iteration;
|
||||
|
||||
@JsonKey(required: true, name: 'one_rep_max_estimate')
|
||||
final num oneRepMaxEstimate;
|
||||
|
||||
ContextData({
|
||||
required this.logId,
|
||||
required this.date,
|
||||
required this.sessionId,
|
||||
required this.exerciseId,
|
||||
required this.repetitionsUnitId,
|
||||
required this.repetitions,
|
||||
required this.weightUnitId,
|
||||
required this.weight,
|
||||
this.iteration,
|
||||
required this.oneRepMaxEstimate,
|
||||
});
|
||||
|
||||
// Boilerplate
|
||||
factory ContextData.fromJson(Map<String, dynamic> json) => _$ContextDataFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ContextDataToJson(this);
|
||||
}
|
||||
50
lib/models/trophies/user_trophy_context_data.g.dart
Normal file
50
lib/models/trophies/user_trophy_context_data.g.dart
Normal file
@@ -0,0 +1,50 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'user_trophy_context_data.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ContextData _$ContextDataFromJson(Map<String, dynamic> json) {
|
||||
$checkKeys(
|
||||
json,
|
||||
requiredKeys: const [
|
||||
'log_id',
|
||||
'date',
|
||||
'session_id',
|
||||
'exercise_id',
|
||||
'repetitions_unit_id',
|
||||
'repetitions',
|
||||
'weight_unit_id',
|
||||
'weight',
|
||||
'iteration',
|
||||
'one_rep_max_estimate',
|
||||
],
|
||||
);
|
||||
return ContextData(
|
||||
logId: (json['log_id'] as num).toInt(),
|
||||
date: utcIso8601ToLocalDate(json['date'] as String),
|
||||
sessionId: (json['session_id'] as num).toInt(),
|
||||
exerciseId: (json['exercise_id'] as num).toInt(),
|
||||
repetitionsUnitId: (json['repetitions_unit_id'] as num).toInt(),
|
||||
repetitions: json['repetitions'] as num,
|
||||
weightUnitId: (json['weight_unit_id'] as num).toInt(),
|
||||
weight: json['weight'] as num,
|
||||
iteration: (json['iteration'] as num?)?.toInt(),
|
||||
oneRepMaxEstimate: json['one_rep_max_estimate'] as num,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$ContextDataToJson(ContextData instance) => <String, dynamic>{
|
||||
'log_id': instance.logId,
|
||||
'date': instance.date.toIso8601String(),
|
||||
'session_id': instance.sessionId,
|
||||
'exercise_id': instance.exerciseId,
|
||||
'repetitions_unit_id': instance.repetitionsUnitId,
|
||||
'repetitions': instance.repetitions,
|
||||
'weight_unit_id': instance.weightUnitId,
|
||||
'weight': instance.weight,
|
||||
'iteration': instance.iteration,
|
||||
'one_rep_max_estimate': instance.oneRepMaxEstimate,
|
||||
};
|
||||
@@ -481,7 +481,7 @@ class GymStateNotifier extends _$GymStateNotifier {
|
||||
pages.add(PageEntry(type: PageType.workoutSummary, pageIndex: pageIndex + 1));
|
||||
|
||||
state = state.copyWith(pages: pages);
|
||||
print(readPageStructure());
|
||||
// _logger.fine(readPageStructure());
|
||||
_logger.finer('Initialized ${state.pages.length} pages');
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ final class GymStateNotifierProvider extends $NotifierProvider<GymStateNotifier,
|
||||
}
|
||||
}
|
||||
|
||||
String _$gymStateNotifierHash() => r'4e1ac85de3c9f5c7dad4b0c5e6ad80ad36397610';
|
||||
String _$gymStateNotifierHash() => r'8474afce33638bf67570fd64b64e9b5d171804d3';
|
||||
|
||||
abstract class _$GymStateNotifier extends $Notifier<GymModeState> {
|
||||
GymModeState build();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/models/trophies/trophy.dart';
|
||||
@@ -28,6 +29,8 @@ import 'base_provider.dart';
|
||||
part 'trophies.g.dart';
|
||||
|
||||
class TrophyRepository {
|
||||
final _logger = Logger('TrophyRepository');
|
||||
|
||||
final WgerBaseProvider base;
|
||||
final trophiesPath = 'trophy';
|
||||
final userTrophiesPath = 'user-trophy';
|
||||
@@ -36,21 +39,43 @@ class TrophyRepository {
|
||||
TrophyRepository(this.base);
|
||||
|
||||
Future<List<Trophy>> fetchTrophies() async {
|
||||
final url = base.makeUrl(trophiesPath, query: {'limit': API_MAX_PAGE_SIZE});
|
||||
final trophyData = await base.fetchPaginated(url);
|
||||
return trophyData.map((e) => Trophy.fromJson(e)).toList();
|
||||
try {
|
||||
final url = base.makeUrl(trophiesPath, query: {'limit': API_MAX_PAGE_SIZE});
|
||||
final trophyData = await base.fetchPaginated(url);
|
||||
return trophyData.map((e) => Trophy.fromJson(e)).toList();
|
||||
} catch (e, stk) {
|
||||
_logger.warning('Error fetching trophies:', e, stk);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<UserTrophy>> fetchUserTrophies() async {
|
||||
final url = base.makeUrl(userTrophiesPath, query: {'limit': API_MAX_PAGE_SIZE});
|
||||
final trophyData = await base.fetchPaginated(url);
|
||||
return trophyData.map((e) => UserTrophy.fromJson(e)).toList();
|
||||
Future<List<UserTrophy>> fetchUserTrophies({Map<String, String>? filterQuery}) async {
|
||||
final query = {'limit': API_MAX_PAGE_SIZE};
|
||||
if (filterQuery != null) {
|
||||
query.addAll(filterQuery);
|
||||
}
|
||||
|
||||
try {
|
||||
final url = base.makeUrl(userTrophiesPath, query: query);
|
||||
final trophyData = await base.fetchPaginated(url);
|
||||
return trophyData.map((e) => UserTrophy.fromJson(e)).toList();
|
||||
} catch (e, stk) {
|
||||
_logger.warning('Error fetching user trophies:');
|
||||
_logger.warning(e);
|
||||
_logger.warning(stk);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<UserTrophyProgression>> fetchProgression() async {
|
||||
final url = base.makeUrl(userTrophyProgressionPath);
|
||||
final List<dynamic> data = await base.fetch(url);
|
||||
return data.map((e) => UserTrophyProgression.fromJson(e)).toList();
|
||||
Future<List<UserTrophyProgression>> fetchProgression({Map<String, String>? filterQuery}) async {
|
||||
try {
|
||||
final url = base.makeUrl(userTrophyProgressionPath, query: filterQuery);
|
||||
final List<dynamic> data = await base.fetch(url);
|
||||
return data.map((e) => UserTrophyProgression.fromJson(e)).toList();
|
||||
} catch (e, stk) {
|
||||
_logger.warning('Error fetching user trophy progression:', e, stk);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
List<Trophy> filterByType(List<Trophy> list, TrophyType type) =>
|
||||
@@ -74,15 +99,27 @@ final class TrophyStateNotifier extends _$TrophyStateNotifier {
|
||||
return repo.fetchTrophies();
|
||||
}
|
||||
|
||||
/// Fetch trophies awarded to the user
|
||||
/// Fetch trophies awarded to the user.
|
||||
/// Excludes hidden trophies as well as repeatable (PR) trophies since they are
|
||||
/// handled separately
|
||||
Future<List<UserTrophy>> fetchUserTrophies() async {
|
||||
final repo = ref.read(trophyRepositoryProvider);
|
||||
return repo.fetchUserTrophies();
|
||||
return repo.fetchUserTrophies(
|
||||
filterQuery: {'trophy__is_hidden': 'false', 'trophy__is_repeatable': 'false'},
|
||||
);
|
||||
}
|
||||
|
||||
/// Fetch PR trophies awarded to the user
|
||||
Future<List<UserTrophy>> fetchUserPRTrophies() async {
|
||||
final repo = ref.read(trophyRepositoryProvider);
|
||||
return repo.fetchUserTrophies(filterQuery: {'trophy__trophy_type': TrophyType.pr.name});
|
||||
}
|
||||
|
||||
/// Fetch trophy progression for the user
|
||||
Future<List<UserTrophyProgression>> fetchTrophyProgression() async {
|
||||
final repo = ref.read(trophyRepositoryProvider);
|
||||
return repo.fetchProgression();
|
||||
return repo.fetchProgression(
|
||||
filterQuery: {'trophy__is_hidden': 'false', 'trophy__is_repeatable': 'false'},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ final class TrophyStateNotifierProvider extends $NotifierProvider<TrophyStateNot
|
||||
}
|
||||
}
|
||||
|
||||
String _$trophyStateNotifierHash() => r'e5c8f2a9477b8f7e5efe4e9ba23765f951627a9f';
|
||||
String _$trophyStateNotifierHash() => r'7f50ce352d980168dae169916a17d9b62b388d28';
|
||||
|
||||
abstract class _$TrophyStateNotifier extends $Notifier<void> {
|
||||
void build();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of wger Workout Manager <https://github.com/wger-project>.
|
||||
* Copyright (c) 2020, 2025 wger Team
|
||||
* Copyright (c) 2020 - 2025 wger Team
|
||||
*
|
||||
* wger Workout Manager is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
@@ -24,10 +24,12 @@ import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/date.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/trophies/user_trophy.dart';
|
||||
import 'package:wger/models/workouts/routine.dart';
|
||||
import 'package:wger/models/workouts/session_api.dart';
|
||||
import 'package:wger/providers/gym_state.dart';
|
||||
import 'package:wger/providers/routines.dart';
|
||||
import 'package:wger/providers/trophies.dart';
|
||||
import 'package:wger/widgets/core/progress_indicator.dart';
|
||||
import 'package:wger/widgets/routines/gym_mode/navigation.dart';
|
||||
|
||||
@@ -48,6 +50,7 @@ class WorkoutSummary extends ConsumerStatefulWidget {
|
||||
class _WorkoutSummaryState extends ConsumerState<WorkoutSummary> {
|
||||
late Future<void> _initData;
|
||||
late Routine _routine;
|
||||
late List<UserTrophy> _userPrTrophies;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -62,6 +65,9 @@ class _WorkoutSummaryState extends ConsumerState<WorkoutSummary> {
|
||||
_routine = await context.read<RoutinesProvider>().fetchAndSetRoutineFull(
|
||||
gymState.routine.id!,
|
||||
);
|
||||
|
||||
final trophyNotifier = ref.read(trophyStateProvider.notifier);
|
||||
_userPrTrophies = await trophyNotifier.fetchUserPRTrophies();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -82,10 +88,18 @@ class _WorkoutSummaryState extends ConsumerState<WorkoutSummary> {
|
||||
} else if (snapshot.hasError) {
|
||||
return Center(child: Text('Error: ${snapshot.error}: ${snapshot.stackTrace}'));
|
||||
} else if (snapshot.connectionState == ConnectionState.done) {
|
||||
final apiSession = _routine.sessions.firstWhereOrNull(
|
||||
(s) => s.session.date.isSameDayAs(clock.now()),
|
||||
);
|
||||
final userTrophies = _userPrTrophies
|
||||
.where(
|
||||
(t) => t.contextData!.sessionId == apiSession?.session.id,
|
||||
)
|
||||
.toList();
|
||||
|
||||
return WorkoutSessionStats(
|
||||
_routine.sessions.firstWhereOrNull(
|
||||
(s) => s.session.date.isSameDayAs(clock.now()),
|
||||
),
|
||||
apiSession,
|
||||
userTrophies,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -102,12 +116,14 @@ class _WorkoutSummaryState extends ConsumerState<WorkoutSummary> {
|
||||
class WorkoutSessionStats extends ConsumerWidget {
|
||||
final _logger = Logger('WorkoutSessionStats');
|
||||
final WorkoutSessionApi? _sessionApi;
|
||||
final List<UserTrophy> _userPrTrophies;
|
||||
|
||||
WorkoutSessionStats(this._sessionApi, {super.key});
|
||||
WorkoutSessionStats(this._sessionApi, this._userPrTrophies, {super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final i18n = AppLocalizations.of(context);
|
||||
final theme = Theme.of(context);
|
||||
|
||||
if (_sessionApi == null) {
|
||||
return Center(
|
||||
@@ -159,16 +175,19 @@ class WorkoutSessionStats extends ConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
// const SizedBox(height: 16),
|
||||
// InfoCard(
|
||||
// title: 'Personal Records',
|
||||
// value: prCount.toString(),
|
||||
// color: theme.colorScheme.tertiaryContainer,
|
||||
// ),
|
||||
if (_userPrTrophies.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: InfoCard(
|
||||
title: i18n.personalRecords,
|
||||
value: _userPrTrophies.length.toString(),
|
||||
color: theme.colorScheme.tertiaryContainer,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MuscleGroupsCard(_sessionApi.logs),
|
||||
const SizedBox(height: 10),
|
||||
ExercisesCard(_sessionApi),
|
||||
ExercisesCard(_sessionApi, _userPrTrophies),
|
||||
FilledButton(
|
||||
onPressed: () {
|
||||
ref.read(gymStateProvider.notifier).clear();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of wger Workout Manager <https://github.com/wger-project>.
|
||||
* Copyright (c) 2020, 2025 wger Team
|
||||
* Copyright (c) 2020 - 2025 wger Team
|
||||
*
|
||||
* wger Workout Manager is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
@@ -20,13 +20,15 @@ import 'package:flutter/material.dart';
|
||||
import 'package:wger/helpers/i18n.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/exercises/exercise.dart';
|
||||
import 'package:wger/models/trophies/user_trophy.dart';
|
||||
import 'package:wger/models/workouts/log.dart';
|
||||
import 'package:wger/models/workouts/session_api.dart';
|
||||
|
||||
class ExercisesCard extends StatelessWidget {
|
||||
final WorkoutSessionApi session;
|
||||
final List<UserTrophy> userPrTrophies;
|
||||
|
||||
const ExercisesCard(this.session, {super.key});
|
||||
const ExercisesCard(this.session, this.userPrTrophies, {super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -44,7 +46,11 @@ class ExercisesCard extends StatelessWidget {
|
||||
const SizedBox(height: 16),
|
||||
...exercises.map((exercise) {
|
||||
final logs = session.logs.where((log) => log.exerciseId == exercise.id).toList();
|
||||
return _ExerciseExpansionTile(exercise: exercise, logs: logs);
|
||||
return _ExerciseExpansionTile(
|
||||
exercise: exercise,
|
||||
logs: logs,
|
||||
userPrTrophies: userPrTrophies,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
@@ -57,8 +63,10 @@ class _ExerciseExpansionTile extends StatelessWidget {
|
||||
const _ExerciseExpansionTile({
|
||||
required this.exercise,
|
||||
required this.logs,
|
||||
required this.userPrTrophies,
|
||||
});
|
||||
|
||||
final List<UserTrophy> userPrTrophies;
|
||||
final Exercise exercise;
|
||||
final List<Log> logs;
|
||||
|
||||
@@ -78,20 +86,20 @@ class _ExerciseExpansionTile extends StatelessWidget {
|
||||
// leading: const Icon(Icons.fitness_center),
|
||||
title: Text(exercise.getTranslation(languageCode).name, style: theme.textTheme.titleMedium),
|
||||
subtitle: Text('Top set: $topSetWeight $topSetWeightUnit'),
|
||||
children: logs.map((log) => _SetDataRow(log: log)).toList(),
|
||||
children: logs.map((log) => _SetDataRow(log: log, userPrTrophies: userPrTrophies)).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SetDataRow extends StatelessWidget {
|
||||
const _SetDataRow({required this.log});
|
||||
const _SetDataRow({required this.log, required this.userPrTrophies});
|
||||
|
||||
final Log log;
|
||||
final List<UserTrophy> userPrTrophies;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final i18n = AppLocalizations.of(context);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||
@@ -103,6 +111,8 @@ class _SetDataRow extends StatelessWidget {
|
||||
log.repTextNoNl(context),
|
||||
style: theme.textTheme.bodyMedium,
|
||||
),
|
||||
if (userPrTrophies.any((trophy) => trophy.contextData?.logId == log.id))
|
||||
Icon(Icons.emoji_events, color: theme.colorScheme.primary, size: 20),
|
||||
// if (log.volume() > 0)
|
||||
// Text(
|
||||
// '${log.volume().toStringAsFixed(0)} ${getServerStringTranslation(log.weightUnitObj!.name, context)}',
|
||||
|
||||
@@ -1107,6 +1107,17 @@ class MockAppLocalizations extends _i1.Mock implements _i2.AppLocalizations {
|
||||
)
|
||||
as String);
|
||||
|
||||
@override
|
||||
String get personalRecords =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.getter(#personalRecords),
|
||||
returnValue: _i3.dummyValue<String>(
|
||||
this,
|
||||
Invocation.getter(#personalRecords),
|
||||
),
|
||||
)
|
||||
as String);
|
||||
|
||||
@override
|
||||
String get gymMode =>
|
||||
(super.noSuchMethod(
|
||||
|
||||
@@ -33,7 +33,9 @@ void main() {
|
||||
testWidgets('DashboardTrophiesWidget shows trophies', (WidgetTester tester) async {
|
||||
// Arrange
|
||||
final mockRepository = MockTrophyRepository();
|
||||
when(mockRepository.fetchUserTrophies()).thenAnswer((_) async => getUserTrophies());
|
||||
when(
|
||||
mockRepository.fetchUserTrophies(filterQuery: anyNamed('filterQuery')),
|
||||
).thenAnswer((_) async => getUserTrophies());
|
||||
|
||||
// Act
|
||||
await mockNetworkImagesFor(() async {
|
||||
@@ -52,7 +54,6 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Assert
|
||||
// expect(find.text('Trophies'), findsOneWidget);
|
||||
expect(find.text('New Year, New Me'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -94,9 +94,13 @@ class MockTrophyRepository extends _i1.Mock implements _i3.TrophyRepository {
|
||||
as _i5.Future<List<_i6.Trophy>>);
|
||||
|
||||
@override
|
||||
_i5.Future<List<_i7.UserTrophy>> fetchUserTrophies() =>
|
||||
_i5.Future<List<_i7.UserTrophy>> fetchUserTrophies({
|
||||
Map<String, String>? filterQuery,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(#fetchUserTrophies, []),
|
||||
Invocation.method(#fetchUserTrophies, [], {
|
||||
#filterQuery: filterQuery,
|
||||
}),
|
||||
returnValue: _i5.Future<List<_i7.UserTrophy>>.value(
|
||||
<_i7.UserTrophy>[],
|
||||
),
|
||||
@@ -104,9 +108,13 @@ class MockTrophyRepository extends _i1.Mock implements _i3.TrophyRepository {
|
||||
as _i5.Future<List<_i7.UserTrophy>>);
|
||||
|
||||
@override
|
||||
_i5.Future<List<_i8.UserTrophyProgression>> fetchProgression() =>
|
||||
_i5.Future<List<_i8.UserTrophyProgression>> fetchProgression({
|
||||
Map<String, String>? filterQuery,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(#fetchProgression, []),
|
||||
Invocation.method(#fetchProgression, [], {
|
||||
#filterQuery: filterQuery,
|
||||
}),
|
||||
returnValue: _i5.Future<List<_i8.UserTrophyProgression>>.value(
|
||||
<_i8.UserTrophyProgression>[],
|
||||
),
|
||||
|
||||
@@ -33,7 +33,9 @@ void main() {
|
||||
testWidgets('TrophiesOverview shows trophies', (WidgetTester tester) async {
|
||||
// Arrange
|
||||
final mockRepository = MockTrophyRepository();
|
||||
when(mockRepository.fetchProgression()).thenAnswer((_) async => getUserTrophyProgression());
|
||||
when(
|
||||
mockRepository.fetchProgression(filterQuery: anyNamed('filterQuery')),
|
||||
).thenAnswer((_) async => getUserTrophyProgression());
|
||||
|
||||
// Act
|
||||
await mockNetworkImagesFor(() async {
|
||||
|
||||
131
test/trophies/widgets/trophies_overview_test.mocks.dart
Normal file
131
test/trophies/widgets/trophies_overview_test.mocks.dart
Normal file
@@ -0,0 +1,131 @@
|
||||
// Mocks generated by Mockito 5.4.6 from annotations
|
||||
// in wger/test/trophies/widgets/trophies_overview_test.dart.
|
||||
// Do not manually edit this file.
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:async' as _i5;
|
||||
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
import 'package:mockito/src/dummies.dart' as _i4;
|
||||
import 'package:wger/models/trophies/trophy.dart' as _i6;
|
||||
import 'package:wger/models/trophies/user_trophy.dart' as _i7;
|
||||
import 'package:wger/models/trophies/user_trophy_progression.dart' as _i8;
|
||||
import 'package:wger/providers/base_provider.dart' as _i2;
|
||||
import 'package:wger/providers/trophies.dart' as _i3;
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: avoid_redundant_argument_values
|
||||
// ignore_for_file: avoid_setters_without_getters
|
||||
// ignore_for_file: comment_references
|
||||
// ignore_for_file: deprecated_member_use
|
||||
// ignore_for_file: deprecated_member_use_from_same_package
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: invalid_use_of_visible_for_testing_member
|
||||
// ignore_for_file: must_be_immutable
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
// ignore_for_file: unnecessary_parenthesis
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: subtype_of_sealed_class
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
|
||||
class _FakeWgerBaseProvider_0 extends _i1.SmartFake implements _i2.WgerBaseProvider {
|
||||
_FakeWgerBaseProvider_0(Object parent, Invocation parentInvocation)
|
||||
: super(parent, parentInvocation);
|
||||
}
|
||||
|
||||
/// A class which mocks [TrophyRepository].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockTrophyRepository extends _i1.Mock implements _i3.TrophyRepository {
|
||||
MockTrophyRepository() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_i2.WgerBaseProvider get base =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.getter(#base),
|
||||
returnValue: _FakeWgerBaseProvider_0(
|
||||
this,
|
||||
Invocation.getter(#base),
|
||||
),
|
||||
)
|
||||
as _i2.WgerBaseProvider);
|
||||
|
||||
@override
|
||||
String get trophiesPath =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.getter(#trophiesPath),
|
||||
returnValue: _i4.dummyValue<String>(
|
||||
this,
|
||||
Invocation.getter(#trophiesPath),
|
||||
),
|
||||
)
|
||||
as String);
|
||||
|
||||
@override
|
||||
String get userTrophiesPath =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.getter(#userTrophiesPath),
|
||||
returnValue: _i4.dummyValue<String>(
|
||||
this,
|
||||
Invocation.getter(#userTrophiesPath),
|
||||
),
|
||||
)
|
||||
as String);
|
||||
|
||||
@override
|
||||
String get userTrophyProgressionPath =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.getter(#userTrophyProgressionPath),
|
||||
returnValue: _i4.dummyValue<String>(
|
||||
this,
|
||||
Invocation.getter(#userTrophyProgressionPath),
|
||||
),
|
||||
)
|
||||
as String);
|
||||
|
||||
@override
|
||||
_i5.Future<List<_i6.Trophy>> fetchTrophies() =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(#fetchTrophies, []),
|
||||
returnValue: _i5.Future<List<_i6.Trophy>>.value(<_i6.Trophy>[]),
|
||||
)
|
||||
as _i5.Future<List<_i6.Trophy>>);
|
||||
|
||||
@override
|
||||
_i5.Future<List<_i7.UserTrophy>> fetchUserTrophies({
|
||||
Map<String, String>? filterQuery,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(#fetchUserTrophies, [], {
|
||||
#filterQuery: filterQuery,
|
||||
}),
|
||||
returnValue: _i5.Future<List<_i7.UserTrophy>>.value(
|
||||
<_i7.UserTrophy>[],
|
||||
),
|
||||
)
|
||||
as _i5.Future<List<_i7.UserTrophy>>);
|
||||
|
||||
@override
|
||||
_i5.Future<List<_i8.UserTrophyProgression>> fetchProgression({
|
||||
Map<String, String>? filterQuery,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(#fetchProgression, [], {
|
||||
#filterQuery: filterQuery,
|
||||
}),
|
||||
returnValue: _i5.Future<List<_i8.UserTrophyProgression>>.value(
|
||||
<_i8.UserTrophyProgression>[],
|
||||
),
|
||||
)
|
||||
as _i5.Future<List<_i8.UserTrophyProgression>>);
|
||||
|
||||
@override
|
||||
List<_i6.Trophy> filterByType(List<_i6.Trophy>? list, _i6.TrophyType? type) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(#filterByType, [list, type]),
|
||||
returnValue: <_i6.Trophy>[],
|
||||
)
|
||||
as List<_i6.Trophy>);
|
||||
}
|
||||
Reference in New Issue
Block a user