Skip to content

Commit

Permalink
Merge pull request #24 from dbadrian/feature/logout_on_api_change
Browse files Browse the repository at this point in the history
Feature/logout on api change
  • Loading branch information
dbadrian authored Jan 4, 2025
2 parents 08f003e + 63d914b commit b7ec67b
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 67 deletions.
22 changes: 11 additions & 11 deletions frontend/lib/api/api_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class APIService {
final SettingsState settings = ref.read(settingsProvider);

final queryParameters = {
'lang': language ?? settings.language,
'lang': language ?? settings.current.language,
if (lcFilter != null) 'lc_filter': lcFilter.join(','),
if (search != null && search.isNotEmpty) 'search': search,
if (user != null) "user": user,
Expand Down Expand Up @@ -72,7 +72,7 @@ class APIService {
final SettingsState settings = ref.read(settingsProvider);

final queryParameters = {
'lang': language ?? settings.language,
'lang': language ?? settings.current.language,
if (servings != null) 'servings': servings,
if (lcFilter != null) 'lc_filter': lcFilter.join(','),
if (toMetric != null && toMetric) 'to_metric': "",
Expand All @@ -91,7 +91,7 @@ class APIService {
final SettingsState settings = ref.read(settingsProvider);

final queryParameters = {
'lang': lang ?? settings.language,
'lang': lang ?? settings.current.language,
};

final url =
Expand Down Expand Up @@ -162,7 +162,7 @@ class APIService {
final SettingsState settings = ref.read(settingsProvider);

final queryParameters = {
'lang': language ?? settings.language,
'lang': language ?? settings.current.language,
if (pageSize != null) 'page_size': pageSize.toString(),
};

Expand Down Expand Up @@ -234,7 +234,7 @@ class APIService {
final SettingsState settings = ref.read(settingsProvider);

final queryParameters = {
'lang': language ?? settings.language,
'lang': language ?? settings.current.language,
if (search != null && search.isNotEmpty) 'search': search,
if (pageSize != null) 'page_size': pageSize.toString(),
};
Expand All @@ -261,7 +261,7 @@ class APIService {
final SettingsState settings = ref.read(settingsProvider);

final queryParameters = {
'lang': language ?? settings.language,
'lang': language ?? settings.current.language,
if (search != null && search.isNotEmpty) 'search': search,
if (pageSize != null) 'page_size': pageSize.toString(),
if (pks != null) 'pks': pks.join(','),
Expand All @@ -279,7 +279,7 @@ class APIService {
final SettingsState settings = ref.read(settingsProvider);

final queryParameters = {
'lang': language ?? settings.language,
'lang': language ?? settings.current.language,
};
final url =
getAPIUrl(settings, "/foods/", queryParameters: queryParameters);
Expand All @@ -299,7 +299,7 @@ class APIService {
final SettingsState settings = ref.read(settingsProvider);

final queryParameters = {
'lang': language ?? settings.language,
'lang': language ?? settings.current.language,
if (search != null && search.isNotEmpty) 'search': search,
if (pageSize != null) 'page_size': pageSize.toString(),
if (pks != null) 'pks': pks.join(','),
Expand All @@ -319,7 +319,7 @@ class APIService {
final SettingsState settings = ref.read(settingsProvider);

final queryParameters = {
'lang': language ?? settings.language,
'lang': language ?? settings.current.language,
};

final url = getAPIUrl(settings, "/foods/$foodId/",
Expand Down Expand Up @@ -388,7 +388,7 @@ class APIService {
final SettingsState settings = ref.read(settingsProvider);

final queryParameters = {
'lang': language ?? settings.language,
'lang': language ?? settings.current.language,
if (search != null && search.isNotEmpty) 'search': search,
if (pageSize != null) 'page_size': pageSize.toString(),
};
Expand All @@ -403,7 +403,7 @@ class APIService {
Future<Tag> createTag(String tagJson, {String? language}) async {
final SettingsState settings = ref.read(settingsProvider);
final queryParameters = {
'lang': language ?? settings.language,
'lang': language ?? settings.current.language,
};

final url = getAPIUrl(settings, "/tags/", queryParameters: queryParameters);
Expand Down
2 changes: 1 addition & 1 deletion frontend/lib/api/api_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ Uri getAPIUrl(SettingsState settings, String path,
{Map<String, dynamic>? queryParameters, withPostSlash = true}) {
final midSlash = path.startsWith('/') ? '' : '/';
final postSlash = path.endsWith('/') || !withPostSlash ? '' : '/';
return Uri.parse('${settings.apiUrl}$midSlash$path$postSlash')
return Uri.parse('${settings.current.apiUrl}$midSlash$path$postSlash')
.replace(queryParameters: queryParameters);
}
2 changes: 1 addition & 1 deletion frontend/lib/config/zest_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import 'package:zest/utils/utils.dart';

// TODO: Set to empty string for (v.1.0.0) release
const String DEFAULT_API_URL = 'http://dbadrian.com/api/v1';
const String DEFAULT_API_URL = 'https://dbadrian.com/api/v1';

///
const API_RECIPE_SEARCH_FIELDS = {
Expand Down
6 changes: 3 additions & 3 deletions frontend/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,16 @@ class ZestApp extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final router = ref.watch(getRouterProvider);

final Color themeBaseColor = ref
.watch(settingsProvider.select((settings) => settings.themeBaseColor));
final Color themeBaseColor = ref.watch(
settingsProvider.select((settings) => settings.dirty.themeBaseColor));

final lightTheme_ = lightTheme.copyWith(
colorScheme: ColorScheme.fromSeed(seedColor: themeBaseColor));
final darkTheme_ = darkTheme.copyWith(
colorScheme: ColorScheme.fromSeed(seedColor: themeBaseColor));

final useDarkTheme = ref.watch(settingsProvider.select((settings) {
return settings.useDarkTheme;
return settings.dirty.useDarkTheme;
}));

return MaterialApp.router(
Expand Down
2 changes: 1 addition & 1 deletion frontend/lib/recipes/controller/details_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class RecipeDetailsController extends _$RecipeDetailsController {
// afterwards we want silent updates?
state = const AsyncValue.loading();

String language = ref.watch(settingsProvider).language;
String language = ref.watch(settingsProvider).current.language;
final recipeValue =
await AsyncValue.guard(() => _loadRecipe(language: language));
if (recipeValue.hasError) {
Expand Down
5 changes: 3 additions & 2 deletions frontend/lib/recipes/controller/edit_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ class RecipeEditController extends _$RecipeEditController {
// set state to loading only for the initial page build
// afterwards we want silent updates?
state = const AsyncValue.loading();
final language = ref.watch(settingsProvider.select((v) => v.language));
final language =
ref.watch(settingsProvider.select((v) => v.current.language));
final recipeValue = await AsyncValue.guard(() =>
ref.read(apiServiceProvider).getRecipe(recipeId, language: language));
if (recipeValue.hasError) {
Expand Down Expand Up @@ -282,7 +283,7 @@ class RecipeEditController extends _$RecipeEditController {
recipeId: "",
dateCreated: DateTime.now(),
owner: "",
language: ref.read(settingsProvider).language,
language: ref.read(settingsProvider).current.language,
title: "",
private: false,
ownerComment: "",
Expand Down
9 changes: 6 additions & 3 deletions frontend/lib/recipes/controller/search_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ class RecipeSearchFilterSettings extends _$RecipeSearchFilterSettings {
// Default: we only show the current user language, unless user
// specified to always show all languages
final showAllLanguages =
ref.watch(settingsProvider.select((s) => s.searchAllLanguages));
ref.watch(settingsProvider.select((s) => s.current.searchAllLanguages));
Set<String> lcFilter = {};
if (showAllLanguages) {
lcFilter.addAll(AVAILABLE_LANGUAGES.keys);
} else {
lcFilter.add(ref.watch(settingsProvider.select((s) => s.language)));
lcFilter
.add(ref.watch(settingsProvider.select((s) => s.current.language)));
}
return FilterSettingsState(
lcFilter: lcFilter,
Expand Down Expand Up @@ -81,7 +82,9 @@ class RecipeSearchFilterSettings extends _$RecipeSearchFilterSettings {
} else {
state = state.copyWith(
showAllLanguages: false,
lcFilter: {ref.watch(settingsProvider.select((s) => s.language))},
lcFilter: {
ref.watch(settingsProvider.select((s) => s.current.language))
},
);
}
}
Expand Down
5 changes: 3 additions & 2 deletions frontend/lib/recipes/screens/recipe_details.dart
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ TableRow buildIngredientRow(WidgetRef ref, Ingredient ingredient,
String recipeId, bool isMarked, Function() markCallback) {
final amount = ingredient.getAmount();
final unit = ingredient.getUnitAbbreviation(
matchLanguage: ref.read(settingsProvider).language);
matchLanguage: ref.read(settingsProvider).current.language);
final food = ingredient.food;
final details = ingredient.details;

Expand Down Expand Up @@ -612,7 +612,8 @@ TableRow buildIngredientRow(WidgetRef ref, Ingredient ingredient,
onConfirm: (String value) async {
final translatedName = TranslatedField(values: [
TranslatedValue(
value: value, lang: ref.read(settingsProvider).language)
value: value,
lang: ref.read(settingsProvider).current.language)
]);
final translatedFood = food.copyWith(name: translatedName);
final json = translatedFood.toJson(); // toJsonExplicit();
Expand Down
2 changes: 1 addition & 1 deletion frontend/lib/recipes/screens/recipe_list_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class RecipeListTile extends ConsumerWidget {

trailing: (language != null &&
language!.isNotEmpty &&
language != ref.watch(settingsProvider).language)
language != ref.watch(settingsProvider).current.language)
? Column(mainAxisAlignment: MainAxisAlignment.center, children: [
CountryFlag.fromLanguageCode(
language!,
Expand Down
2 changes: 1 addition & 1 deletion frontend/lib/recipes/screens/widgets/ingredient_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ class FoodCreationTile extends ConsumerWidget {
title: Text("Add food '${foodController.text}'"),
onTap: () async {
final currentLanguage =
ref.watch(settingsProvider.select((s) => s.language));
ref.watch(settingsProvider.select((s) => s.current.language));
foodCreationDialog(
initialLanguage: currentLanguage,
initialValue: foodController.text,
Expand Down
6 changes: 3 additions & 3 deletions frontend/lib/recipes/screens/widgets/translatable_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class _TranslatableFieldState extends ConsumerState<TranslatableField> {

bool canBeTranslated() {
final settings = ref.read(settingsProvider);
return settings.language != widget.field.activeLanguage();
return settings.current.language != widget.field.activeLanguage();
}

Widget _buildTranslationDialog(
Expand All @@ -126,8 +126,8 @@ class _TranslatableFieldState extends ConsumerState<TranslatableField> {
child: TextFormField(
controller: controller,
decoration: InputDecoration(
labelText:
AVAILABLE_LANGUAGES[ref.read(settingsProvider).language],
labelText: AVAILABLE_LANGUAGES[
ref.read(settingsProvider).current.language],
// suffixText: "optional",
// border: const OutlineInputBorder(),
),
Expand Down
61 changes: 41 additions & 20 deletions frontend/lib/settings/settings_provider.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:go_router/go_router.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:zest/authentication/auth_service.dart';
import 'package:zest/ui/login_screen.dart';

import '../config/constants.dart';
import '../config/zest_api.dart';
Expand All @@ -24,8 +27,8 @@ const _showAdvancedSettingsKey = 'settings_show_advanced_settings';
const _baseColor = Color.fromARGB(255, 7, 228, 255);

@freezed
class SettingsState with _$SettingsState {
factory SettingsState({
class SettingsStateData with _$SettingsStateData {
const factory SettingsStateData({
// Language: UI and Content
// TODO Default language should be infered based on system language
@Default(DEFAULT_LANGUAGE) String language,
Expand All @@ -38,9 +41,18 @@ class SettingsState with _$SettingsState {

// API Related
@Default(DEFAULT_API_URL) apiUrl,
@Default(false) bool apiUrlDirty,

// Advanced Settings
@Default(false) bool showAdvancedSettings,
}) = _SettingsStateData;
}

@freezed
class SettingsState with _$SettingsState {
factory SettingsState({
@Default(SettingsStateData()) SettingsStateData current,
@Default(SettingsStateData()) SettingsStateData dirty,
}) = _SettingsState;
}

Expand All @@ -52,31 +64,31 @@ class Settings extends _$Settings {
}

void setUseDarkTheme(bool useDarkTheme) {
state = state.copyWith(useDarkTheme: useDarkTheme);
state = state.copyWith.dirty(useDarkTheme: useDarkTheme);
}

void setPickerColor(Color pickerColor) {
state = state.copyWith(pickerColor: pickerColor);
state = state.copyWith.dirty(pickerColor: pickerColor);
}

void setThemeColor(Color themeBaseColor) {
state = state.copyWith(themeBaseColor: themeBaseColor);
state = state.copyWith.dirty(themeBaseColor: themeBaseColor);
}

void setLanguage(String language) {
state = state.copyWith(language: language);
state = state.copyWith.dirty(language: language);
}

void setSearchAllLanguages(bool searchAllLanguages) {
state = state.copyWith(searchAllLanguages: searchAllLanguages);
state = state.copyWith.dirty(searchAllLanguages: searchAllLanguages);
}

void setApiUrl(String apiUrl) {
state = state.copyWith(apiUrl: apiUrl);
state = state.copyWith.dirty(apiUrl: apiUrl, apiUrlDirty: true);
}

void setShowAdvancedSettings(bool showAdvancedSettings) {
state = state.copyWith(showAdvancedSettings: showAdvancedSettings);
state = state.copyWith.dirty(showAdvancedSettings: showAdvancedSettings);
}

SettingsState loadSettings() {
Expand All @@ -92,40 +104,49 @@ class Settings extends _$Settings {
final showAdvancedSettings =
prefs.getBool(_showAdvancedSettingsKey) ?? false;
final apiUrl = prefs.getString(apiUrlKey) ?? DEFAULT_API_URL;
return SettingsState(
final apiUrlDirty = false;

final gt = SettingsStateData(
useDarkTheme: useDarkTheme,
pickerColor: Color(pickerColor),
themeBaseColor: Color(themeBaseColor),
language: language,
searchAllLanguages: searchAllLanguages,
showAdvancedSettings: showAdvancedSettings,
apiUrl: apiUrl,
apiUrlDirty: apiUrlDirty,
);

return SettingsState(current: gt, dirty: gt);
}

// Load settings from the sharedPrefs
void discardSettings() {
void discardChanges() {
state = loadSettings();
}

// Load settings from the sharedPrefs
void restoreDefaultSettings() {
state = SettingsState(showAdvancedSettings: state.showAdvancedSettings);
final gt = SettingsStateData(
showAdvancedSettings: state.dirty.showAdvancedSettings);
state = SettingsState(current: gt, dirty: gt);
}

// Write them to the sharedPrefs
void persistSettings() {
void persistSettings() async {
// saveSettings(ref, state);
final prefs = ref.read(sharedPreferencesProvider);
// Theme
prefs.setBool(_themeUseDarkThemeKey, state.useDarkTheme);
prefs.setInt(_themeColorPickerKey, state.pickerColor.value);
prefs.setInt(_themeBaseColorKey, state.themeBaseColor.value);
prefs.setBool(_themeUseDarkThemeKey, state.dirty.useDarkTheme);
prefs.setInt(_themeColorPickerKey, state.dirty.pickerColor.value);
prefs.setInt(_themeBaseColorKey, state.dirty.themeBaseColor.value);
// Language
prefs.setString(_languageKey, state.language);
prefs.setBool(_searchAllLanguagesKey, state.searchAllLanguages);
prefs.setString(_languageKey, state.dirty.language);
prefs.setBool(_searchAllLanguagesKey, state.dirty.searchAllLanguages);
// Advanced
prefs.setBool(_showAdvancedSettingsKey, state.showAdvancedSettings);
prefs.setString(apiUrlKey, state.apiUrl);
prefs.setBool(_showAdvancedSettingsKey, state.dirty.showAdvancedSettings);
prefs.setString(apiUrlKey, state.dirty.apiUrl);

state = state.copyWith(current: state.dirty);
}
}
Loading

0 comments on commit b7ec67b

Please sign in to comment.