diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 003c43ea..6d845a4f 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -100,6 +100,7 @@ "@labelWorkoutPlan": { "description": "Title for screen workout plan" }, + "dashboardWidgets": "Dashboard widgets", "labelDashboard": "Dashboard", "@labelDashboard": { "description": "Title for screen dashboard" diff --git a/lib/main.dart b/lib/main.dart index 47761881..577f346e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,13 +1,13 @@ /* * This file is part of wger Workout Manager . - * Copyright (C) 2020, 2021 wger Team + * Copyright (c) 2026 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. * - * wger Workout Manager is distributed in the hope that it will be useful, + * 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. @@ -37,7 +37,6 @@ import 'package:wger/providers/routines.dart'; import 'package:wger/providers/user.dart'; import 'package:wger/screens/add_exercise_screen.dart'; import 'package:wger/screens/auth_screen.dart'; -import 'package:wger/screens/configure_plates_screen.dart'; import 'package:wger/screens/dashboard.dart'; import 'package:wger/screens/exercise_screen.dart'; import 'package:wger/screens/exercises_screen.dart'; @@ -56,6 +55,8 @@ import 'package:wger/screens/routine_edit_screen.dart'; import 'package:wger/screens/routine_list_screen.dart'; import 'package:wger/screens/routine_logs_screen.dart'; import 'package:wger/screens/routine_screen.dart'; +import 'package:wger/screens/settings_dashboard_widgets_screen.dart'; +import 'package:wger/screens/settings_plates_screen.dart'; import 'package:wger/screens/splash_screen.dart'; import 'package:wger/screens/update_app_screen.dart'; import 'package:wger/screens/weight_screen.dart'; @@ -252,6 +253,8 @@ class MainApp extends StatelessWidget { SettingsPage.routeName: (ctx) => const SettingsPage(), LogOverviewPage.routeName: (ctx) => const LogOverviewPage(), ConfigurePlatesScreen.routeName: (ctx) => const ConfigurePlatesScreen(), + ConfigureDashboardWidgetsScreen.routeName: (ctx) => + const ConfigureDashboardWidgetsScreen(), }, localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, diff --git a/lib/providers/user.dart b/lib/providers/user.dart index 27f7516d..e2dc2664 100644 --- a/lib/providers/user.dart +++ b/lib/providers/user.dart @@ -1,6 +1,6 @@ /* * This file is part of wger Workout Manager . - * Copyright (C) 2020, 2021 wger Team + * Copyright (c) 2026 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 @@ -26,19 +26,36 @@ import 'package:wger/helpers/shared_preferences.dart'; import 'package:wger/models/user/profile.dart'; import 'package:wger/providers/base_provider.dart'; +enum DashboardWidget { + routines('routines'), + weight('weight'), + measurements('measurements'), + calendar('calendar'), + nutrition('nutrition'); + + final String value; + const DashboardWidget(this.value); + + static DashboardWidget? fromString(String s) { + for (final e in DashboardWidget.values) { + if (e.value == s) return e; + } + return null; + } +} + class UserProvider with ChangeNotifier { ThemeMode themeMode = ThemeMode.system; final WgerBaseProvider baseProvider; late SharedPreferencesAsync prefs; - // bool hideNutrition = false; // New: visibility state for dashboard widgets - Map dashboardWidgetVisibility = { - 'routines': true, - 'weight': true, - 'measurements': true, - 'calendar': true, - 'nutrition': true, + Map dashboardWidgetVisibility = { + DashboardWidget.routines: true, + DashboardWidget.weight: true, + DashboardWidget.measurements: true, + DashboardWidget.calendar: true, + DashboardWidget.nutrition: true, }; static const String PREFS_DASHBOARD_VISIBILITY = 'dashboardWidgetVisibility'; @@ -80,31 +97,47 @@ class UserProvider with ChangeNotifier { notifyListeners(); } - Future _loadDashboardVisibility() async { - final jsonString = await prefs.getString(PREFS_DASHBOARD_VISIBILITY); - if (jsonString != null) { - try { - final decoded = jsonDecode(jsonString) as Map; - dashboardWidgetVisibility = - decoded.map((k, v) => MapEntry(k, v as bool)); - } catch (_) { - // If parsing fails, keep defaults + Future _loadDashboardVisibility() async { + final jsonString = await prefs.getString(PREFS_DASHBOARD_VISIBILITY); + if (jsonString == null) { + return; + } + + try { + final decoded = jsonDecode(jsonString) as Map; + final Map loaded = {}; + + for (final entry in decoded.entries) { + final widget = DashboardWidget.fromString(entry.key); + if (widget != null) { + loaded[widget] = entry.value as bool; + } } + + if (loaded.isNotEmpty) { + dashboardWidgetVisibility = loaded; + } + } catch (_) { + // parsing failed -> keep defaults } notifyListeners(); } - bool isDashboardWidgetVisible(String key) { + bool isDashboardWidgetVisible(DashboardWidget key) { return dashboardWidgetVisibility[key] ?? true; } - Future setDashboardWidgetVisible(String key, bool visible) async { + Future setDashboardWidgetVisible(DashboardWidget key, bool visible) async { dashboardWidgetVisibility[key] = visible; + final Map serializable = { + for (final e in dashboardWidgetVisibility.entries) e.key.value: e.value, + }; + await prefs.setString( PREFS_DASHBOARD_VISIBILITY, - jsonEncode(dashboardWidgetVisibility), + jsonEncode(serializable), ); notifyListeners(); } @@ -133,7 +166,6 @@ class UserProvider with ChangeNotifier { } } - /// Save the user's profile to the server Future saveProfile() async { await baseProvider.post( diff --git a/lib/screens/dashboard.dart b/lib/screens/dashboard.dart index ae41069e..dae86cb0 100644 --- a/lib/screens/dashboard.dart +++ b/lib/screens/dashboard.dart @@ -19,13 +19,13 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:wger/l10n/generated/app_localizations.dart'; +import 'package:wger/providers/user.dart'; import 'package:wger/widgets/core/app_bar.dart'; import 'package:wger/widgets/dashboard/calendar.dart'; import 'package:wger/widgets/dashboard/widgets/measurements.dart'; import 'package:wger/widgets/dashboard/widgets/nutrition.dart'; import 'package:wger/widgets/dashboard/widgets/routines.dart'; import 'package:wger/widgets/dashboard/widgets/weight.dart'; -import 'package:wger/providers/user.dart'; class DashboardScreen extends StatelessWidget { const DashboardScreen({super.key}); @@ -42,19 +42,19 @@ class DashboardScreen extends StatelessWidget { padding: const EdgeInsets.all(10), child: Column( children: [ - if (user.isDashboardWidgetVisible('routines')) + if (user.isDashboardWidgetVisible(DashboardWidget.routines)) const DashboardRoutineWidget(), - if (user.isDashboardWidgetVisible('weight')) + if (user.isDashboardWidgetVisible(DashboardWidget.weight)) const DashboardWeightWidget(), - if (user.isDashboardWidgetVisible('measurements')) + if (user.isDashboardWidgetVisible(DashboardWidget.measurements)) const DashboardMeasurementWidget(), - if (user.isDashboardWidgetVisible('calendar')) + if (user.isDashboardWidgetVisible(DashboardWidget.calendar)) const DashboardCalendarWidget(), - if (user.isDashboardWidgetVisible('nutrition')) + if (user.isDashboardWidgetVisible(DashboardWidget.nutrition)) const DashboardNutritionWidget(), ], ), ), ); } -} \ No newline at end of file +} diff --git a/lib/screens/settings_dashboard_widgets_screen.dart b/lib/screens/settings_dashboard_widgets_screen.dart new file mode 100644 index 00000000..d3be7771 --- /dev/null +++ b/lib/screens/settings_dashboard_widgets_screen.dart @@ -0,0 +1,38 @@ +/* + * This file is part of wger Workout Manager . + * Copyright (c) 2026 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 . + */ + +import 'package:flutter/material.dart'; +import 'package:wger/core/wide_screen_wrapper.dart'; +import 'package:wger/l10n/generated/app_localizations.dart'; +import 'package:wger/widgets/core/settings/dashboard_visibility.dart'; + +class ConfigureDashboardWidgetsScreen extends StatelessWidget { + static const routeName = '/ConfigureDashboardWidgetScreen'; + + const ConfigureDashboardWidgetsScreen({super.key}); + + @override + Widget build(BuildContext context) { + final i18n = AppLocalizations.of(context); + + return Scaffold( + appBar: AppBar(title: Text(i18n.dashboardWidgets)), + body: const WidescreenWrapper(child: SettingsDashboardVisibility()), + ); + } +} diff --git a/lib/screens/configure_plates_screen.dart b/lib/screens/settings_plates_screen.dart similarity index 100% rename from lib/screens/configure_plates_screen.dart rename to lib/screens/settings_plates_screen.dart diff --git a/lib/widgets/core/app_bar.dart b/lib/widgets/core/app_bar.dart index cf0948d5..be52f063 100644 --- a/lib/widgets/core/app_bar.dart +++ b/lib/widgets/core/app_bar.dart @@ -1,6 +1,6 @@ /* * This file is part of wger Workout Manager . - * Copyright (C) 2020, 2021 wger Team + * Copyright (c) 2026 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 @@ -26,6 +26,7 @@ import 'package:wger/providers/nutrition.dart'; import 'package:wger/providers/routines.dart'; import 'package:wger/providers/user.dart'; import 'package:wger/screens/form_screen.dart'; +import 'package:wger/screens/settings_dashboard_widgets_screen.dart'; import 'package:wger/widgets/core/about.dart'; import 'package:wger/widgets/core/settings.dart'; import 'package:wger/widgets/user/forms.dart'; @@ -40,71 +41,19 @@ class MainAppBar extends StatelessWidget implements PreferredSizeWidget { return AppBar( title: Text(_title), actions: [ + IconButton( + icon: const Icon(Icons.widgets_outlined), + onPressed: () { + Navigator.of(context).pushNamed(ConfigureDashboardWidgetsScreen.routeName); + }, + ), IconButton( icon: const Icon(Icons.settings), onPressed: () async { return showDialog( context: context, builder: (BuildContext context) { - return AlertDialog( - title: Text(AppLocalizations.of(context).optionsLabel), - actions: [ - TextButton( - child: Text( - MaterialLocalizations.of(context).closeButtonLabel, - ), - onPressed: () => Navigator.of(context).pop(), - ), - ], - contentPadding: EdgeInsets.zero, - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ListTile( - //dense: true, - leading: const Icon(Icons.person), - title: Text(AppLocalizations.of(context).userProfile), - onTap: () => Navigator.pushNamed( - context, - FormScreen.routeName, - arguments: FormScreenArguments( - AppLocalizations.of(context).userProfile, - UserProfileForm( - context.read().profile!, - ), - ), - ), - ), - ListTile( - leading: const Icon(Icons.settings), - onTap: () => Navigator.of(context).pushNamed(SettingsPage.routeName), - title: Text(AppLocalizations.of(context).settingsTitle), - ), - ListTile( - leading: const Icon(Icons.info), - onTap: () => Navigator.of(context).pushNamed(AboutPage.routeName), - title: Text(AppLocalizations.of(context).aboutPageTitle), - ), - const Divider(), - ListTile( - //dense: true, - leading: const Icon(Icons.exit_to_app), - title: Text(AppLocalizations.of(context).logout), - onTap: () { - context.read().logout(); - context.read().clear(); - context.read().clear(); - context.read().clear(); - context.read().clear(); - context.read().clear(); - - Navigator.of(context).pop(); - Navigator.of(context).pushReplacementNamed('/'); - }, - ), - ], - ), - ); + return const MainSettingsDialog(); }, ); }, @@ -117,6 +66,73 @@ class MainAppBar extends StatelessWidget implements PreferredSizeWidget { Size get preferredSize => const Size.fromHeight(kToolbarHeight); } +class MainSettingsDialog extends StatelessWidget { + const MainSettingsDialog({super.key}); + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(AppLocalizations.of(context).optionsLabel), + actions: [ + TextButton( + child: Text( + MaterialLocalizations.of(context).closeButtonLabel, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ], + contentPadding: EdgeInsets.zero, + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + //dense: true, + leading: const Icon(Icons.person), + title: Text(AppLocalizations.of(context).userProfile), + onTap: () => Navigator.pushNamed( + context, + FormScreen.routeName, + arguments: FormScreenArguments( + AppLocalizations.of(context).userProfile, + UserProfileForm( + context.read().profile!, + ), + ), + ), + ), + ListTile( + leading: const Icon(Icons.settings), + onTap: () => Navigator.of(context).pushNamed(SettingsPage.routeName), + title: Text(AppLocalizations.of(context).settingsTitle), + ), + ListTile( + leading: const Icon(Icons.info), + onTap: () => Navigator.of(context).pushNamed(AboutPage.routeName), + title: Text(AppLocalizations.of(context).aboutPageTitle), + ), + const Divider(), + ListTile( + //dense: true, + leading: const Icon(Icons.exit_to_app), + title: Text(AppLocalizations.of(context).logout), + onTap: () { + context.read().logout(); + context.read().clear(); + context.read().clear(); + context.read().clear(); + context.read().clear(); + context.read().clear(); + + Navigator.of(context).pop(); + Navigator.of(context).pushReplacementNamed('/'); + }, + ), + ], + ), + ); + } +} + /// App bar that only displays a title class EmptyAppBar extends StatelessWidget implements PreferredSizeWidget { final String _title; diff --git a/lib/widgets/core/settings.dart b/lib/widgets/core/settings.dart index 336e13b8..8ddcf0ee 100644 --- a/lib/widgets/core/settings.dart +++ b/lib/widgets/core/settings.dart @@ -1,13 +1,13 @@ /* * This file is part of wger Workout Manager . - * Copyright (C) wger Team + * Copyright (c) 2026 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. * - * wger Workout Manager is distributed in the hope that it will be useful, + * 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. @@ -16,17 +16,14 @@ * along with this program. If not, see . */ -//import 'package:drift/drift.dart'; import 'package:flutter/material.dart'; -import 'package:wger/core/wide_screen_wrapper.dart'; import 'package:wger/l10n/generated/app_localizations.dart'; -import 'package:wger/screens/configure_plates_screen.dart'; -import 'package:wger/widgets/core/settings/exercise_cache.dart'; -import 'package:wger/widgets/core/settings/ingredient_cache.dart'; -import 'package:wger/widgets/core/settings/theme.dart'; -import 'package:provider/provider.dart'; -import 'package:wger/providers/user.dart'; +import 'package:wger/screens/settings_dashboard_widgets_screen.dart'; +import 'package:wger/screens/settings_plates_screen.dart'; +import './settings/exercise_cache.dart'; +import './settings/ingredient_cache.dart'; +import './settings/theme.dart'; class SettingsPage extends StatelessWidget { static String routeName = '/SettingsPage'; @@ -48,44 +45,6 @@ class SettingsPage extends StatelessWidget { const SettingsIngredientCache(), ListTile(title: Text(i18n.others, style: Theme.of(context).textTheme.headlineSmall)), const SettingsTheme(), - Consumer( - builder: (context, user, _) { - return Column( - children: [ - SwitchListTile( - title: const Text('Show routines on dashboard'), - value: user.isDashboardWidgetVisible('routines'), - onChanged: (v) => - user.setDashboardWidgetVisible('routines', v), - ), - SwitchListTile( - title: const Text('Show weight on dashboard'), - value: user.isDashboardWidgetVisible('weight'), - onChanged: (v) => - user.setDashboardWidgetVisible('weight', v), - ), - SwitchListTile( - title: const Text('Show measurements on dashboard'), - value: user.isDashboardWidgetVisible('measurements'), - onChanged: (v) => - user.setDashboardWidgetVisible('measurements', v), - ), - SwitchListTile( - title: const Text('Show calendar on dashboard'), - value: user.isDashboardWidgetVisible('calendar'), - onChanged: (v) => - user.setDashboardWidgetVisible('calendar', v), - ), - SwitchListTile( - title: const Text('Show nutrition on dashboard'), - value: user.isDashboardWidgetVisible('nutrition'), - onChanged: (v) => - user.setDashboardWidgetVisible('nutrition', v), - ), - ], - ); - }, - ), ListTile( title: Text(i18n.selectAvailablePlates), onTap: () { @@ -93,6 +52,13 @@ class SettingsPage extends StatelessWidget { }, trailing: const Icon(Icons.chevron_right), ), + ListTile( + title: Text(i18n.dashboardWidgets), + onTap: () { + Navigator.of(context).pushNamed(ConfigureDashboardWidgetsScreen.routeName); + }, + trailing: const Icon(Icons.chevron_right), + ), ], ), ); diff --git a/lib/widgets/core/settings/dashboard_visibility.dart b/lib/widgets/core/settings/dashboard_visibility.dart new file mode 100644 index 00000000..d00ead0b --- /dev/null +++ b/lib/widgets/core/settings/dashboard_visibility.dart @@ -0,0 +1,65 @@ +/* + * This file is part of wger Workout Manager . + * Copyright (c) 2026 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 . + */ + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:wger/l10n/generated/app_localizations.dart'; +import 'package:wger/providers/user.dart'; + +class SettingsDashboardVisibility extends StatelessWidget { + const SettingsDashboardVisibility({super.key}); + + @override + Widget build(BuildContext context) { + final i18n = AppLocalizations.of(context); + + return Consumer( + builder: (context, user, _) { + return Column( + children: [ + SwitchListTile( + title: Text(i18n.routines), + value: user.isDashboardWidgetVisible(DashboardWidget.routines), + onChanged: (v) => user.setDashboardWidgetVisible(DashboardWidget.routines, v), + ), + SwitchListTile( + title: Text(i18n.weight), + value: user.isDashboardWidgetVisible(DashboardWidget.weight), + onChanged: (v) => user.setDashboardWidgetVisible(DashboardWidget.weight, v), + ), + SwitchListTile( + title: Text(i18n.measurements), + value: user.isDashboardWidgetVisible(DashboardWidget.measurements), + onChanged: (v) => user.setDashboardWidgetVisible(DashboardWidget.measurements, v), + ), + SwitchListTile( + title: Text(i18n.calendar), + value: user.isDashboardWidgetVisible(DashboardWidget.calendar), + onChanged: (v) => user.setDashboardWidgetVisible(DashboardWidget.calendar, v), + ), + SwitchListTile( + title: Text(i18n.nutritionalPlans), + value: user.isDashboardWidgetVisible(DashboardWidget.nutrition), + onChanged: (v) => user.setDashboardWidgetVisible(DashboardWidget.nutrition, v), + ), + ], + ); + }, + ); + } +} diff --git a/lib/widgets/routines/gym_mode/log_page.dart b/lib/widgets/routines/gym_mode/log_page.dart index 088836d6..49865e7e 100644 --- a/lib/widgets/routines/gym_mode/log_page.dart +++ b/lib/widgets/routines/gym_mode/log_page.dart @@ -31,7 +31,7 @@ import 'package:wger/providers/gym_log_state.dart'; import 'package:wger/providers/gym_state.dart'; import 'package:wger/providers/plate_weights.dart'; import 'package:wger/providers/routines.dart'; -import 'package:wger/screens/configure_plates_screen.dart'; +import 'package:wger/screens/settings_plates_screen.dart'; import 'package:wger/widgets/core/core.dart'; import 'package:wger/widgets/core/progress_indicator.dart'; import 'package:wger/widgets/routines/forms/reps_unit.dart'; diff --git a/test/core/settings_test.dart b/test/core/settings_test.dart index b2934682..bb27464b 100644 --- a/test/core/settings_test.dart +++ b/test/core/settings_test.dart @@ -1,13 +1,13 @@ /* * This file is part of wger Workout Manager . - * Copyright (C) 2020, 2021 wger Team + * Copyright (c) 2026 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. * - * wger Workout Manager is distributed in the hope that it will be useful, + * 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. @@ -49,13 +49,9 @@ void main() { setUp(() { when(mockUserProvider.themeMode).thenReturn(ThemeMode.system); + when(mockUserProvider.isDashboardWidgetVisible(any)).thenReturn(true); when(mockExerciseProvider.exercises).thenReturn(getTestExercises()); when(mockNutritionProvider.ingredients).thenReturn([ingredient1, ingredient2]); - when(mockUserProvider.isDashboardWidgetVisible('routines')).thenReturn(true); - when(mockUserProvider.isDashboardWidgetVisible('weight')).thenReturn(true); - when(mockUserProvider.isDashboardWidgetVisible('measurements')).thenReturn(true); - when(mockUserProvider.isDashboardWidgetVisible('calendar')).thenReturn(true); - when(mockUserProvider.isDashboardWidgetVisible('nutrition')).thenReturn(true); }); Widget createSettingsScreen({locale = 'en'}) { @@ -105,24 +101,27 @@ void main() { group('Theme settings', () { test('Default theme is system', () async { when(mockSharedPreferences.getBool(PREFS_USER_DARK_THEME)).thenAnswer((_) async => null); - when(mockSharedPreferences.getString('dashboardWidgetVisibility')) - .thenAnswer((_) async => null); + when( + mockSharedPreferences.getString('dashboardWidgetVisibility'), + ).thenAnswer((_) async => null); final userProvider = await UserProvider(MockWgerBaseProvider(), prefs: mockSharedPreferences); expect(userProvider.themeMode, ThemeMode.system); }); test('Loads light theme', () async { when(mockSharedPreferences.getBool(PREFS_USER_DARK_THEME)).thenAnswer((_) async => false); - when(mockSharedPreferences.getString('dashboardWidgetVisibility')) - .thenAnswer((_) async => null); + when( + mockSharedPreferences.getString('dashboardWidgetVisibility'), + ).thenAnswer((_) async => null); final userProvider = await UserProvider(MockWgerBaseProvider(), prefs: mockSharedPreferences); expect(userProvider.themeMode, ThemeMode.light); }); test('Saves theme to prefs', () { when(mockSharedPreferences.getBool(any)).thenAnswer((_) async => null); - when(mockSharedPreferences.getString('dashboardWidgetVisibility')) - .thenAnswer((_) async => null); + when( + mockSharedPreferences.getString('dashboardWidgetVisibility'), + ).thenAnswer((_) async => null); final userProvider = UserProvider(MockWgerBaseProvider(), prefs: mockSharedPreferences); userProvider.setThemeMode(ThemeMode.dark); verify(mockSharedPreferences.setBool(PREFS_USER_DARK_THEME, true)).called(1); diff --git a/test/core/settings_test.mocks.dart b/test/core/settings_test.mocks.dart index 4e060322..b7dc303f 100644 --- a/test/core/settings_test.mocks.dart +++ b/test/core/settings_test.mocks.dart @@ -943,6 +943,14 @@ class MockUserProvider extends _i1.Mock implements _i21.UserProvider { ) as _i14.SharedPreferencesAsync); + @override + Map<_i21.DashboardWidget, bool> get dashboardWidgetVisibility => + (super.noSuchMethod( + Invocation.getter(#dashboardWidgetVisibility), + returnValue: <_i21.DashboardWidget, bool>{}, + ) + as Map<_i21.DashboardWidget, bool>); + @override set themeMode(_i22.ThemeMode? value) => super.noSuchMethod( Invocation.setter(#themeMode, value), @@ -955,6 +963,12 @@ class MockUserProvider extends _i1.Mock implements _i21.UserProvider { returnValueForMissingStub: null, ); + @override + set dashboardWidgetVisibility(Map<_i21.DashboardWidget, bool>? value) => super.noSuchMethod( + Invocation.setter(#dashboardWidgetVisibility, value), + returnValueForMissingStub: null, + ); + @override set profile(_i23.Profile? value) => super.noSuchMethod( Invocation.setter(#profile, value), @@ -971,6 +985,26 @@ class MockUserProvider extends _i1.Mock implements _i21.UserProvider { returnValueForMissingStub: null, ); + @override + bool isDashboardWidgetVisible(_i21.DashboardWidget? key) => + (super.noSuchMethod( + Invocation.method(#isDashboardWidgetVisible, [key]), + returnValue: false, + ) + as bool); + + @override + _i18.Future setDashboardWidgetVisible( + _i21.DashboardWidget? key, + bool? visible, + ) => + (super.noSuchMethod( + Invocation.method(#setDashboardWidgetVisible, [key, visible]), + returnValue: _i18.Future.value(), + returnValueForMissingStub: _i18.Future.value(), + ) + as _i18.Future); + @override void setThemeMode(_i22.ThemeMode? mode) => super.noSuchMethod( Invocation.method(#setThemeMode, [mode]), diff --git a/test/exercises/contribute_exercise_test.mocks.dart b/test/exercises/contribute_exercise_test.mocks.dart index 726b8a14..c3defcf4 100644 --- a/test/exercises/contribute_exercise_test.mocks.dart +++ b/test/exercises/contribute_exercise_test.mocks.dart @@ -389,6 +389,14 @@ class MockUserProvider extends _i1.Mock implements _i17.UserProvider { ) as _i4.SharedPreferencesAsync); + @override + Map<_i17.DashboardWidget, bool> get dashboardWidgetVisibility => + (super.noSuchMethod( + Invocation.getter(#dashboardWidgetVisibility), + returnValue: <_i17.DashboardWidget, bool>{}, + ) + as Map<_i17.DashboardWidget, bool>); + @override set themeMode(_i18.ThemeMode? value) => super.noSuchMethod( Invocation.setter(#themeMode, value), @@ -401,6 +409,12 @@ class MockUserProvider extends _i1.Mock implements _i17.UserProvider { returnValueForMissingStub: null, ); + @override + set dashboardWidgetVisibility(Map<_i17.DashboardWidget, bool>? value) => super.noSuchMethod( + Invocation.setter(#dashboardWidgetVisibility, value), + returnValueForMissingStub: null, + ); + @override set profile(_i19.Profile? value) => super.noSuchMethod( Invocation.setter(#profile, value), @@ -417,6 +431,26 @@ class MockUserProvider extends _i1.Mock implements _i17.UserProvider { returnValueForMissingStub: null, ); + @override + bool isDashboardWidgetVisible(_i17.DashboardWidget? key) => + (super.noSuchMethod( + Invocation.method(#isDashboardWidgetVisible, [key]), + returnValue: false, + ) + as bool); + + @override + _i15.Future setDashboardWidgetVisible( + _i17.DashboardWidget? key, + bool? visible, + ) => + (super.noSuchMethod( + Invocation.method(#setDashboardWidgetVisible, [key, visible]), + returnValue: _i15.Future.value(), + returnValueForMissingStub: _i15.Future.value(), + ) + as _i15.Future); + @override void setThemeMode(_i18.ThemeMode? mode) => super.noSuchMethod( Invocation.method(#setThemeMode, [mode]), diff --git a/test/weight/weight_screen_test.mocks.dart b/test/weight/weight_screen_test.mocks.dart index 8f508d55..eac9ecd4 100644 --- a/test/weight/weight_screen_test.mocks.dart +++ b/test/weight/weight_screen_test.mocks.dart @@ -231,6 +231,14 @@ class MockUserProvider extends _i1.Mock implements _i13.UserProvider { ) as _i4.SharedPreferencesAsync); + @override + Map<_i13.DashboardWidget, bool> get dashboardWidgetVisibility => + (super.noSuchMethod( + Invocation.getter(#dashboardWidgetVisibility), + returnValue: <_i13.DashboardWidget, bool>{}, + ) + as Map<_i13.DashboardWidget, bool>); + @override set themeMode(_i14.ThemeMode? value) => super.noSuchMethod( Invocation.setter(#themeMode, value), @@ -243,6 +251,12 @@ class MockUserProvider extends _i1.Mock implements _i13.UserProvider { returnValueForMissingStub: null, ); + @override + set dashboardWidgetVisibility(Map<_i13.DashboardWidget, bool>? value) => super.noSuchMethod( + Invocation.setter(#dashboardWidgetVisibility, value), + returnValueForMissingStub: null, + ); + @override set profile(_i15.Profile? value) => super.noSuchMethod( Invocation.setter(#profile, value), @@ -259,6 +273,26 @@ class MockUserProvider extends _i1.Mock implements _i13.UserProvider { returnValueForMissingStub: null, ); + @override + bool isDashboardWidgetVisible(_i13.DashboardWidget? key) => + (super.noSuchMethod( + Invocation.method(#isDashboardWidgetVisible, [key]), + returnValue: false, + ) + as bool); + + @override + _i11.Future setDashboardWidgetVisible( + _i13.DashboardWidget? key, + bool? visible, + ) => + (super.noSuchMethod( + Invocation.method(#setDashboardWidgetVisible, [key, visible]), + returnValue: _i11.Future.value(), + returnValueForMissingStub: _i11.Future.value(), + ) + as _i11.Future); + @override void setThemeMode(_i14.ThemeMode? mode) => super.noSuchMethod( Invocation.method(#setThemeMode, [mode]),