diff --git a/lib/providers/user.dart b/lib/providers/user.dart index 5e4004e7..07bb6f21 100644 --- a/lib/providers/user.dart +++ b/lib/providers/user.dart @@ -100,7 +100,11 @@ class UserProvider with ChangeNotifier { .map((w) => DashboardItem(w)) .toList(); - List get dashboardOrder => _dashboardItems.map((e) => e.widget).toList(); + /// List of visible dashboard widgets in the configured order + List get dashboardWidgets => + _dashboardItems.where((w) => w.isVisible).map((w) => w.widget).toList(); + + List get allDashboardWidgets => _dashboardItems.map((w) => w.widget).toList(); Future _loadDashboardConfig() async { final jsonString = await prefs.getString(PREFS_DASHBOARD_CONFIG); diff --git a/lib/screens/dashboard.dart b/lib/screens/dashboard.dart index 51319722..56a8e5b9 100644 --- a/lib/screens/dashboard.dart +++ b/lib/screens/dashboard.dart @@ -49,13 +49,6 @@ class DashboardScreen extends StatelessWidget { case DashboardWidget.trophies: return const DashboardTrophiesWidget(); } - /* - child: Column( - children: user.dashboardOrder - .where((w) => user.isDashboardWidgetVisible(w)) - .map(_getDashboardWidget) - .toList(), - */ } @override @@ -83,14 +76,16 @@ class DashboardScreen extends StatelessWidget { child: isMobile ? ListView.builder( padding: const EdgeInsets.all(10), - itemBuilder: (context, index) => _getDashboardWidget(user.dashboardOrder[index]), - itemCount: user.dashboardOrder.length, + itemBuilder: (context, index) => + _getDashboardWidget(user.dashboardWidgets[index]), + itemCount: user.dashboardWidgets.length, ) : GridView.builder( padding: const EdgeInsets.all(10), - itemBuilder: (context, index) => - SingleChildScrollView(child: _getDashboardWidget(user.dashboardOrder[index])), - itemCount: user.dashboardOrder.length, + itemBuilder: (context, index) => SingleChildScrollView( + child: _getDashboardWidget(user.dashboardWidgets[index]), + ), + itemCount: user.dashboardWidgets.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: crossAxisCount, childAspectRatio: 0.7, diff --git a/lib/widgets/core/settings/dashboard_visibility.dart b/lib/widgets/core/settings/dashboard_visibility.dart index a86b8d5f..23d0c66d 100644 --- a/lib/widgets/core/settings/dashboard_visibility.dart +++ b/lib/widgets/core/settings/dashboard_visibility.dart @@ -51,7 +51,7 @@ class SettingsDashboardVisibility extends StatelessWidget { physics: const NeverScrollableScrollPhysics(), buildDefaultDragHandles: false, onReorder: user.setDashboardOrder, - children: user.dashboardOrder.asMap().entries.map((entry) { + children: user.allDashboardWidgets.asMap().entries.map((entry) { final index = entry.key; final w = entry.value; diff --git a/test/core/settings_dashboard_visibility_test.dart b/test/core/settings_dashboard_visibility_test.dart index 1aedab97..2da4e4ca 100644 --- a/test/core/settings_dashboard_visibility_test.dart +++ b/test/core/settings_dashboard_visibility_test.dart @@ -20,6 +20,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart'; import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart'; import 'package:wger/l10n/generated/app_localizations.dart'; @@ -37,7 +38,7 @@ void main() { setUp(() { SharedPreferencesAsyncPlatform.instance = InMemorySharedPreferencesAsync.empty(); mockBaseProvider = MockWgerBaseProvider(); - userProvider = UserProvider(mockBaseProvider); + userProvider = UserProvider(mockBaseProvider, prefs: SharedPreferencesAsync()); }); Widget createWidget() { @@ -78,7 +79,7 @@ void main() { // Tap to toggle await tester.tap(iconBtn); - await tester.pump(); // re-render + await tester.pump(); // Check provider state expect(userProvider.isDashboardWidgetVisible(DashboardWidget.routines), false); @@ -96,8 +97,9 @@ void main() { await tester.pumpAndSettle(); // Initial order: trophies, routines, nutrition, weight... - expect(userProvider.dashboardOrder[0], DashboardWidget.trophies); - expect(userProvider.dashboardOrder[1], DashboardWidget.routines); + expect(userProvider.dashboardWidgets[0], DashboardWidget.trophies); + expect(userProvider.dashboardWidgets[1], DashboardWidget.routines); + expect(userProvider.dashboardWidgets[2], DashboardWidget.nutrition); // Find drag handle for Trophies (index 0) final handleFinder = find.byIcon(Icons.drag_handle); @@ -110,8 +112,8 @@ void main() { // Verify order changed // 100px drag seems to skip 2 items (trophies moves to index 2) // [routines, nutrition, trophies, ...] - expect(userProvider.dashboardOrder[0], DashboardWidget.routines); - expect(userProvider.dashboardOrder[1], DashboardWidget.nutrition); - expect(userProvider.dashboardOrder[2], DashboardWidget.trophies); + expect(userProvider.dashboardWidgets[0], DashboardWidget.routines); + expect(userProvider.dashboardWidgets[1], DashboardWidget.nutrition); + expect(userProvider.dashboardWidgets[2], DashboardWidget.trophies); }); } diff --git a/test/core/settings_test.mocks.dart b/test/core/settings_test.mocks.dart index 0c0b6b32..19b552e4 100644 --- a/test/core/settings_test.mocks.dart +++ b/test/core/settings_test.mocks.dart @@ -1,3 +1,21 @@ +/* + * 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 . + */ + // Mocks generated by Mockito 5.4.6 from annotations // in wger/test/core/settings_test.dart. // Do not manually edit this file. @@ -944,7 +962,7 @@ class MockUserProvider extends _i1.Mock implements _i21.UserProvider { as _i14.SharedPreferencesAsync); @override - List<_i21.DashboardWidget> get dashboardOrder => + List<_i21.DashboardWidget> get dashboardWidgets => (super.noSuchMethod( Invocation.getter(#dashboardOrder), returnValue: <_i21.DashboardWidget>[], diff --git a/test/exercises/contribute_exercise_test.mocks.dart b/test/exercises/contribute_exercise_test.mocks.dart index dd9f98e8..e57f7393 100644 --- a/test/exercises/contribute_exercise_test.mocks.dart +++ b/test/exercises/contribute_exercise_test.mocks.dart @@ -1,3 +1,21 @@ +/* + * 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 . + */ + // Mocks generated by Mockito 5.4.6 from annotations // in wger/test/exercises/contribute_exercise_test.dart. // Do not manually edit this file. @@ -390,7 +408,7 @@ class MockUserProvider extends _i1.Mock implements _i17.UserProvider { as _i4.SharedPreferencesAsync); @override - List<_i17.DashboardWidget> get dashboardOrder => + List<_i17.DashboardWidget> get dashboardWidgets => (super.noSuchMethod( Invocation.getter(#dashboardOrder), returnValue: <_i17.DashboardWidget>[], diff --git a/test/user/provider_test.dart b/test/user/provider_test.dart index c5a9206e..fdb9b1f0 100644 --- a/test/user/provider_test.dart +++ b/test/user/provider_test.dart @@ -54,7 +54,7 @@ void main() { setUp(() { SharedPreferencesAsyncPlatform.instance = InMemorySharedPreferencesAsync.empty(); mockWgerBaseProvider = MockWgerBaseProvider(); - userProvider = UserProvider(mockWgerBaseProvider); + userProvider = UserProvider(mockWgerBaseProvider, prefs: SharedPreferencesAsync()); when(mockWgerBaseProvider.makeUrl(any)).thenReturn(tProfileUri); when( @@ -106,10 +106,10 @@ void main() { group('dashboard config', () { test('initial config should be default (all visible, default order)', () { - expect(userProvider.dashboardOrder.length, 6); + expect(userProvider.dashboardWidgets.length, 6); expect( - userProvider.dashboardOrder, + userProvider.allDashboardWidgets, orderedEquals([ DashboardWidget.trophies, DashboardWidget.routines, @@ -136,16 +136,16 @@ void main() { test('reordering should update order', () async { // arrange - final initialFirst = userProvider.dashboardOrder[0]; - final initialSecond = userProvider.dashboardOrder[1]; + final initialFirst = userProvider.dashboardWidgets[0]; + final initialSecond = userProvider.dashboardWidgets[1]; // act: move first to second position // oldIndex: 0, newIndex: 2 (because insert is before index) await userProvider.setDashboardOrder(0, 2); // assert - expect(userProvider.dashboardOrder[0], initialSecond); - expect(userProvider.dashboardOrder[1], initialFirst); + expect(userProvider.dashboardWidgets[0], initialSecond); + expect(userProvider.dashboardWidgets[1], initialFirst); }); test('should load config from prefs', () async { @@ -169,21 +169,18 @@ void main() { // Missing: trophies (0), weight (3), measurements (4), calendar (5) // 1. trophies (index 0) inserted at 0 -> [trophies, nutrition, routines] // 2. weight (index 3) inserted at 3 -> [trophies, nutrition, routines, weight] - - expect(newProvider.dashboardOrder[0], DashboardWidget.trophies); - expect(newProvider.dashboardOrder[1], DashboardWidget.nutrition); - expect(newProvider.dashboardOrder[2], DashboardWidget.routines); - expect(newProvider.dashboardOrder[3], DashboardWidget.weight); + expect(newProvider.allDashboardWidgets[0], DashboardWidget.trophies); + expect(newProvider.allDashboardWidgets[1], DashboardWidget.nutrition); + expect(newProvider.allDashboardWidgets[2], DashboardWidget.routines); + expect(newProvider.allDashboardWidgets[3], DashboardWidget.weight); // Check visibility expect(newProvider.isDashboardWidgetVisible(DashboardWidget.nutrition), true); expect(newProvider.isDashboardWidgetVisible(DashboardWidget.routines), false); // Missing items should be visible by default - expect( - newProvider.isDashboardWidgetVisible(DashboardWidget.weight), - true, - ); + expect(newProvider.isDashboardWidgetVisible(DashboardWidget.weight), true); + expect(newProvider.isDashboardWidgetVisible(DashboardWidget.trophies), true); }); }); } diff --git a/test/weight/weight_screen_test.mocks.dart b/test/weight/weight_screen_test.mocks.dart index ae2d83ee..57035131 100644 --- a/test/weight/weight_screen_test.mocks.dart +++ b/test/weight/weight_screen_test.mocks.dart @@ -1,3 +1,21 @@ +/* + * 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 . + */ + // Mocks generated by Mockito 5.4.6 from annotations // in wger/test/weight/weight_screen_test.dart. // Do not manually edit this file. @@ -232,7 +250,7 @@ class MockUserProvider extends _i1.Mock implements _i13.UserProvider { as _i4.SharedPreferencesAsync); @override - List<_i13.DashboardWidget> get dashboardOrder => + List<_i13.DashboardWidget> get dashboardWidgets => (super.noSuchMethod( Invocation.getter(#dashboardOrder), returnValue: <_i13.DashboardWidget>[],