diff --git a/AUTHORS.md b/AUTHORS.md
index e8e7ac60..d886c6d7 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -32,6 +32,7 @@
- sizzlesloth -
- Arya Singh -
- Xianglin Zeng -
+- Sangharsh Sulke -
## Translators
diff --git a/Gemfile b/Gemfile
index 2ccf2ecb..73fd0e0c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,5 +1,9 @@
source "https://rubygems.org"
gem "fastlane"
+gem 'logger'
+gem 'mutex_m'
+gem 'abbrev'
+
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)
diff --git a/Gemfile.lock b/Gemfile.lock
index 3b1f941c..f8cc1530 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -5,25 +5,26 @@ GEM
base64
nkf
rexml
+ abbrev (0.1.2)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.3.0)
- aws-partitions (1.1003.0)
- aws-sdk-core (3.212.0)
+ aws-partitions (1.1042.0)
+ aws-sdk-core (3.216.1)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
jmespath (~> 1, >= 1.6.1)
- aws-sdk-kms (1.95.0)
- aws-sdk-core (~> 3, >= 3.210.0)
+ aws-sdk-kms (1.97.0)
+ aws-sdk-core (~> 3, >= 3.216.0)
aws-sigv4 (~> 1.5)
- aws-sdk-s3 (1.170.0)
- aws-sdk-core (~> 3, >= 3.210.0)
+ aws-sdk-s3 (1.178.0)
+ aws-sdk-core (~> 3, >= 3.216.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
- aws-sigv4 (1.10.1)
+ aws-sigv4 (1.11.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
base64 (0.2.0)
@@ -58,8 +59,8 @@ GEM
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
- faraday-multipart (1.0.4)
- multipart-post (~> 2)
+ faraday-multipart (1.1.0)
+ multipart-post (~> 2.0)
faraday-net_http (1.0.2)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
@@ -67,8 +68,8 @@ GEM
faraday-retry (1.0.3)
faraday_middleware (1.2.1)
faraday (~> 1.0)
- fastimage (2.3.1)
- fastlane (2.225.0)
+ fastimage (2.4.0)
+ fastlane (2.226.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
@@ -108,7 +109,7 @@ GEM
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
- xcpretty (~> 0.3.0)
+ xcpretty (~> 0.4.0)
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
fastlane-plugin-versioning (0.7.0)
fastlane-sirp (1.0.0)
@@ -151,23 +152,25 @@ GEM
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
- http-cookie (1.0.7)
+ http-cookie (1.0.8)
domain_name (~> 0.5)
httpclient (2.8.3)
jmespath (1.6.2)
- json (2.8.1)
- jwt (2.9.3)
+ json (2.9.1)
+ jwt (2.10.1)
base64
+ logger (1.6.5)
mini_magick (4.13.2)
mini_mime (1.1.5)
multi_json (1.15.0)
multipart-post (2.4.1)
+ mutex_m (0.3.0)
nanaimo (0.4.0)
naturally (2.2.1)
nkf (0.2.0)
optparse (0.6.0)
os (1.1.4)
- plist (3.7.1)
+ plist (3.7.2)
public_suffix (6.0.1)
rake (13.2.1)
representable (3.2.0)
@@ -175,10 +178,10 @@ GEM
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
- rexml (3.3.9)
- rouge (2.0.7)
+ rexml (3.4.0)
+ rouge (3.28.0)
ruby2_keywords (0.0.5)
- rubyzip (2.3.2)
+ rubyzip (2.4.1)
security (0.1.5)
signet (0.19.0)
addressable (~> 2.8)
@@ -207,8 +210,8 @@ GEM
colored2 (~> 3.1)
nanaimo (~> 0.4.0)
rexml (>= 3.3.6, < 4.0)
- xcpretty (0.3.0)
- rouge (~> 2.0.7)
+ xcpretty (0.4.0)
+ rouge (~> 3.28.0)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
@@ -216,11 +219,15 @@ PLATFORMS
arm64-darwin-21
arm64-darwin-22
arm64-darwin-23
+ arm64-darwin-24
x86_64-linux
DEPENDENCIES
+ abbrev
fastlane
fastlane-plugin-versioning
+ logger
+ mutex_m
BUNDLED WITH
- 2.2.32
+ 2.6.3
diff --git a/fastlane/metadata/android/uk/video.txt b/fastlane/metadata/android/uk/video.txt
index e69de29b..8b137891 100644
--- a/fastlane/metadata/android/uk/video.txt
+++ b/fastlane/metadata/android/uk/video.txt
@@ -0,0 +1 @@
+
diff --git a/flatpak/de.wger.flutter.metainfo.xml b/flatpak/de.wger.flutter.metainfo.xml
index 2ae67f65..fbcca043 100755
--- a/flatpak/de.wger.flutter.metainfo.xml
+++ b/flatpak/de.wger.flutter.metainfo.xml
@@ -8,32 +8,26 @@
fitness goals.
+ Workout Management
- -
- Workout Management
-
- - Create and customize workout routines tailored to your fitness level and
- goals
-
- - Track your progress with detailed exercise logs
- - Access a vast library of exercises
-
-
- -
- Nutrition Tracking
-
- - Log your food intake using the Open Food Facts database
- - Calculate your calorie intake and macronutrient breakdown
- - Set personalized dietary goals and track your progress
-
-
- -
- Body Measurement Tracking
-
- - Monitor your body weight, body fat percentage, and other measurements
- - Visualize your progress with charts and graphs
-
+ - Create and customize workout routines tailored to your fitness level and
+ goals
+ - Track your progress with detailed exercise logs
+ - Access a vast library of exercises
+
+
+ Nutrition Tracking
+
+ - Log your food intake using the Open Food Facts database
+ - Calculate your calorie intake and macronutrient breakdown
+ - Set personalized dietary goals and track your progress
+
+
+ Body Measurement Tracking
+
+ - Monitor your body weight, body fat percentage, and other measurements
+ - Visualize your progress with charts and graphs
diff --git a/lib/helpers/consts.dart b/lib/helpers/consts.dart
index 1d255751..db66b4f8 100644
--- a/lib/helpers/consts.dart
+++ b/lib/helpers/consts.dart
@@ -62,6 +62,7 @@ const PREFS_LAST_UPDATED_LANGUAGES = 'lastUpdatedLanguages';
const PREFS_INGREDIENTS = 'ingredientData';
const PREFS_WORKOUT_UNITS = 'workoutUnits';
const PREFS_USER = 'userData';
+const PREFS_USER_DARK_THEME = 'userDarkMode';
const PREFS_LAST_SERVER = 'lastServer';
const DEFAULT_ANIMATION_DURATION = Duration(milliseconds: 200);
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index cd52c000..fde38997 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -925,5 +925,9 @@
"indicatorAvg": "avg",
"@indicatorAvg": {
"description": "added for localization of Class Indicator's field text"
- }
+ },
+ "themeMode": "Theme mode",
+ "darkMode": "Always dark mode",
+ "lightMode": "Always light mode",
+ "systemMode": "System settings"
}
diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/lib/l10n/app_nl.arb
@@ -0,0 +1 @@
+{}
diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb
index 6888e85f..811f59ad 100644
--- a/lib/l10n/app_pt.arb
+++ b/lib/l10n/app_pt.arb
@@ -161,7 +161,7 @@
"@planned": {
"description": "Header for the column of 'planned' nutritional values, i.e. what should be eaten"
},
- "weekAverage": "média dos 7 dias",
+ "weekAverage": "Média dos 7 dias",
"@weekAverage": {
"description": "Header for the column of '7 day average' nutritional values, i.e. what was logged last week"
},
@@ -775,5 +775,90 @@
"aboutDonateTitle": "Doar",
"@aboutDonateTitle": {},
"aboutDonateText": "Nos compre um café para ajudar o projeto, pagar os custos do servidor e nos manter energizados",
- "@aboutDonateText": {}
+ "@aboutDonateText": {},
+ "onlyLogging": "Só controlar calorias",
+ "@onlyLogging": {},
+ "goalEnergy": "Meta energética",
+ "@goalEnergy": {},
+ "goalProtein": "Meta proteica",
+ "@goalProtein": {},
+ "goalCarbohydrates": "Meta de carboidratos",
+ "@goalCarbohydrates": {},
+ "goalFat": "Meta de gordura",
+ "@goalFat": {},
+ "today": "Hoje",
+ "@today": {},
+ "kcalValue": "{value} kcal",
+ "@kcalValue": {
+ "description": "A value in kcal, e.g. 500 kcal",
+ "type": "text",
+ "placeholders": {
+ "value": {}
+ }
+ },
+ "gValue": "{value} g",
+ "@gValue": {
+ "description": "A value in grams, e.g. 5 g",
+ "type": "text",
+ "placeholders": {
+ "value": {}
+ }
+ },
+ "percentValue": "{value} %",
+ "@percentValue": {
+ "description": "A value in percent, e.g. 10 %",
+ "type": "text",
+ "placeholders": {
+ "value": {}
+ }
+ },
+ "noIngredientsDefined": "Sem ingredientes definido ainda",
+ "@noIngredientsDefined": {},
+ "ingredientLogged": "Ingrediente ativo registrado diariamente",
+ "@ingredientLogged": {},
+ "onlyLoggingHelpText": "Marque a caixa se você desejar apenas o seu registo de calorias e não quer a configuração de um detalhado plano nutricional com refeições",
+ "@onlyLoggingHelpText": {},
+ "goalMacro": "Macro objetivos",
+ "@goalMacro": {
+ "description": "The goal for macronutrients"
+ },
+ "selectMealToLog": "Selecione uma refeição para entrar no diário",
+ "@selectMealToLog": {},
+ "goalFiber": "Meta de fibra",
+ "@goalFiber": {},
+ "deficit": "Défice",
+ "@deficit": {
+ "description": "Caloric deficit (either planned or unplanned)"
+ },
+ "surplus": "Excedente",
+ "@surplus": {
+ "description": "Caloric surplus (either planned or unplanned)"
+ },
+ "chart30DaysTitle": "{name} Ultimos 30 dias",
+ "@chart30DaysTitle": {
+ "description": "last 30 days chart of 'name' (e.g. 'weight', 'body fat' etc.)",
+ "type": "text",
+ "placeholders": {
+ "name": {}
+ }
+ },
+ "chartDuringPlanTitle": "{chartName} Durante o plano nutricional {planName}",
+ "@chartDuringPlanTitle": {
+ "description": "chart of 'chartName' (e.g. 'weight', 'body fat' etc.) logged during plan",
+ "type": "text",
+ "placeholders": {
+ "chartName": {},
+ "planName": {}
+ }
+ },
+ "loggedToday": "Registrado hoje",
+ "@loggedToday": {},
+ "chartAllTimeTitle": "{name} de todo o tempo",
+ "@chartAllTimeTitle": {
+ "description": "All-time chart of 'name' (e.g. 'weight', 'body fat' etc.)",
+ "type": "text",
+ "placeholders": {
+ "name": {}
+ }
+ }
}
diff --git a/lib/l10n/app_pt_BR.arb b/lib/l10n/app_pt_BR.arb
index 60d6a0ea..25c9a66f 100644
--- a/lib/l10n/app_pt_BR.arb
+++ b/lib/l10n/app_pt_BR.arb
@@ -99,7 +99,7 @@
"@comment": {
"description": "Comment, additional information"
},
- "logIngredient": "Salvar no diário nutricional",
+ "logIngredient": "Salvar ingrediente no diário nutricional",
"@logIngredient": {},
"equipment": "Equipamento",
"@equipment": {
@@ -221,7 +221,7 @@
"@enterValue": {
"description": "Error message when the user hasn't entered a value on a required field"
},
- "logMeal": "Registrar esta refeição",
+ "logMeal": "Registrar refeição para diário de nutrição",
"@logMeal": {},
"newEntry": "Nova entrada",
"@newEntry": {
@@ -677,5 +677,274 @@
"ingredientLogged": "Ingrediente registrado no diário",
"@ingredientLogged": {},
"noIngredientsDefined": "Nenhum ingrediente definido ainda",
- "@noIngredientsDefined": {}
+ "@noIngredientsDefined": {},
+ "bench": "Banco",
+ "@bench": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "goalFiber": "Meta de fibras",
+ "@goalFiber": {},
+ "overallChangeWeight": "Mudança geral",
+ "@overallChangeWeight": {
+ "description": "Overall change in weight, added for localization"
+ },
+ "goalTypeMeals": "De refeições",
+ "@goalTypeMeals": {
+ "description": "added for localization of Class GoalType's filed meals"
+ },
+ "goalTypeBasic": "Básico",
+ "@goalTypeBasic": {
+ "description": "added for localization of Class GoalType's filed basic"
+ },
+ "goalTypeAdvanced": "Avançado",
+ "@goalTypeAdvanced": {
+ "description": "added for localization of Class GoalType's filed advanced"
+ },
+ "indicatorRaw": "bruto",
+ "@indicatorRaw": {
+ "description": "added for localization of Class Indicator's field text"
+ },
+ "indicatorAvg": "média",
+ "@indicatorAvg": {
+ "description": "added for localization of Class Indicator's field text"
+ },
+ "seconds": "Segundos",
+ "@seconds": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "textPromptTitle": "Pronto para iniciar?",
+ "@textPromptTitle": {},
+ "textPromptSubheading": "Aperte o botão de ação para começar",
+ "@textPromptSubheading": {},
+ "chest": "Peito",
+ "@chest": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "max_reps": "Repetições Máximas",
+ "@max_reps": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "pull_up_bar": "Barra de Pull-up",
+ "@pull_up_bar": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "quads": "Quadríceps",
+ "@quads": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "goalFat": "Meta de gordura",
+ "@goalFat": {},
+ "body_weight": "Peso Corporal",
+ "@body_weight": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "kilometers": "Quilômetros",
+ "@kilometers": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "kilometers_per_hour": "Quilômetros por hora",
+ "@kilometers_per_hour": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "miles_per_hour": "Milhas por hora",
+ "@miles_per_hour": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "minutes": "Minutos",
+ "@minutes": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "sz_bar": "Barra Curvada",
+ "@sz_bar": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "goalProtein": "Meta de proteína",
+ "@goalProtein": {},
+ "goalEnergy": "Meta energética",
+ "@goalEnergy": {},
+ "today": "Hoje",
+ "@today": {},
+ "arms": "Braços",
+ "@arms": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "calves": "Panturrilha",
+ "@calves": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "triceps": "Tríceps",
+ "@triceps": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "goalCarbohydrates": "Meta de carbohidratos",
+ "@goalCarbohydrates": {},
+ "onlyLoggingHelpText": "Marque a caixa se você apenas quiser registrar suas calorias e não quer configurar um plano nutricional detalhado com refeições específicas",
+ "@onlyLoggingHelpText": {},
+ "kcalValue": "{value} kcal",
+ "@kcalValue": {
+ "description": "A value in kcal, e.g. 500 kcal",
+ "type": "text",
+ "placeholders": {
+ "value": {}
+ }
+ },
+ "percentValue": "{value} %",
+ "@percentValue": {
+ "description": "A value in percent, e.g. 10 %",
+ "type": "text",
+ "placeholders": {
+ "value": {}
+ }
+ },
+ "goalMacro": "Macro Objetivos",
+ "@goalMacro": {
+ "description": "The goal for macronutrients"
+ },
+ "selectMealToLog": "Selecione uma refeição para registrar no diário",
+ "@selectMealToLog": {},
+ "loggedToday": "Registrado hoje",
+ "@loggedToday": {},
+ "surplus": "excedente",
+ "@surplus": {
+ "description": "Caloric surplus (either planned or unplanned)"
+ },
+ "deficit": "déficit",
+ "@deficit": {
+ "description": "Caloric deficit (either planned or unplanned)"
+ },
+ "gValue": "{value} g",
+ "@gValue": {
+ "description": "A value in grams, e.g. 5 g",
+ "type": "text",
+ "placeholders": {
+ "value": {}
+ }
+ },
+ "abs": "Abdômen",
+ "@abs": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "back": "Costas",
+ "@back": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "barbell": "Barra",
+ "@barbell": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "cardio": "Cardio",
+ "@cardio": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "dumbbell": "Haltere",
+ "@dumbbell": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "glutes": "Glúteos",
+ "@glutes": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "gym_mat": "Tapete",
+ "@gym_mat": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "hamstrings": "Tendões",
+ "@hamstrings": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "kettlebell": "Kettlebell",
+ "@kettlebell": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "lats": "Dorsal",
+ "@lats": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "legs": "Pernas",
+ "@legs": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "lower_back": "Lombar",
+ "@lower_back": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "plates": "Anilhas",
+ "@plates": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "repetitions": "Repetições",
+ "@repetitions": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "shoulders": "Ombros",
+ "@shoulders": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "until_failure": "Até a falha",
+ "@until_failure": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "kg": "kg",
+ "@kg": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "none__bodyweight_exercise_": "nenhum (exercício com peso corporal)",
+ "@none__bodyweight_exercise_": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "lb": "lb",
+ "@lb": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "chartAllTimeTitle": "{name} total",
+ "@chartAllTimeTitle": {
+ "description": "All-time chart of 'name' (e.g. 'weight', 'body fat' etc.)",
+ "type": "text",
+ "placeholders": {
+ "name": {}
+ }
+ },
+ "chart30DaysTitle": "{name} últimos 30 dias",
+ "@chart30DaysTitle": {
+ "description": "last 30 days chart of 'name' (e.g. 'weight', 'body fat' etc.)",
+ "type": "text",
+ "placeholders": {
+ "name": {}
+ }
+ },
+ "chartDuringPlanTitle": "{chartName} durante plano nutricional {planName}",
+ "@chartDuringPlanTitle": {
+ "description": "chart of 'chartName' (e.g. 'weight', 'body fat' etc.) logged during plan",
+ "type": "text",
+ "placeholders": {
+ "chartName": {},
+ "planName": {}
+ }
+ },
+ "settingsIngredientCacheDescription": "Cache de Ingredientes",
+ "@settingsIngredientCacheDescription": {},
+ "cacheWarning": "Devido ao cache pode demorar algum tempo até que mudanças estejam visíveis na aplicação.",
+ "@cacheWarning": {},
+ "swiss_ball": "Bola Suíça",
+ "@swiss_ball": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "log": "Registro",
+ "@log": {
+ "description": "Log a specific meal (imperative form)"
+ },
+ "done": "Feito",
+ "@done": {},
+ "incline_bench": "Banco inclinado",
+ "@incline_bench": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "miles": "Milhas",
+ "@miles": {
+ "description": "Generated entry for translation for server strings"
+ },
+ "biceps": "Bíceps",
+ "@biceps": {
+ "description": "Generated entry for translation for server strings"
+ }
}
diff --git a/lib/main.dart b/lib/main.dart
index 0f3968f1..eeccefa1 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -137,48 +137,50 @@ class MyApp extends StatelessWidget {
),
],
child: Consumer(
- builder: (ctx, auth, _) => MaterialApp(
- title: 'wger',
- theme: wgerLightTheme,
- darkTheme: wgerDarkTheme,
- highContrastTheme: wgerLightThemeHc,
- highContrastDarkTheme: wgerDarkThemeHc,
- themeMode: ThemeMode.system,
- home: auth.isAuth
- ? const HomeTabsScreen()
- : FutureBuilder(
- future: auth.tryAutoLogin(),
- builder: (ctx, authResultSnapshot) =>
- authResultSnapshot.connectionState == ConnectionState.waiting
- ? const SplashScreen()
- : const AuthScreen(),
- ),
- routes: {
- DashboardScreen.routeName: (ctx) => const DashboardScreen(),
- FormScreen.routeName: (ctx) => const FormScreen(),
- GalleryScreen.routeName: (ctx) => const GalleryScreen(),
- GymModeScreen.routeName: (ctx) => const GymModeScreen(),
- HomeTabsScreen.routeName: (ctx) => const HomeTabsScreen(),
- MeasurementCategoriesScreen.routeName: (ctx) => const MeasurementCategoriesScreen(),
- MeasurementEntriesScreen.routeName: (ctx) => const MeasurementEntriesScreen(),
- NutritionalPlansScreen.routeName: (ctx) => const NutritionalPlansScreen(),
- NutritionalDiaryScreen.routeName: (ctx) => const NutritionalDiaryScreen(),
- NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen(),
- LogMealsScreen.routeName: (ctx) => const LogMealsScreen(),
- LogMealScreen.routeName: (ctx) => const LogMealScreen(),
- WeightScreen.routeName: (ctx) => const WeightScreen(),
- RoutineScreen.routeName: (ctx) => const RoutineScreen(),
- RoutineEditScreen.routeName: (ctx) => const RoutineEditScreen(),
- WorkoutLogsScreen.routeName: (ctx) => const WorkoutLogsScreen(),
- RoutineListScreen.routeName: (ctx) => const RoutineListScreen(),
- ExercisesScreen.routeName: (ctx) => const ExercisesScreen(),
- ExerciseDetailScreen.routeName: (ctx) => const ExerciseDetailScreen(),
- AddExerciseScreen.routeName: (ctx) => const AddExerciseScreen(),
- AboutPage.routeName: (ctx) => const AboutPage(),
- SettingsPage.routeName: (ctx) => const SettingsPage(),
- },
- localizationsDelegates: AppLocalizations.localizationsDelegates,
- supportedLocales: AppLocalizations.supportedLocales,
+ builder: (ctx, auth, _) => Consumer(
+ builder: (ctx, user, _) => MaterialApp(
+ title: 'wger',
+ theme: wgerLightTheme,
+ darkTheme: wgerDarkTheme,
+ highContrastTheme: wgerLightThemeHc,
+ highContrastDarkTheme: wgerDarkThemeHc,
+ themeMode: user.themeMode,
+ home: auth.isAuth
+ ? const HomeTabsScreen()
+ : FutureBuilder(
+ future: auth.tryAutoLogin(),
+ builder: (ctx, authResultSnapshot) =>
+ authResultSnapshot.connectionState == ConnectionState.waiting
+ ? const SplashScreen()
+ : const AuthScreen(),
+ ),
+ routes: {
+ DashboardScreen.routeName: (ctx) => const DashboardScreen(),
+ FormScreen.routeName: (ctx) => const FormScreen(),
+ GalleryScreen.routeName: (ctx) => const GalleryScreen(),
+ GymModeScreen.routeName: (ctx) => const GymModeScreen(),
+ HomeTabsScreen.routeName: (ctx) => const HomeTabsScreen(),
+ MeasurementCategoriesScreen.routeName: (ctx) => const MeasurementCategoriesScreen(),
+ MeasurementEntriesScreen.routeName: (ctx) => const MeasurementEntriesScreen(),
+ NutritionalPlansScreen.routeName: (ctx) => const NutritionalPlansScreen(),
+ NutritionalDiaryScreen.routeName: (ctx) => const NutritionalDiaryScreen(),
+ NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen(),
+ LogMealsScreen.routeName: (ctx) => const LogMealsScreen(),
+ LogMealScreen.routeName: (ctx) => const LogMealScreen(),
+ WeightScreen.routeName: (ctx) => const WeightScreen(),
+ RoutineScreen.routeName: (ctx) => const RoutineScreen(),
+ RoutineEditScreen.routeName: (ctx) => const RoutineEditScreen(),
+ WorkoutLogsScreen.routeName: (ctx) => const WorkoutLogsScreen(),
+ RoutineListScreen.routeName: (ctx) => const RoutineListScreen(),
+ ExercisesScreen.routeName: (ctx) => const ExercisesScreen(),
+ ExerciseDetailScreen.routeName: (ctx) => const ExerciseDetailScreen(),
+ AddExerciseScreen.routeName: (ctx) => const AddExerciseScreen(),
+ AboutPage.routeName: (ctx) => const AboutPage(),
+ SettingsPage.routeName: (ctx) => const SettingsPage(),
+ },
+ localizationsDelegates: AppLocalizations.localizationsDelegates,
+ supportedLocales: AppLocalizations.supportedLocales,
+ ),
),
),
);
diff --git a/lib/models/exercises/exercise.dart b/lib/models/exercises/exercise.dart
index 69bd82e4..e642dd15 100644
--- a/lib/models/exercises/exercise.dart
+++ b/lib/models/exercises/exercise.dart
@@ -15,6 +15,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
+import 'dart:developer';
import 'package:collection/collection.dart';
import 'package:equatable/equatable.dart';
@@ -161,7 +162,15 @@ class Exercise extends Equatable {
equipment = baseData.equipment;
category = baseData.category;
translations = baseData.translations.map((e) {
- e.language = languages.firstWhere((l) => l.id == e.languageId);
+ e.language = languages.firstWhere(
+ (l) => l.id == e.languageId,
+
+ // workaround for https://github.com/wger-project/flutter/issues/722
+ orElse: () {
+ log('Could not find language for translation ${e.languageId}');
+ return Language(id: e.languageId, shortName: 'unknown', fullName: 'unknown');
+ },
+ );
return e;
}).toList();
videos = baseData.videos;
diff --git a/lib/providers/auth.dart b/lib/providers/auth.dart
index 1bfbdca1..6e914e81 100644
--- a/lib/providers/auth.dart
+++ b/lib/providers/auth.dart
@@ -22,6 +22,7 @@ import 'dart:developer';
import 'dart:io';
import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:http/http.dart' as http;
import 'package:package_info_plus/package_info_plus.dart';
diff --git a/lib/providers/exercises.dart b/lib/providers/exercises.dart
index 8f43ec34..2956890f 100644
--- a/lib/providers/exercises.dart
+++ b/lib/providers/exercises.dart
@@ -298,20 +298,16 @@ class ExercisesProvider with ChangeNotifier {
Exercise exercise;
// TODO: this should be a .getSingleOrNull()!!! However, for some reason there
- // are duplicates in the db. Perhaps a race condition so that two
+ // can be duplicates in the db. Perhaps a race condition so that two
// entries are written at the same time or something?
final exerciseResult =
await (database.select(database.exercises)..where((e) => e.id.equals(exerciseId))).get();
ExerciseTable? exerciseDb;
- if (exerciseResult.length > 0) {
+ if (exerciseResult.isNotEmpty) {
exerciseDb = exerciseResult.first;
- } else {
- exerciseDb = null;
}
- log(exerciseResult.toString());
-
// Exercise is already known locally
if (exerciseDb != null) {
final nextFetch = exerciseDb.lastFetched.add(const Duration(hours: EXERCISE_FETCH_HOURS));
diff --git a/lib/providers/user.dart b/lib/providers/user.dart
index cb547c49..8e6c4456 100644
--- a/lib/providers/user.dart
+++ b/lib/providers/user.dart
@@ -19,12 +19,20 @@
import 'dart:async';
import 'package:flutter/material.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+import 'package:wger/helpers/consts.dart';
import 'package:wger/models/user/profile.dart';
import 'package:wger/providers/base_provider.dart';
class UserProvider with ChangeNotifier {
+ ThemeMode themeMode = ThemeMode.system;
final WgerBaseProvider baseProvider;
- UserProvider(this.baseProvider);
+ late SharedPreferencesAsync prefs;
+
+ UserProvider(this.baseProvider, {SharedPreferencesAsync? prefs}) {
+ this.prefs = prefs ?? SharedPreferencesAsync();
+ _loadThemeMode();
+ }
static const PROFILE_URL = 'userprofile';
static const VERIFY_EMAIL = 'verify-email';
@@ -36,6 +44,37 @@ class UserProvider with ChangeNotifier {
profile = null;
}
+ // Load theme mode from SharedPreferences
+ Future _loadThemeMode() async {
+ final prefsDarkMode = await prefs.getBool(PREFS_USER_DARK_THEME);
+
+ print(prefsDarkMode);
+
+ if (prefsDarkMode == null) {
+ themeMode = ThemeMode.system;
+ } else {
+ themeMode = prefsDarkMode ? ThemeMode.dark : ThemeMode.light;
+ }
+
+ print(themeMode);
+
+ notifyListeners();
+ }
+
+ // Change mode on switch button click
+ void setThemeMode(ThemeMode mode) async {
+ themeMode = mode;
+
+ // Save to SharedPreferences
+ if (themeMode == ThemeMode.system) {
+ await prefs.remove(PREFS_USER_DARK_THEME);
+ } else {
+ await prefs.setBool(PREFS_USER_DARK_THEME, themeMode == ThemeMode.dark);
+ }
+
+ notifyListeners();
+ }
+
/// Fetch the current user's profile
Future fetchAndSetProfile() async {
final userData = await baseProvider.fetch(baseProvider.makeUrl(PROFILE_URL));
diff --git a/lib/widgets/core/settings.dart b/lib/widgets/core/settings.dart
index 9dde8f8b..62b48be3 100644
--- a/lib/widgets/core/settings.dart
+++ b/lib/widgets/core/settings.dart
@@ -22,6 +22,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/nutrition.dart';
+import 'package:wger/providers/user.dart';
class SettingsPage extends StatelessWidget {
static String routeName = '/SettingsPage';
@@ -33,11 +34,11 @@ class SettingsPage extends StatelessWidget {
final i18n = AppLocalizations.of(context);
final exerciseProvider = Provider.of(context, listen: false);
final nutritionProvider = Provider.of(context, listen: false);
+ final userProvider = Provider.of(context);
+ final i18n = AppLocalizations.of(context);
return Scaffold(
- appBar: AppBar(
- title: Text(AppLocalizations.of(context).settingsTitle),
- ),
+ appBar: AppBar(title: Text(i18n.settingsTitle)),
body: ListView(
children: [
ListTile(
@@ -64,7 +65,7 @@ class SettingsPage extends StatelessWidget {
),
),
ListTile(
- title: Text(AppLocalizations.of(context).settingsIngredientCacheDescription),
+ title: Text(i18n.settingsIngredientCacheDescription),
trailing: IconButton(
key: const ValueKey('cacheIconIngredients'),
icon: const Icon(Icons.delete),
@@ -73,7 +74,7 @@ class SettingsPage extends StatelessWidget {
if (context.mounted) {
final snackBar = SnackBar(
- content: Text(AppLocalizations.of(context).settingsCacheDeletedSnackbar),
+ content: Text(i18n.settingsCacheDeletedSnackbar),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
@@ -81,6 +82,35 @@ class SettingsPage extends StatelessWidget {
},
),
),
+ ListTile(
+ title: Text(i18n.themeMode),
+ trailing: DropdownButton(
+ key: const ValueKey('themeModeDropdown'),
+ value: userProvider.themeMode,
+ onChanged: (ThemeMode? newValue) {
+ if (newValue != null) {
+ userProvider.setThemeMode(newValue);
+ }
+ },
+ items: ThemeMode.values.map>((ThemeMode value) {
+ final label = (() {
+ switch (value) {
+ case ThemeMode.system:
+ return i18n.systemMode;
+ case ThemeMode.light:
+ return i18n.lightMode;
+ case ThemeMode.dark:
+ return i18n.darkMode;
+ }
+ })();
+
+ return DropdownMenuItem(
+ value: value,
+ child: Text(label),
+ );
+ }).toList(),
+ ),
+ ),
],
),
);
diff --git a/pubspec.lock b/pubspec.lock
index 26471dbf..08709222 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
- sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
+ sha256: "03f6da266a27a4538a69295ec142cb5717d7d4e5727b84658b63e1e1509bac9c"
url: "https://pub.dev"
source: hosted
- version: "76.0.0"
+ version: "79.0.0"
_macros:
dependency: transitive
description: dart
@@ -18,18 +18,18 @@ packages:
dependency: transitive
description:
name: analyzer
- sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
+ sha256: c9040fc56483c22a5e04a9f6a251313118b1a3c42423770623128fa484115643
url: "https://pub.dev"
source: hosted
- version: "6.11.0"
+ version: "7.2.0"
archive:
dependency: transitive
description:
name: archive
- sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
+ sha256: "6199c74e3db4fbfbd04f66d739e72fe11c8a8957d5f219f1f4482dbde6420b5a"
url: "https://pub.dev"
source: hosted
- version: "3.6.1"
+ version: "4.0.2"
args:
dependency: transitive
description:
@@ -58,34 +58,34 @@ packages:
dependency: transitive
description:
name: build
- sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
+ sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0
url: "https://pub.dev"
source: hosted
- version: "2.4.1"
+ version: "2.4.2"
build_config:
dependency: transitive
description:
name: build_config
- sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
+ sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
url: "https://pub.dev"
source: hosted
- version: "1.1.1"
+ version: "1.1.2"
build_daemon:
dependency: transitive
description:
name: build_daemon
- sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
+ sha256: "294a2edaf4814a378725bfe6358210196f5ea37af89ecd81bfa32960113d4948"
url: "https://pub.dev"
source: hosted
- version: "4.0.2"
+ version: "4.0.3"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
- sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
+ sha256: "99d3980049739a985cf9b21f30881f46db3ebc62c5b8d5e60e27440876b1ba1e"
url: "https://pub.dev"
source: hosted
- version: "2.4.2"
+ version: "2.4.3"
build_runner:
dependency: "direct dev"
description:
@@ -114,42 +114,42 @@ packages:
dependency: transitive
description:
name: built_value
- sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb
+ sha256: "28a712df2576b63c6c005c465989a348604960c0958d28be5303ba9baa841ac2"
url: "https://pub.dev"
source: hosted
- version: "8.9.2"
+ version: "8.9.3"
camera:
dependency: transitive
description:
name: camera
- sha256: "26ff41045772153f222ffffecba711a206f670f5834d40ebf5eed3811692f167"
+ sha256: "413d2b34fe28496c35c69ede5b232fb9dd5ca2c3a4cb606b14efc1c7546cc8cb"
url: "https://pub.dev"
source: hosted
- version: "0.11.0+2"
+ version: "0.11.1"
camera_android_camerax:
dependency: transitive
description:
name: camera_android_camerax
- sha256: e3627fdc2132d89212b8a8676679f5b07008c7e3d8ae00cea775c3397f9e742b
+ sha256: "7cc6adf1868bdcf4e63a56b24b41692dfbad2bec1cdceea451c77798f6a605c3"
url: "https://pub.dev"
source: hosted
- version: "0.6.10"
+ version: "0.6.13"
camera_avfoundation:
dependency: transitive
description:
name: camera_avfoundation
- sha256: "2e4c568f70e406ccb87376bc06b53d2f5bebaab71e2fbcc1a950e31449381bcf"
+ sha256: "3f81ee3e88a79b0b010f0233d42625926299551b05d5dc995267a0b35bc33247"
url: "https://pub.dev"
source: hosted
- version: "0.9.17+5"
+ version: "0.9.18"
camera_platform_interface:
dependency: transitive
description:
name: camera_platform_interface
- sha256: b3ede1f171532e0d83111fe0980b46d17f1aa9788a07a2fbed07366bbdbb9061
+ sha256: "953e7baed3a7c8fae92f7200afeb2be503ff1a17c3b4e4ed7b76f008c2810a31"
url: "https://pub.dev"
source: hosted
- version: "2.8.0"
+ version: "2.9.0"
camera_web:
dependency: transitive
description:
@@ -170,10 +170,10 @@ packages:
dependency: transitive
description:
name: change
- sha256: "65db7f966dc7e786687f49900a94c5f08b0eb9ca8c4a3e7eed3a55e980b455e2"
+ sha256: "3bda1ce98526b21927cdea05688563c7065fd7e66d1abbe176c354fef3b2057b"
url: "https://pub.dev"
source: hosted
- version: "0.7.4"
+ version: "0.7.5"
characters:
dependency: transitive
description:
@@ -186,10 +186,10 @@ packages:
dependency: transitive
description:
name: charcode
- sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306
+ sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a
url: "https://pub.dev"
source: hosted
- version: "1.3.1"
+ version: "1.4.0"
checked_yaml:
dependency: transitive
description:
@@ -282,26 +282,26 @@ packages:
dependency: transitive
description:
name: dart_style
- sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
+ sha256: "27eb0ae77836989a3bc541ce55595e8ceee0992807f14511552a898ddd0d88ac"
url: "https://pub.dev"
source: hosted
- version: "2.3.7"
+ version: "3.0.1"
drift:
dependency: "direct main"
description:
name: drift
- sha256: af3941e4d544727b2eb80590eb64e9cb8d77cd68c7690265502ea6a2427aa621
+ sha256: "76f23535e19a9f2be92f954e74d8802e96f526e5195d7408c1a20f6659043941"
url: "https://pub.dev"
source: hosted
- version: "2.23.1"
+ version: "2.24.0"
drift_dev:
dependency: "direct dev"
description:
name: drift_dev
- sha256: fa98fdbb7303a1b5b2dc110cb516eda2253a5d291680f8cbc72b1af24099f7f9
+ sha256: d1d90b0d55b22de412b77186f3bf3179a4b7e2acc4c8fb3a7aaf28a01abc194b
url: "https://pub.dev"
source: hosted
- version: "2.23.1"
+ version: "2.24.0"
equatable:
dependency: "direct main"
description:
@@ -338,10 +338,10 @@ packages:
dependency: transitive
description:
name: file_selector_linux
- sha256: b2b91daf8a68ecfa4a01b778a6f52edef9b14ecd506e771488ea0f2e0784198b
+ sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33"
url: "https://pub.dev"
source: hosted
- version: "0.9.3+1"
+ version: "0.9.3+2"
file_selector_macos:
dependency: transitive
description:
@@ -386,10 +386,10 @@ packages:
dependency: "direct main"
description:
name: flex_color_scheme
- sha256: "90f4fe67b9561ae8a4af117df65a8ce9988624025667c54e6d304e65cff77d52"
+ sha256: "09bea5d776f694c5a67f2229f2aa500cc7cce369322dc6500ab01cf9ad1b4e1a"
url: "https://pub.dev"
source: hosted
- version: "8.0.2"
+ version: "8.1.0"
flex_seed_scheme:
dependency: "direct main"
description:
@@ -497,18 +497,10 @@ packages:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
- sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398"
+ sha256: "615a505aef59b151b46bbeef55b36ce2b6ed299d160c51d84281946f0aa0ce0e"
url: "https://pub.dev"
source: hosted
- version: "2.0.23"
- flutter_riverpod:
- dependency: "direct main"
- description:
- name: flutter_riverpod
- sha256: "9532ee6db4a943a1ed8383072a2e3eeda041db5657cdf6d2acecf3c21ecbe7e1"
- url: "https://pub.dev"
- source: hosted
- version: "2.6.1"
+ version: "2.0.24"
flutter_staggered_grid_view:
dependency: "direct main"
description:
@@ -521,10 +513,10 @@ packages:
dependency: "direct main"
description:
name: flutter_svg
- sha256: "54900a1a1243f3c4a5506d853a2b5c2dbc38d5f27e52a52618a8054401431123"
+ sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b
url: "https://pub.dev"
source: hosted
- version: "2.0.16"
+ version: "2.0.17"
flutter_svg_icons:
dependency: "direct main"
description:
@@ -571,10 +563,10 @@ packages:
dependency: "direct dev"
description:
name: freezed
- sha256: "44c19278dd9d89292cf46e97dc0c1e52ce03275f40a97c5a348e802a924bf40e"
+ sha256: "59a584c24b3acdc5250bb856d0d3e9c0b798ed14a4af1ddb7dc1c7b41df91c9c"
url: "https://pub.dev"
source: hosted
- version: "2.5.7"
+ version: "2.5.8"
freezed_annotation:
dependency: "direct main"
description:
@@ -608,10 +600,10 @@ packages:
dependency: transitive
description:
name: glob
- sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
+ sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
url: "https://pub.dev"
source: hosted
- version: "2.1.2"
+ version: "2.1.3"
golden_toolkit:
dependency: "direct dev"
description:
@@ -640,34 +632,34 @@ packages:
dependency: "direct main"
description:
name: http
- sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
+ sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f
url: "https://pub.dev"
source: hosted
- version: "1.2.2"
+ version: "1.3.0"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
- sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
+ sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
url: "https://pub.dev"
source: hosted
- version: "3.2.1"
+ version: "3.2.2"
http_parser:
dependency: transitive
description:
name: http_parser
- sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
+ sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.dev"
source: hosted
- version: "4.0.2"
+ version: "4.1.2"
image:
dependency: transitive
description:
name: image
- sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d
+ sha256: "8346ad4b5173924b5ddddab782fc7d8a6300178c8b1dc427775405a01701c4a6"
url: "https://pub.dev"
source: hosted
- version: "4.3.0"
+ version: "4.5.2"
image_picker:
dependency: "direct main"
description:
@@ -680,10 +672,10 @@ packages:
dependency: transitive
description:
name: image_picker_android
- sha256: "8faba09ba361d4b246dc0a17cb4289b3324c2b9f6db7b3d457ee69106a86bd32"
+ sha256: b62d34a506e12bb965e824b6db4fbf709ee4589cf5d3e99b45ab2287b008ee0c
url: "https://pub.dev"
source: hosted
- version: "0.8.12+17"
+ version: "0.8.12+20"
image_picker_for_web:
dependency: transitive
description:
@@ -696,10 +688,10 @@ packages:
dependency: transitive
description:
name: image_picker_ios
- sha256: "4f0568120c6fcc0aaa04511cb9f9f4d29fc3d0139884b1d06be88dcec7641d6b"
+ sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100"
url: "https://pub.dev"
source: hosted
- version: "0.8.12+1"
+ version: "0.8.12+2"
image_picker_linux:
dependency: transitive
description:
@@ -712,18 +704,18 @@ packages:
dependency: transitive
description:
name: image_picker_macos
- sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62"
+ sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1"
url: "https://pub.dev"
source: hosted
- version: "0.2.1+1"
+ version: "0.2.1+2"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
- sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80"
+ sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0"
url: "https://pub.dev"
source: hosted
- version: "2.10.0"
+ version: "2.10.1"
image_picker_windows:
dependency: transitive
description:
@@ -749,10 +741,10 @@ packages:
dependency: transitive
description:
name: io
- sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
+ sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
url: "https://pub.dev"
source: hosted
- version: "1.0.4"
+ version: "1.0.5"
js:
dependency: transitive
description:
@@ -773,10 +765,10 @@ packages:
dependency: "direct dev"
description:
name: json_serializable
- sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c
+ sha256: b0a98230538fe5d0b60a22fb6bf1b6cb03471b53e3324ff6069c591679dd59c9
url: "https://pub.dev"
source: hosted
- version: "6.9.0"
+ version: "6.9.3"
leak_tracker:
dependency: transitive
description:
@@ -805,10 +797,10 @@ packages:
dependency: transitive
description:
name: lints
- sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
+ sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
url: "https://pub.dev"
source: hosted
- version: "5.0.0"
+ version: "5.1.1"
list_counter:
dependency: transitive
description:
@@ -837,10 +829,10 @@ packages:
dependency: transitive
description:
name: markdown
- sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051
+ sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1"
url: "https://pub.dev"
source: hosted
- version: "7.2.2"
+ version: "7.3.0"
marker:
dependency: transitive
description:
@@ -885,10 +877,10 @@ packages:
dependency: "direct dev"
description:
name: mockito
- sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917"
+ sha256: f99d8d072e249f719a5531735d146d8cf04c580d93920b04de75bef6dfb2daf6
url: "https://pub.dev"
source: hosted
- version: "5.4.4"
+ version: "5.4.5"
multi_select_flutter:
dependency: "direct main"
description:
@@ -917,26 +909,26 @@ packages:
dependency: transitive
description:
name: package_config
- sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
+ sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67"
url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "2.1.1"
package_info_plus:
dependency: "direct main"
description:
name: package_info_plus
- sha256: da8d9ac8c4b1df253d1a328b7bf01ae77ef132833479ab40763334db13b91cce
+ sha256: "739e0a5c3c4055152520fa321d0645ee98e932718b4c8efeeb51451968fe0790"
url: "https://pub.dev"
source: hosted
- version: "8.1.1"
+ version: "8.1.3"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
- sha256: ac1f4a4847f1ade8e6a87d1f39f5d7c67490738642e2542f559ec38c37489a66
+ sha256: a5ef9986efc7bf772f2696183a3992615baa76c1ffb1189318dd8803778fb05b
url: "https://pub.dev"
source: hosted
- version: "3.0.1"
+ version: "3.0.2"
path:
dependency: "direct main"
description:
@@ -965,18 +957,18 @@ packages:
dependency: transitive
description:
name: path_provider_android
- sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a
+ sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2"
url: "https://pub.dev"
source: hosted
- version: "2.2.12"
+ version: "2.2.15"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
- sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
+ sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
url: "https://pub.dev"
source: hosted
- version: "2.4.0"
+ version: "2.4.1"
path_provider_linux:
dependency: transitive
description:
@@ -1065,6 +1057,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.5.1"
+ posix:
+ dependency: transitive
+ description:
+ name: posix
+ sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.0.1"
process:
dependency: transitive
description:
@@ -1085,18 +1085,18 @@ packages:
dependency: transitive
description:
name: pub_semver
- sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
+ sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd"
url: "https://pub.dev"
source: hosted
- version: "2.1.4"
+ version: "2.1.5"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
- sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8
+ sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082"
url: "https://pub.dev"
source: hosted
- version: "1.3.0"
+ version: "1.5.0"
recase:
dependency: transitive
description:
@@ -1129,14 +1129,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.4.15"
- riverpod:
- dependency: transitive
- description:
- name: riverpod
- sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959"
- url: "https://pub.dev"
- source: hosted
- version: "2.6.1"
shared_preferences:
dependency: "direct main"
description:
@@ -1149,18 +1141,18 @@ packages:
dependency: transitive
description:
name: shared_preferences_android
- sha256: "02a7d8a9ef346c9af715811b01fbd8e27845ad2c41148eefd31321471b41863d"
+ sha256: "138b7bbbc7f59c56236e426c37afb8f78cbc57b094ac64c440e0bb90e380a4f5"
url: "https://pub.dev"
source: hosted
- version: "2.4.0"
+ version: "2.4.2"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
- sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d"
+ sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
url: "https://pub.dev"
source: hosted
- version: "2.5.3"
+ version: "2.5.4"
shared_preferences_linux:
dependency: transitive
description:
@@ -1170,7 +1162,7 @@ packages:
source: hosted
version: "2.4.1"
shared_preferences_platform_interface:
- dependency: transitive
+ dependency: "direct dev"
description:
name: shared_preferences_platform_interface
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
@@ -1197,18 +1189,18 @@ packages:
dependency: transitive
description:
name: shelf
- sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
+ sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
url: "https://pub.dev"
source: hosted
- version: "1.4.1"
+ version: "1.4.2"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
- sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
+ sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
url: "https://pub.dev"
source: hosted
- version: "2.0.0"
+ version: "2.0.1"
simple_gesture_detector:
dependency: transitive
description:
@@ -1226,18 +1218,18 @@ packages:
dependency: transitive
description:
name: source_gen
- sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
+ sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b"
url: "https://pub.dev"
source: hosted
- version: "1.5.0"
+ version: "2.0.0"
source_helper:
dependency: transitive
description:
name: source_helper
- sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd"
+ sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c"
url: "https://pub.dev"
source: hosted
- version: "1.3.4"
+ version: "1.3.5"
source_span:
dependency: transitive
description:
@@ -1250,26 +1242,26 @@ packages:
dependency: transitive
description:
name: sqlite3
- sha256: bb174b3ec2527f9c5f680f73a89af8149dd99782fbb56ea88ad0807c5638f2ed
+ sha256: "35d3726fe18ab1463403a5cc8d97dbc81f2a0b08082e8173851363fcc97b6627"
url: "https://pub.dev"
source: hosted
- version: "2.4.7"
+ version: "2.7.2"
sqlite3_flutter_libs:
dependency: "direct main"
description:
name: sqlite3_flutter_libs
- sha256: "73016db8419f019e807b7a5e5fbf2a7bd45c165fed403b8e7681230f3a102785"
+ sha256: "50a7e3f294c741d3142eed0ff228e38498334e11e0ccb9d73e0496e005949e44"
url: "https://pub.dev"
source: hosted
- version: "0.5.28"
+ version: "0.5.29"
sqlparser:
dependency: transitive
description:
name: sqlparser
- sha256: "4cad4b2c5f63dc9ea1a8dcffb58cf762322bea5dd8836870164a65e913bdae41"
+ sha256: "27dd0a9f0c02e22ac0eb42a23df9ea079ce69b52bb4a3b478d64e0ef34a263ee"
url: "https://pub.dev"
source: hosted
- version: "0.40.0"
+ version: "0.41.0"
stack_trace:
dependency: transitive
description:
@@ -1278,14 +1270,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.12.0"
- state_notifier:
- dependency: transitive
- description:
- name: state_notifier
- sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb
- url: "https://pub.dev"
- source: hosted
- version: "1.0.0"
stream_channel:
dependency: transitive
description:
@@ -1298,10 +1282,10 @@ packages:
dependency: transitive
description:
name: stream_transform
- sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
+ sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "2.1.1"
string_scanner:
dependency: transitive
description:
@@ -1322,10 +1306,10 @@ packages:
dependency: "direct main"
description:
name: table_calendar
- sha256: "4ca32b2fc919452c9974abd4c6ea611a63e33b9e4f0b8c38dba3ac1f4a6549d1"
+ sha256: "0c0c6219878b363a2d5f40c7afb159d845f253d061dc3c822aa0d5fe0f721982"
url: "https://pub.dev"
source: hosted
- version: "3.1.2"
+ version: "3.2.0"
term_glyph:
dependency: transitive
description:
@@ -1346,10 +1330,10 @@ packages:
dependency: transitive
description:
name: timing
- sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
+ sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe"
url: "https://pub.dev"
source: hosted
- version: "1.0.1"
+ version: "1.0.2"
typed_data:
dependency: transitive
description:
@@ -1378,10 +1362,10 @@ packages:
dependency: transitive
description:
name: url_launcher_ios
- sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e
+ sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626"
url: "https://pub.dev"
source: hosted
- version: "6.3.1"
+ version: "6.3.2"
url_launcher_linux:
dependency: transitive
description:
@@ -1394,10 +1378,10 @@ packages:
dependency: transitive
description:
name: url_launcher_macos
- sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672"
+ sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2"
url: "https://pub.dev"
source: hosted
- version: "3.2.1"
+ version: "3.2.2"
url_launcher_platform_interface:
dependency: transitive
description:
@@ -1410,42 +1394,42 @@ packages:
dependency: transitive
description:
name: url_launcher_web
- sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
+ sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9"
url: "https://pub.dev"
source: hosted
- version: "2.3.3"
+ version: "2.4.0"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
- sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4"
+ sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
url: "https://pub.dev"
source: hosted
- version: "3.1.3"
+ version: "3.1.4"
vector_graphics:
dependency: transitive
description:
name: vector_graphics
- sha256: "773c9522d66d523e1c7b25dfb95cc91c26a1e17b107039cfe147285e92de7878"
+ sha256: "27d5fefe86fb9aace4a9f8375b56b3c292b64d8c04510df230f849850d912cb7"
url: "https://pub.dev"
source: hosted
- version: "1.1.14"
+ version: "1.1.15"
vector_graphics_codec:
dependency: transitive
description:
name: vector_graphics_codec
- sha256: "2430b973a4ca3c4dbc9999b62b8c719a160100dcbae5c819bae0cacce32c9cdb"
+ sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146"
url: "https://pub.dev"
source: hosted
- version: "1.1.12"
+ version: "1.1.13"
vector_graphics_compiler:
dependency: transitive
description:
name: vector_graphics_compiler
- sha256: ab9ff38fc771e9ee1139320adbe3d18a60327370c218c60752068ebee4b49ab1
+ sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad"
url: "https://pub.dev"
source: hosted
- version: "1.1.15"
+ version: "1.1.16"
vector_math:
dependency: transitive
description:
@@ -1482,18 +1466,18 @@ packages:
dependency: transitive
description:
name: video_player_android
- sha256: "391e092ba4abe2f93b3e625bd6b6a6ec7d7414279462c1c0ee42b5ab8d0a0898"
+ sha256: "7018dbcb395e2bca0b9a898e73989e67c0c4a5db269528e1b036ca38bcca0d0b"
url: "https://pub.dev"
source: hosted
- version: "2.7.16"
+ version: "2.7.17"
video_player_avfoundation:
dependency: transitive
description:
name: video_player_avfoundation
- sha256: cd5ab8a8bc0eab65ab0cea40304097edc46da574c8c1ecdee96f28cd8ef3792f
+ sha256: "8a4e73a3faf2b13512978a43cf1cdda66feeeb900a0527f1fbfd7b19cf3458d3"
url: "https://pub.dev"
source: hosted
- version: "2.6.2"
+ version: "2.6.7"
video_player_platform_interface:
dependency: transitive
description:
@@ -1522,10 +1506,10 @@ packages:
dependency: transitive
description:
name: watcher
- sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
+ sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104"
url: "https://pub.dev"
source: hosted
- version: "1.1.0"
+ version: "1.1.1"
web:
dependency: transitive
description:
@@ -1546,10 +1530,10 @@ packages:
dependency: transitive
description:
name: web_socket_channel
- sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
+ sha256: "0b8e2457400d8a859b7b2030786835a28a8e80836ef64402abef392ff4f1d0e5"
url: "https://pub.dev"
source: hosted
- version: "3.0.1"
+ version: "3.0.2"
webdriver:
dependency: transitive
description:
@@ -1562,10 +1546,10 @@ packages:
dependency: transitive
description:
name: win32
- sha256: "84ba388638ed7a8cb3445a320c8273136ab2631cd5f2c57888335504ddab1bc2"
+ sha256: "154360849a56b7b67331c21f09a386562d88903f90a1099c5987afc1912e1f29"
url: "https://pub.dev"
source: hosted
- version: "5.8.0"
+ version: "5.10.0"
xdg_directories:
dependency: transitive
description:
@@ -1586,10 +1570,10 @@ packages:
dependency: transitive
description:
name: yaml
- sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
+ sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
url: "https://pub.dev"
source: hosted
- version: "3.1.2"
+ version: "3.1.3"
sdks:
dart: ">=3.6.0 <4.0.0"
flutter: ">=3.27.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 7eaa6c39..a1ecac09 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -39,13 +39,13 @@ dependencies:
drift: ^2.16.0
equatable: ^2.0.7
fl_chart: ^0.69.2
- flex_color_scheme: ^8.0.2
+ flex_color_scheme: ^8.1.0
flex_seed_scheme: ^3.5.0
flutter_barcode_scanner: ^2.0.0
flutter_calendar_carousel: ^2.4.4
flutter_html: ^3.0.0-beta.2
flutter_staggered_grid_view: ^0.7.0
- flutter_svg: ^2.0.16
+ flutter_svg: ^2.0.17
flutter_svg_icons: ^0.0.1
flutter_typeahead: ^5.2.0
flutter_zxing: ^1.8.2
@@ -57,13 +57,13 @@ dependencies:
intl: ^0.19.0
json_annotation: ^4.8.1
multi_select_flutter: ^4.1.3
- package_info_plus: ^8.1.1
+ package_info_plus: ^8.1.3
path: ^1.9.0
path_provider: ^2.1.5
provider: ^6.1.2
rive: ^0.13.20
shared_preferences: ^2.3.5
- sqlite3_flutter_libs: ^0.5.28
+ sqlite3_flutter_libs: ^0.5.29
table_calendar: ^3.0.8
url_launcher: ^6.3.1
version: ^3.0.2
@@ -87,6 +87,7 @@ dev_dependencies:
json_serializable: ^6.9.0
mockito: ^5.4.4
network_image_mock: ^2.1.1
+ shared_preferences_platform_interface: ^2.0.0
# Script to read out unused translations
#translations_cleaner: ^0.0.5
diff --git a/test/core/settings_test.dart b/test/core/settings_test.dart
index 72806b48..8a1d6ff8 100644
--- a/test/core/settings_test.dart
+++ b/test/core/settings_test.dart
@@ -22,22 +22,39 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+import 'package:wger/helpers/consts.dart';
+import 'package:wger/providers/base_provider.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/nutrition.dart';
+import 'package:wger/providers/user.dart';
import 'package:wger/widgets/core/settings.dart';
import 'settings_test.mocks.dart';
-@GenerateMocks([ExercisesProvider, NutritionPlansProvider])
+@GenerateMocks([
+ ExercisesProvider,
+ NutritionPlansProvider,
+ UserProvider,
+ WgerBaseProvider,
+ SharedPreferencesAsync,
+])
void main() {
final mockExerciseProvider = MockExercisesProvider();
final mockNutritionProvider = MockNutritionPlansProvider();
+ final mockSharedPreferences = MockSharedPreferencesAsync();
+ final mockUserProvider = MockUserProvider();
+
+ setUp(() {
+ when(mockUserProvider.themeMode).thenReturn(ThemeMode.system);
+ });
Widget createSettingsScreen({locale = 'en'}) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => mockNutritionProvider),
ChangeNotifierProvider(create: (context) => mockExerciseProvider),
+ ChangeNotifierProvider(create: (context) => mockUserProvider),
],
child: MaterialApp(
locale: Locale(locale),
@@ -65,4 +82,35 @@ void main() {
verify(mockNutritionProvider.clearIngredientCache());
});
});
+
+ group('Theme settings', () {
+ test('Default theme is system', () async {
+ when(mockSharedPreferences.getBool(PREFS_USER_DARK_THEME)).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);
+ final userProvider = await UserProvider(MockWgerBaseProvider(), prefs: mockSharedPreferences);
+ expect(userProvider.themeMode, ThemeMode.light);
+ });
+
+ test('Saves theme to prefs', () {
+ when(mockSharedPreferences.getBool(any)).thenAnswer((_) async => null);
+ final userProvider = UserProvider(MockWgerBaseProvider(), prefs: mockSharedPreferences);
+ userProvider.setThemeMode(ThemeMode.dark);
+ verify(mockSharedPreferences.setBool(PREFS_USER_DARK_THEME, true)).called(1);
+ expect(userProvider.themeMode, ThemeMode.dark);
+ });
+
+ testWidgets('Test changing the theme mode in preferences', (WidgetTester tester) async {
+ await tester.pumpWidget(createSettingsScreen());
+ await tester.tap(find.byKey(const ValueKey('themeModeDropdown')));
+ await tester.pumpAndSettle();
+ await tester.tap(find.text('Always light mode'));
+
+ verify(mockUserProvider.setThemeMode(ThemeMode.light)).called(1);
+ });
+ });
}
diff --git a/test/user/provider_test.dart b/test/user/provider_test.dart
index 6d13688c..0aec436d 100644
--- a/test/user/provider_test.dart
+++ b/test/user/provider_test.dart
@@ -21,6 +21,8 @@ import 'dart:convert';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.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/providers/base_provider.dart';
import 'package:wger/providers/user.dart';
@@ -29,6 +31,7 @@ import 'provider_test.mocks.dart';
@GenerateMocks([WgerBaseProvider])
void main() {
+ TestWidgetsFlutterBinding.ensureInitialized();
late UserProvider userProvider;
late MockWgerBaseProvider mockWgerBaseProvider;
@@ -47,6 +50,7 @@ void main() {
);
setUp(() {
+ SharedPreferencesAsyncPlatform.instance = InMemorySharedPreferencesAsync.empty();
mockWgerBaseProvider = MockWgerBaseProvider();
userProvider = UserProvider(mockWgerBaseProvider);