Give users more control over the exercise cache

This allows users to manually refresh the cache and load all exercises
from the server.
This commit is contained in:
Roland Geider
2025-09-06 00:04:45 +02:00
parent c89ccb630c
commit d85ee13ed9
10 changed files with 177 additions and 24 deletions

View File

@@ -20,10 +20,10 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/providers/user.dart';
import 'package:wger/screens/configure_plates_screen.dart';
import 'package:wger/widgets/core/settings/exercise_cache.dart';
class SettingsPage extends StatelessWidget {
static String routeName = '/SettingsPage';
@@ -33,7 +33,6 @@ class SettingsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final i18n = AppLocalizations.of(context);
final exerciseProvider = Provider.of<ExercisesProvider>(context, listen: false);
final nutritionProvider = Provider.of<NutritionPlansProvider>(context, listen: false);
final userProvider = Provider.of<UserProvider>(context);
@@ -47,24 +46,7 @@ class SettingsPage extends StatelessWidget {
style: Theme.of(context).textTheme.headlineSmall,
),
),
ListTile(
title: Text(i18n.settingsExerciseCacheDescription),
trailing: IconButton(
key: const ValueKey('cacheIconExercises'),
icon: const Icon(Icons.delete),
onPressed: () async {
await exerciseProvider.clearAllCachesAndPrefs();
if (context.mounted) {
final snackBar = SnackBar(
content: Text(i18n.settingsCacheDeletedSnackbar),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
},
),
),
const SettingsExerciseCache(),
ListTile(
title: Text(i18n.settingsIngredientCacheDescription),
trailing: IconButton(
@@ -83,6 +65,12 @@ class SettingsPage extends StatelessWidget {
},
),
),
ListTile(
title: Text(
i18n.others,
style: Theme.of(context).textTheme.headlineSmall,
),
),
ListTile(
title: Text(i18n.themeMode),
trailing: DropdownButton<ThemeMode>(

View File

@@ -0,0 +1,89 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/exercises.dart';
class SettingsExerciseCache extends StatefulWidget {
const SettingsExerciseCache({super.key});
@override
State<SettingsExerciseCache> createState() => _SettingsExerciseCacheState();
}
class _SettingsExerciseCacheState extends State<SettingsExerciseCache> {
bool _isRefreshLoading = false;
String _subtitle = '';
@override
Widget build(BuildContext context) {
final exerciseProvider = Provider.of<ExercisesProvider>(context, listen: false);
final i18n = AppLocalizations.of(context);
return ListTile(
enabled: !_isRefreshLoading,
title: Text(i18n.settingsExerciseCacheDescription),
subtitle: _subtitle.isNotEmpty ? Text(_subtitle) : null,
trailing: Row(mainAxisSize: MainAxisSize.min, children: [
IconButton(
key: const ValueKey('cacheIconExercisesRefresh'),
icon: _isRefreshLoading
? const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.refresh),
onPressed: _isRefreshLoading
? null
: () async {
setState(() => _isRefreshLoading = true);
// Note: status messages are currently left in English on purpose
try {
setState(() => _subtitle = 'Clearing cache...');
await exerciseProvider.clearAllCachesAndPrefs();
if (mounted) {
setState(() => _subtitle = 'Loading languages and units...');
}
await exerciseProvider.fetchAndSetInitialData();
if (mounted) {
setState(() => _subtitle = 'Loading all exercises from server...');
}
await exerciseProvider.fetchAndSetAllExercises();
if (mounted) {
setState(() => _subtitle = '');
}
} finally {
if (mounted) {
setState(() => _isRefreshLoading = false);
}
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(i18n.success)),
);
}
}
},
),
IconButton(
key: const ValueKey('cacheIconExercisesDelete'),
icon: const Icon(Icons.delete),
onPressed: () async {
await exerciseProvider.clearAllCachesAndPrefs();
if (context.mounted) {
final snackBar = SnackBar(
content: Text(i18n.settingsCacheDeletedSnackbar),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
},
)
]),
);
}
}