From 19e35608b80facb73d04f38be53fb0672b7312c9 Mon Sep 17 00:00:00 2001 From: Aman Raj <57723319+AshAman999@users.noreply.github.com> Date: Mon, 2 May 2022 11:36:28 +0530 Subject: [PATCH 01/27] fix: filter while selecting countries #1200 (#1728) * added country search feat * even look for country selection * color edits * added optional parameter of onchanged * more genericn style for country selector --- .../widgets/smooth_text_form_field.dart | 23 ++- .../pages/onboarding/country_selector.dart | 187 ++++++++++-------- .../lib/pages/onboarding/welcome_page.dart | 38 ++-- .../lib/pages/user_preferences_profile.dart | 7 +- 4 files changed, 136 insertions(+), 119 deletions(-) diff --git a/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart b/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart index dbeb1703b43..486ba7e9fd6 100644 --- a/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart +++ b/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart @@ -21,6 +21,7 @@ class SmoothTextFormField extends StatefulWidget { this.hintTextFontSize, this.prefixIcon, this.textInputType, + this.onChanged, }) : super(key: key); final TextFieldTypes type; @@ -35,6 +36,7 @@ class SmoothTextFormField extends StatefulWidget { final double? hintTextFontSize; final Color? backgroundColor; final TextInputType? textInputType; + final void Function(String?)? onChanged; @override State createState() => _SmoothTextFormFieldState(); @@ -65,16 +67,17 @@ class _SmoothTextFormFieldState extends State { autocorrect: _autocorrect, autofillHints: widget.autofillHints, autovalidateMode: AutovalidateMode.onUserInteraction, - onChanged: (String data) { - // Rebuilds for changing the eye icon - if (widget.type == TextFieldTypes.PASSWORD) { - if (data.isEmpty) { - setState(() {}); - } else if (data.isNotEmpty && data.length > 1) { - setState(() {}); - } - } - }, + onChanged: widget.onChanged ?? + (String data) { + // Rebuilds for changing the eye icon + if (widget.type == TextFieldTypes.PASSWORD) { + if (data.isEmpty) { + setState(() {}); + } else if (data.isNotEmpty && data.length > 1) { + setState(() {}); + } + } + }, decoration: InputDecoration( prefixIcon: widget.prefixIcon, filled: true, diff --git a/packages/smooth_app/lib/pages/onboarding/country_selector.dart b/packages/smooth_app/lib/pages/onboarding/country_selector.dart index 54c4dc075c3..6e6bbc927a2 100644 --- a/packages/smooth_app/lib/pages/onboarding/country_selector.dart +++ b/packages/smooth_app/lib/pages/onboarding/country_selector.dart @@ -1,20 +1,19 @@ import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:iso_countries/iso_countries.dart'; import 'package:openfoodfacts/utils/CountryHelper.dart'; import 'package:smooth_app/data_models/user_preferences.dart'; import 'package:smooth_app/database/product_query.dart'; +import 'package:smooth_app/generic_lib/buttons/smooth_action_button.dart'; +import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_text_form_field.dart'; /// A selector for selecting user's country. class CountrySelector extends StatefulWidget { const CountrySelector({ required this.initialCountryCode, - this.inputDecoration, - this.padding, }); - final String? initialCountryCode; - final InputDecoration? inputDecoration; - final EdgeInsetsGeometry? padding; @override State createState() => _CountrySelectorState(); @@ -48,61 +47,111 @@ class _CountrySelectorState extends State { } @override - Widget build(BuildContext context) => FutureBuilder( - future: _initFuture, - builder: (BuildContext context, AsyncSnapshot snapshot) { - if (snapshot.hasError) { - return Text('Fatal Error: ${snapshot.error}'); - } else if (snapshot.connectionState != ConnectionState.done) { - return const CircularProgressIndicator(); - } - return LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - final double parentWidth = constraints.maxWidth; - return Container( - padding: widget.padding, - child: DropdownButtonFormField( - value: _chosenValue, - decoration: widget.inputDecoration, - selectedItemBuilder: (BuildContext context) { - return _countryList - .map( - (Country country) => _CountrySelectorItem( - country: country, - parentWidth: parentWidth, - ), - ) - .toList(growable: false); - }, - items: _countryList - .map>((Country country) { - final bool isSelected = _chosenValue == country; + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context)!; + final TextEditingController _countryController = TextEditingController(); + return FutureBuilder( + future: _initFuture, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasError) { + return Text('Fatal Error: ${snapshot.error}'); + } else if (snapshot.connectionState != ConnectionState.done) { + return const CircularProgressIndicator(); + } - return DropdownMenuItem( - value: country, - child: DefaultTextStyle.merge( - child: _CountrySelectorItem( - country: country, - parentWidth: parentWidth, - ), - style: TextStyle( - fontWeight: isSelected ? FontWeight.bold : null, + return GestureDetector( + onTap: () async { + List filteredList = List.from(_countryList); + await showDialog( + context: context, + builder: (BuildContext context) { + return StatefulBuilder( + builder: (BuildContext context, + void Function(VoidCallback fn) setState) { + return SmoothAlertDialog.advanced( + close: false, + maxHeight: MediaQuery.of(context).size.height, + body: SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + child: Column( + children: [ + SmoothTextFormField( + type: TextFieldTypes.PLAIN_TEXT, + prefixIcon: const Icon(Icons.search), + controller: _countryController, + onChanged: (String? query) { + setState( + () { + filteredList = _countryList + .where( + (Country item) => + item.name.toLowerCase().contains( + query!.toLowerCase(), + ) | + item.countryCode + .toLowerCase() + .contains( + query.toLowerCase(), + ), + ) + .toList(); + }, + ); + }, + hintText: appLocalizations.search, + ), + Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: filteredList.length, + itemBuilder: (BuildContext context, int index) { + final Country country = filteredList[index]; + return ListTile( + title: Text(country.name), + onTap: () async { + _chosenValue = country; + await _setUserCountry( + _chosenValue.countryCode); + setState(() {}); + Navigator.of(context).pop(); + }, + ); + }, + ), + ), + ], + ), ), - ), - ); - }).toList(growable: false), - onChanged: (Country? value) async { - if (value != null) { - _chosenValue = value; - await _setUserCountry(_chosenValue.countryCode); - setState(() {}); - } - }, - ), + actions: [ + SmoothActionButton( + onPressed: () => Navigator.pop(context), + text: appLocalizations.cancel, + ), + ], + ); + }, + ); + }, ); - }); - }, - ); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + ), + child: ListTile( + leading: const Icon(Icons.public), + title: Text( + _chosenValue.name, + style: Theme.of(context).textTheme.headline3, + ), + trailing: const Icon(Icons.arrow_drop_down), + ), + ), + ); + }, + ); + } /// Sanitize the country list by removing countries that are not in [OpenFoodFactsCountry] /// and providing a fallback English name for countries that are in [OpenFoodFactsCountry] @@ -172,27 +221,3 @@ class _CountrySelectorState extends State { return countries; } } - -class _CountrySelectorItem extends StatelessWidget { - const _CountrySelectorItem({ - required this.country, - required this.parentWidth, - Key? key, - }) : assert(parentWidth >= 0), - super(key: key); - - final Country country; - final double parentWidth; - - @override - Widget build(BuildContext context) { - return ConstrainedBox( - // Set the maxWidth so the dropdown arrow icon doesn't overflow. - // 48 dp is needed to account for dropdown arrow icon and padding. - constraints: BoxConstraints(maxWidth: parentWidth - 48).normalize(), - child: Text( - country.name, - ), - ); - } -} diff --git a/packages/smooth_app/lib/pages/onboarding/welcome_page.dart b/packages/smooth_app/lib/pages/onboarding/welcome_page.dart index 3a8ecf65b67..247033a594f 100644 --- a/packages/smooth_app/lib/pages/onboarding/welcome_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/welcome_page.dart @@ -52,31 +52,23 @@ class WelcomePage extends StatelessWidget { style: bodyTextStyle, ), ), - CountrySelector( - initialCountryCode: WidgetsBinding - .instance?.window.locale.countryCode - ?.toLowerCase(), - padding: const EdgeInsets.only( - top: MEDIUM_SPACE, - bottom: LARGE_SPACE, - ), - inputDecoration: InputDecoration( - focusedBorder: OutlineInputBorder( - borderRadius: ROUNDED_BORDER_RADIUS, - borderSide: BorderSide( - color: Theme.of(context).primaryColorDark, - width: 2.0, - ), + Container( + decoration: BoxDecoration( + border: Border.all( + color: Colors.white, + width: 1, ), - border: const OutlineInputBorder( - borderSide: BorderSide( - color: Color.fromARGB(255, 235, 235, 235), - ), - borderRadius: ROUNDED_BORDER_RADIUS, + borderRadius: BorderRadius.circular( + LARGE_SPACE, ), - filled: Theme.of(context).colorScheme.brightness == - Brightness.light, - fillColor: const Color.fromARGB(255, 235, 235, 235), + color: Theme.of(context).cardColor, + ), + margin: + const EdgeInsets.symmetric(vertical: MEDIUM_SPACE), + child: CountrySelector( + initialCountryCode: WidgetsBinding + .instance?.window.locale.countryCode + ?.toLowerCase(), ), ), Padding( diff --git a/packages/smooth_app/lib/pages/user_preferences_profile.dart b/packages/smooth_app/lib/pages/user_preferences_profile.dart index 3a295be700d..77c056279d4 100644 --- a/packages/smooth_app/lib/pages/user_preferences_profile.dart +++ b/packages/smooth_app/lib/pages/user_preferences_profile.dart @@ -192,11 +192,8 @@ class _UserPreferencesPageState extends State { result.addAll( [ - ListTile( - leading: const Icon(Icons.public), - title: CountrySelector( - initialCountryCode: widget.userPreferences.userCountryCode, - ), + CountrySelector( + initialCountryCode: widget.userPreferences.userCountryCode, ), SwitchListTile( title: Text(appLocalizations.crash_reporting_toggle_title), From f2a31ccc503e476c3bb23378ded16d7d9b855c6b Mon Sep 17 00:00:00 2001 From: Marvin M <39344769+M123-dev@users.noreply.github.com> Date: Mon, 2 May 2022 14:00:16 +0200 Subject: [PATCH 02/27] Updated PR template (#1731) --- .github/pull_request_template.yml | 14 ++++++++++---- .github/workflows/ios-release.yml | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/pull_request_template.yml b/.github/pull_request_template.yml index 688895959bf..c997dea3b89 100644 --- a/.github/pull_request_template.yml +++ b/.github/pull_request_template.yml @@ -1,10 +1,16 @@ ### What -- description of the PR + +- Changed x to achieve y ### Screenshot -(Insert a screenshot to provide visual record of your changes, if visible) + + ### Fixes bug(s) -- #1, #2 and #3 (change by appropriate issues) + + +- Fixes: #1 +- Closes: #2 + ### Part of - https://github.com/openfoodfacts/smooth-app/issues/525 -(please be as granular as possible) + diff --git a/.github/workflows/ios-release.yml b/.github/workflows/ios-release.yml index 2df67e055f1..b4b8a767841 100644 --- a/.github/workflows/ios-release.yml +++ b/.github/workflows/ios-release.yml @@ -36,7 +36,7 @@ jobs: with: channel: stable cache: true - cache-key: flutter2.10 #change this to force refresh cache + cache-key: flutter2.10 # change this to force refresh cache - run: flutter --version - name: Get dependencies From 4777adbedfce8b006a9fd0769fc7f3ea6548aad0 Mon Sep 17 00:00:00 2001 From: Pualoo Date: Tue, 3 May 2022 12:27:53 -0300 Subject: [PATCH 03/27] feat: Button ingredient extraction appear after upload an image. Issue: #1624 (#1719) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 🐛 Set light mode on the scan page * fix: 🐛 Update nutrition table quantity ✅ Closes: #1671 * feat: 🎸 Button ingredient extraction appear after upload image ✅ Closes: #1624 --- .../pages/product/edit_ingredients_page.dart | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart b/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart index f51b5035a73..9ad291bf833 100644 --- a/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart @@ -193,6 +193,7 @@ class _EditIngredientsPageState extends State { onTapGetImage: _onTapGetImage, onSubmitField: _onSubmitField, updatingIngredients: _updatingIngredients, + hasImageProvider: _imageProvider != null, )); } @@ -234,6 +235,7 @@ class _EditIngredientsBody extends StatelessWidget { required this.onSubmitField, required this.onTapGetImage, required this.updatingIngredients, + required this.hasImageProvider, }) : super(key: key); final TextEditingController controller; @@ -241,6 +243,17 @@ class _EditIngredientsBody extends StatelessWidget { final String? imageIngredientsUrl; final Future Function(bool) onTapGetImage; final Future Function() onSubmitField; + final bool hasImageProvider; + + Widget _getExtraitIngredientsBtn(AppLocalizations appLocalizations) { + if (hasImageProvider || imageIngredientsUrl != null) { + return SmoothActionButton( + text: appLocalizations.edit_ingredients_extrait_ingredients_btn_text, + onPressed: () => onTapGetImage(false), + ); + } + return Container(); + } @override Widget build(BuildContext context) { @@ -280,11 +293,7 @@ class _EditIngredientsBody extends StatelessWidget { padding: const EdgeInsets.all(LARGE_SPACE), child: Column( children: [ - SmoothActionButton( - text: appLocalizations - .edit_ingredients_extrait_ingredients_btn_text, - onPressed: () => onTapGetImage(false), - ), + _getExtraitIngredientsBtn(appLocalizations), const SizedBox(height: MEDIUM_SPACE), TextField( enabled: !updatingIngredients, From f11488e7b2da99d5d2ebe7dde28880a24db6bdd6 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt <47862474+bhattabhi013@users.noreply.github.com> Date: Tue, 3 May 2022 21:07:49 +0530 Subject: [PATCH 04/27] fix: Unable to view details of product after scanning (#1726) * fix: Unable to view details of product after scanning * moved the provider to main.dart file * cross button changes * removed extra instances of ContinuousScanModel() * added provider to async init * loaded at init * improvization --- .../lib/cards/product_cards/product_title_card.dart | 2 +- packages/smooth_app/lib/helpers/picture_capture_helper.dart | 6 ++---- packages/smooth_app/lib/main.dart | 4 ++++ packages/smooth_app/lib/pages/scan/scan_page.dart | 6 ++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/smooth_app/lib/cards/product_cards/product_title_card.dart b/packages/smooth_app/lib/cards/product_cards/product_title_card.dart index 77cef9ff5cc..534f304bd71 100644 --- a/packages/smooth_app/lib/cards/product_cards/product_title_card.dart +++ b/packages/smooth_app/lib/cards/product_cards/product_title_card.dart @@ -28,7 +28,7 @@ class ProductTitleCard extends StatelessWidget { final Widget trailingWidget; final String brands = product.brands ?? appLocalizations.unknownBrand; final String quantity = product.quantity ?? ''; - if (isRemovable) { + if (isRemovable && !isSelectable) { final ContinuousScanModel model = context.watch(); subtitleText = '$brands${quantity == '' ? '' : ', $quantity'}'; trailingWidget = InkWell( diff --git a/packages/smooth_app/lib/helpers/picture_capture_helper.dart b/packages/smooth_app/lib/helpers/picture_capture_helper.dart index 7ea91e7debc..1765d5e4206 100644 --- a/packages/smooth_app/lib/helpers/picture_capture_helper.dart +++ b/packages/smooth_app/lib/helpers/picture_capture_helper.dart @@ -3,7 +3,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/continuous_scan_model.dart'; -import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/database/product_query.dart'; import 'package:smooth_app/generic_lib/loading_dialog.dart'; @@ -41,7 +40,6 @@ Future uploadCapturedPicture( Future _updateContinuousScanModel( BuildContext context, String barcode) async { - final ContinuousScanModel? model = - await ContinuousScanModel().load(context.read()); - await model?.onCreateProduct(barcode); + final ContinuousScanModel model = context.read(); + await model.onCreateProduct(barcode); } diff --git a/packages/smooth_app/lib/main.dart b/packages/smooth_app/lib/main.dart index f2131260796..3f777da3b6f 100644 --- a/packages/smooth_app/lib/main.dart +++ b/packages/smooth_app/lib/main.dart @@ -14,6 +14,7 @@ import 'package:openfoodfacts/utils/OpenFoodAPIConfiguration.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:smooth_app/data_models/continuous_scan_model.dart'; import 'package:smooth_app/data_models/product_preferences.dart'; import 'package:smooth_app/data_models/user_management_provider.dart'; import 'package:smooth_app/data_models/user_preferences.dart'; @@ -64,6 +65,7 @@ late UserPreferences _userPreferences; late ProductPreferences _productPreferences; late LocalDatabase _localDatabase; late ThemeProvider _themeProvider; +final ContinuousScanModel _continuousScanModel = ContinuousScanModel(); bool _init1done = false; // Had to split init in 2 methods, for test/screenshots reasons. @@ -84,6 +86,7 @@ Future _init1() async { ); _userPreferences = await UserPreferences.getUserPreferences(); _localDatabase = await LocalDatabase.getLocalDatabase(); + await _continuousScanModel.load(_localDatabase); _productPreferences = ProductPreferences( ProductPreferencesSelection( setImportance: _userPreferences.setImportance, @@ -167,6 +170,7 @@ class _SmoothAppState extends State { provide(_localDatabase), provide(_themeProvider), provide(_userManagementProvider), + provide(_continuousScanModel), ], builder: _buildApp, ); diff --git a/packages/smooth_app/lib/pages/scan/scan_page.dart b/packages/smooth_app/lib/pages/scan/scan_page.dart index 88371070c97..16f770216be 100644 --- a/packages/smooth_app/lib/pages/scan/scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/scan_page.dart @@ -7,7 +7,6 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/continuous_scan_model.dart'; import 'package:smooth_app/data_models/user_preferences.dart'; -import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/generic_lib/buttons/smooth_action_button.dart'; import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; @@ -35,11 +34,10 @@ class _ScanPageState extends State { } Future _updateModel() async { - final LocalDatabase localDatabase = context.watch(); if (_model == null) { - _model = await ContinuousScanModel().load(localDatabase); + _model = context.read(); } else { - await _model?.refresh(); + await _model!.refresh(); } setState(() {}); } From 955895d7dfcf5725c616aaa0666336b0ee8371fb Mon Sep 17 00:00:00 2001 From: Marvin M <39344769+M123-dev@users.noreply.github.com> Date: Wed, 4 May 2022 15:38:01 +0200 Subject: [PATCH 05/27] fix: BAD_DECRYPT Exception on invalid cipher (#1730) * fix: BAD_DECRYPT Exception on invalid cipher * Update user_management_provider.dart * More comments + showing SnackBar * Moving cred movment lower in the tree * Moved back * Await user credentials on app start * Update packages/smooth_app/lib/data_models/user_management_provider.dart Co-authored-by: monsieurtanuki Co-authored-by: monsieurtanuki --- .../data_models/user_management_provider.dart | 29 +++++++++++-------- packages/smooth_app/lib/main.dart | 4 +-- .../lib/pages/user_preferences_profile.dart | 10 +++---- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/packages/smooth_app/lib/data_models/user_management_provider.dart b/packages/smooth_app/lib/data_models/user_management_provider.dart index cf22d3d60f2..b98bef334e7 100644 --- a/packages/smooth_app/lib/data_models/user_management_provider.dart +++ b/packages/smooth_app/lib/data_models/user_management_provider.dart @@ -1,4 +1,5 @@ -import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/utils/OpenFoodAPIConfiguration.dart'; import 'package:smooth_app/database/dao_secured_string.dart'; @@ -7,10 +8,6 @@ class UserManagementProvider with ChangeNotifier { static const String _USER_ID = 'user_id'; static const String _PASSWORD = 'pasword'; - bool _finishedLoading = false; - - bool get isLoading => !_finishedLoading; - /// Checks credentials and conditionally saves them Future login(User user) async { final bool rightCredentials; @@ -22,6 +19,7 @@ class UserManagementProvider with ChangeNotifier { if (rightCredentials) { await putUser(user); + notifyListeners(); } return rightCredentials && await credentialsInStorage(); @@ -38,20 +36,27 @@ class UserManagementProvider with ChangeNotifier { } /// Mounts already stored credentials, called at app startup - Future mountCredentials() async { - final String? userId = await DaoSecuredString.get(_USER_ID); - final String? password = await DaoSecuredString.get(_PASSWORD); + static Future mountCredentials() async { + String? userId; + String? password; + + try { + userId = await DaoSecuredString.get(_USER_ID); + password = await DaoSecuredString.get(_PASSWORD); + } on PlatformException { + /// Decrypting the values can go wrong if, for example, the app was + /// manually overwritten from an external apk. + DaoSecuredString.remove(key: _USER_ID); + DaoSecuredString.remove(key: _PASSWORD); + debugPrint('Credentials query failed, you have been logged out'); + } if (userId == null || password == null) { - _finishedLoading = true; - notifyListeners(); return; } final User user = User(userId: userId, password: password); OpenFoodAPIConfiguration.globalUser = user; - _finishedLoading = true; - notifyListeners(); } /// Checks if any credentials exist in storage diff --git a/packages/smooth_app/lib/main.dart b/packages/smooth_app/lib/main.dart index 3f777da3b6f..efd63bab281 100644 --- a/packages/smooth_app/lib/main.dart +++ b/packages/smooth_app/lib/main.dart @@ -84,6 +84,7 @@ Future _init1() async { system: Platform.operatingSystemVersion, url: 'https://world.openfoodfacts.org/', ); + await UserManagementProvider.mountCredentials(); _userPreferences = await UserPreferences.getUserPreferences(); _localDatabase = await LocalDatabase.getLocalDatabase(); await _continuousScanModel.load(_localDatabase); @@ -182,6 +183,7 @@ class _SmoothAppState extends State { final ThemeProvider themeProvider = context.watch(); final Widget appWidget = OnboardingFlowNavigator(_userPreferences) .getPageWidget(context, _userPreferences.lastVisitedOnboardingPage); + return MaterialApp( localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, @@ -231,8 +233,6 @@ class SmoothAppGetLanguage extends StatelessWidget { final LocalDatabase _localDatabase = context.read(); AnalyticsHelper.trackStart(_localDatabase, context); - context.read().mountCredentials(); - return appWidget; } } diff --git a/packages/smooth_app/lib/pages/user_preferences_profile.dart b/packages/smooth_app/lib/pages/user_preferences_profile.dart index 77c056279d4..9063b1b97e1 100644 --- a/packages/smooth_app/lib/pages/user_preferences_profile.dart +++ b/packages/smooth_app/lib/pages/user_preferences_profile.dart @@ -109,8 +109,9 @@ class _UserPreferencesPageState extends State { @override Widget build(BuildContext context) { - final UserManagementProvider userManagementProvider = - context.watch(); + // We need to listen to reflect login's from outside of the preferences page + // e.g. question card, ... + context.watch(); final ThemeData theme = Theme.of(context); final AppLocalizations appLocalizations = AppLocalizations.of(context)!; @@ -118,10 +119,7 @@ class _UserPreferencesPageState extends State { final List result = []; - if (userManagementProvider.isLoading) { - //Loading - result.add(const Center(child: CircularProgressIndicator())); - } else if (OpenFoodAPIConfiguration.globalUser != null) { + if (OpenFoodAPIConfiguration.globalUser != null) { //Credentials final String userId = OpenFoodAPIConfiguration.globalUser!.userId; result.add( From 21253c15db88e7dfaeacea51a51d25d1355b3e05 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Wed, 4 May 2022 17:00:30 +0200 Subject: [PATCH 06/27] feat: #960 - changed the attribute/importance preference display. (#1590) Impacted files: * `attribute_button.dart`: changed the whole display. * `design_constants.dart`: added constants for the default icon size and the minimum target size (according to goldens). * `product_preferences.dart`: added the downgrading of "very important" to "important". * `pubspec.lock`: wtf * `user_preferences_page-blue-dark.png`: impacted by new display. * `user_preferences_page-blue-light.png`: impacted by new display. * `user_preferences_page-brown-dark.png`: impacted by new display. * `user_preferences_page-brown-light.png`: impacted by new display. * `user_preferences_page-green-dark.png`: impacted by new display. * `user_preferences_page-green-light.png`: impacted by new display. --- .../lib/data_models/product_preferences.dart | 13 +- .../lib/generic_lib/design_constants.dart | 6 + .../lib/widgets/attribute_button.dart | 156 +++++++++++++----- .../user_preferences_page-blue-dark.png | Bin 7729 -> 7603 bytes .../user_preferences_page-blue-light.png | Bin 7761 -> 7669 bytes .../user_preferences_page-brown-dark.png | Bin 7729 -> 7603 bytes .../user_preferences_page-brown-light.png | Bin 7762 -> 7679 bytes .../user_preferences_page-green-dark.png | Bin 7729 -> 7603 bytes .../user_preferences_page-green-light.png | Bin 7763 -> 7679 bytes 9 files changed, 123 insertions(+), 52 deletions(-) diff --git a/packages/smooth_app/lib/data_models/product_preferences.dart b/packages/smooth_app/lib/data_models/product_preferences.dart index ddeba010688..cddfbce3cbe 100644 --- a/packages/smooth_app/lib/data_models/product_preferences.dart +++ b/packages/smooth_app/lib/data_models/product_preferences.dart @@ -6,7 +6,6 @@ import 'package:openfoodfacts/model/AttributeGroup.dart'; import 'package:openfoodfacts/personalized_search/available_attribute_groups.dart'; import 'package:openfoodfacts/personalized_search/available_preference_importances.dart'; import 'package:openfoodfacts/personalized_search/available_product_preferences.dart'; -import 'package:openfoodfacts/personalized_search/preference_importance.dart'; import 'package:openfoodfacts/personalized_search/product_preferences_manager.dart'; import 'package:openfoodfacts/personalized_search/product_preferences_selection.dart'; import 'package:smooth_app/data_models/downloadable_string.dart'; @@ -182,16 +181,6 @@ class ProductPreferences extends ProductPreferencesManager with ChangeNotifier { availableProductPreferences = myAvailableProductPreferences; } - @override - String getImportanceIdForAttributeId(String attributeId) => - _getRefinedImportanceId(super.getImportanceIdForAttributeId(attributeId)); - - /// Downgrades "very important" to "important" (from 4 to 3 choices, simpler). - static String _getRefinedImportanceId(final String importanceId) => - importanceId == PreferenceImportance.ID_VERY_IMPORTANT - ? PreferenceImportance.ID_IMPORTANT - : importanceId; - Future resetImportances() async { await clearImportances(notifyListeners: false); if (attributeGroups != null) { @@ -202,7 +191,7 @@ class ProductPreferences extends ProductPreferencesManager with ChangeNotifier { if (attribute.id != null && defaultF != null) { await setImportance( attribute.id!, - _getRefinedImportanceId(defaultF), + defaultF, notifyListeners: false, ); } diff --git a/packages/smooth_app/lib/generic_lib/design_constants.dart b/packages/smooth_app/lib/generic_lib/design_constants.dart index e595f53a1d2..d32ee8ad752 100644 --- a/packages/smooth_app/lib/generic_lib/design_constants.dart +++ b/packages/smooth_app/lib/generic_lib/design_constants.dart @@ -9,6 +9,12 @@ const double LARGE_SPACE = 16.0; const double VERY_LARGE_SPACE = 20.0; const double MINIMUM_TOUCH_SIZE = 48.0; +/// Default icon size, cf. [Icon] +const double DEFAULT_ICON_SIZE = 24.0; + +/// Default icon size, cf. goldens.dart +const double MINIMUM_TARGET_SIZE = 48.0; + /// Background, e.g SmoothCard const Radius ROUNDED_RADIUS = Radius.circular(20.0); //ignore: non_constant_identifier_names diff --git a/packages/smooth_app/lib/widgets/attribute_button.dart b/packages/smooth_app/lib/widgets/attribute_button.dart index c74e2db2ca2..6e5a00e853f 100644 --- a/packages/smooth_app/lib/widgets/attribute_button.dart +++ b/packages/smooth_app/lib/widgets/attribute_button.dart @@ -1,9 +1,12 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/model/Attribute.dart'; import 'package:openfoodfacts/personalized_search/preference_importance.dart'; import 'package:smooth_app/data_models/product_preferences.dart'; +import 'package:smooth_app/generic_lib/buttons/smooth_action_button.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; /// Colored button for attribute importance, with corresponding action class AttributeButton extends StatelessWidget { @@ -15,58 +18,131 @@ class AttributeButton extends StatelessWidget { final Attribute attribute; final ProductPreferences productPreferences; - static const Map _nextValues = { - PreferenceImportance.ID_NOT_IMPORTANT: PreferenceImportance.ID_IMPORTANT, - PreferenceImportance.ID_IMPORTANT: PreferenceImportance.ID_MANDATORY, - PreferenceImportance.ID_MANDATORY: PreferenceImportance.ID_NOT_IMPORTANT, - }; - - static const Map _colors = { - PreferenceImportance.ID_NOT_IMPORTANT: PRIMARY_GREY_COLOR, - PreferenceImportance.ID_IMPORTANT: PRIMARY_BLUE_COLOR, - PreferenceImportance.ID_MANDATORY: RED_COLOR, - }; + static const List _importanceIds = [ + PreferenceImportance.ID_NOT_IMPORTANT, + PreferenceImportance.ID_IMPORTANT, + PreferenceImportance.ID_VERY_IMPORTANT, + PreferenceImportance.ID_MANDATORY, + ]; @override Widget build(BuildContext context) { final ThemeData themeData = Theme.of(context); - String importanceId = + final IconThemeData iconThemeData = IconTheme.of(context); + final String currentImportanceId = productPreferences.getImportanceIdForAttributeId(attribute.id!); - // We switch from 4 to 3 choices: very important is downgraded to important - if (importanceId == PreferenceImportance.ID_VERY_IMPORTANT) { - importanceId = PreferenceImportance.ID_IMPORTANT; - } const double horizontalPadding = LARGE_SPACE; - final double screenWidth = + final double widgetWidth = MediaQuery.of(context).size.width - 2 * horizontalPadding; + final double importanceWidth = widgetWidth / 4; final TextStyle style = themeData.textTheme.headline3!; + final String? info = attribute.settingNote; + final List children = []; + for (final String importanceId in _importanceIds) { + children.add( + GestureDetector( + onTap: () async { + await productPreferences.setImportance(attribute.id!, importanceId); + final AppLocalizations? appLocalizations = + AppLocalizations.of(context); + await showDialog( + context: context, + builder: (BuildContext context) => SmoothAlertDialog( + body: Text( + 'blah blah blah importance "$importanceId"'), // TODO(monsieurtanuki): find translations + actions: [ + SmoothActionButton( + text: appLocalizations!.close, + onPressed: () => Navigator.pop(context), + ), + ], + ), + ); + }, + child: SizedBox( + width: importanceWidth, + height: MINIMUM_TARGET_SIZE, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AutoSizeText( + productPreferences + .getPreferenceImportanceFromImportanceId(importanceId)! + .name!, + maxLines: 1, + textAlign: TextAlign.center, + ), + Icon( + currentImportanceId == importanceId + ? Icons.radio_button_checked + : Icons.radio_button_off, + color: themeData.colorScheme.primary, + ), + ], + ), + ), + ), + ); + } return Padding( - padding: const EdgeInsets.symmetric(horizontal: horizontalPadding), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, + padding: const EdgeInsets.symmetric( + vertical: SMALL_SPACE, + horizontal: horizontalPadding, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox( - width: screenWidth * .45, - child: Text(attribute.name!, style: style), - ), - SizedBox( - width: screenWidth * .45, - child: ElevatedButton( - child: AutoSizeText( - productPreferences - .getPreferenceImportanceFromImportanceId(importanceId)! - .name!, - style: style.copyWith(color: Colors.white), - maxLines: 1, + GestureDetector( + child: SizedBox( + height: MINIMUM_TARGET_SIZE, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (info != null) const Icon(Icons.info_outline), + Container( + padding: info == null + ? null + : const EdgeInsets.only(left: SMALL_SPACE), + child: SizedBox( + width: widgetWidth - + SMALL_SPACE - + (iconThemeData.size ?? DEFAULT_ICON_SIZE), + child: AutoSizeText( + attribute.settingName ?? attribute.name!, + maxLines: 2, + style: style, + ), + ), + ), + ], ), - style: ElevatedButton.styleFrom( - primary: _colors[importanceId], - onPrimary: Colors.white, - ), - onPressed: () async => productPreferences.setImportance( - attribute.id!, _nextValues[importanceId]!), ), + onTap: info == null + ? null + : () async => showDialog( + context: context, + builder: (BuildContext context) { + final AppLocalizations? appLocalizations = + AppLocalizations.of(context); + return SmoothAlertDialog( + body: Text(info), + actions: [ + SmoothActionButton( + text: appLocalizations!.close, + onPressed: () => Navigator.pop(context), + ), + ], + ); + }, + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: children, ), ], ), diff --git a/packages/smooth_app/test/pages/goldens/user_preferences_page-blue-dark.png b/packages/smooth_app/test/pages/goldens/user_preferences_page-blue-dark.png index 83e045c356e1708312ea4bcdb2d2216f8ce7dfb5..6a1c5f722db917ac2952f8f6fb165e7d22c5dd12 100644 GIT binary patch literal 7603 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 toLwHL7L;P$d;Hv=e;QeI_g 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 S(M8d3%AfVs`5!9ffprSyGGK4ABs{|3Kmnt9u zEQ%-;QluCZ0w|M~02dj8GDPMv1cW3&5^{G!Z+}#Kdu#Rm-h26HpX{8Iz4qGQ`qsDB z3EyLHy?Eiug#duXHaju<0FYe`fXu=9^We;F-%CDlKoIs>ZwFb`YW?ub9Kv>+1M}f0 zX#NQ@0ILKxm~99ADeP7U@?p88rqN_ymy)OT57JxDMBtjgTurkrJgXnpfWy!fo`->KtONXy*3nR_@8|&WO{n-A^k-FQA=X|+fO{@)f$I{Kmc6J%K**-{R z-->-TygqDO(hAdCj@0xJ>OlV(nlGTcitqu2A=LW{qP{m+U0DEDKXW}mhvtp&maGQA zawS3rfP2W#dFia;S8O2`x$Zt5{m?mYTAYq+&vh3~US3}{Wl;o*`wk-z0KA&N1lke_ zKF{Tb1N7p8$=)JyMmiP%(v$9m^8xtQiUjw0dXD6>=bzD8!Q4j!U%_8#m$g6VcHj5i z?XQue|7oGySK56Jauon5KJG>fubN31R(m2GUq9P4Ghm{N;9_2D! ztudv69J zUNo_eCxnbVlN+rz;am?ojG3%JSEDoZ9H?o8=@B$5R4lp?9YLPxN$~Edy=$FXy`mjo zSl#^YbuYfKt$-fZ!={|HP$H?h$-U@J4pndU^6Tm}7YyZ0jMq6>n`f=PMkep;6?R1E z9zS>PTvsRRXNzilweyt#qFLftSWUoaN15dB{m1+EQcV1^>d~5})y#lH<^nh*(D?r> zNX!}XkomSmdP*Np3(gOS-#itty+c)ds}ofx^HSELP$|vqsGuQb*C3>)r>CZd8~}Aa z(#Uil(q64)PnqBqHAZ)|`mr`%YzbG=LZNI|HJ>uDGVh758N`PatyfPY6uw4Ro-$ae z-m6L>;M%_SuJm}`{LUzGtg3neBkSvu_K}kfcF^8rwSiTUlBWZ8mTzP1< zK955R;x=GexB-o_ckj-dh6w$;I&rP`BZibQ5uc?onMWpj7f!BGHzOVxpdiP_T4sgW z-}#vYCqH{mbAMtTK~T~=&bdiUtQ(vpj`8C6@VFG~KZqw<2Sr&IrzZJ->uB||Cxl+x zME&C-NzJ;26R5_Fv53WB!=T9J9yY> zPccFw_r63!;Eqad$-qIt`J2p~|0gZ>7jZ8iqsD`@9nNsZ;gVjc0dVy3E(1&G8%&Q- z*lUqIGxZBTYqeL04ry6TzT6oqPGAY$Z4)3RSA0t%$;NGh34e~%QRNXwt=mr`l7o~XFVxf_Nnu4nneGV8)ZS`_EVPC|O z98*u&3<0{aE^T=zUN}$qqm7t(TrAvtjT0zdwqw&PiWki!{33|kUnnb6d{75hVDyS5 zzl20f_)Nsfp!wz>;VuLWq?9;k=vP9VR*f8f1`a_&&z7rFwsh1*08p^%b17vgj{(@_ zLS;r|V5wGcz)`VWV?fAkI8!z?MO?ZAsjPEYC9v)LcAts!GJ%NVU40jfYx^&x<7DsL zGTgegvpiC@_DrsA4J;Yz%XvKCv**s0MMu*$I3huE*$p169DZ@-x&Q*_j(BjQmDga@ zCpMNm*qC`J)nmaDaORk|x2}DX=?bxtkU7y;uk@jY%N-f0?6JU2-|5&51_pI4OqU^% zCMG7S9ul;?jTAn>8=yi$n?0T14}ASb-R~^|-u-R3jc&sG0xCNs5+|P<26|5xg4i$P0p>ue7i~za~eYi_S z+wyA3v6iCH(4nss6ckXXju$sHd*bx@1Qg0X+1!k`h!pVSQ=>-lcN0pS4N;+P<>Fw& z_+WQ7K7NcCLu`FHlfyqLxTJ?$d{3BgH>}e_Ty?&|6Hvdj1f(|yj~ph8$C-AHR7Anm z53uYOEY}4I4&VPO)rKtt81Y5ZVY(2Far!f~AeGCrWRCRGyUVq3vVu%LWtbp!_?ctD z!DcAb)o2aJf(4erqB?QF5@hHEW8>E(ut#21Rkil4VdraauZoBYS4X;n7q^)7iEALBZb|`VXxPDH zH_renwXPqNR`-y&nB?-NsfnDh)!QngVZE7TVG}w|H|y||FW}(o>zj^~JDRm6q3WQk zYjn!m@~7N^Wzw2=^s5U{KK)nMOPQwl9+ybZBXZA-6X|_iq9avSkLi-xNVCBBw?Ds< z-8=c^c5r64MJ+AYRkwO!{%w(Jb8~ZcZtk*3E6q1-Uo{io4J#w98axpU`m>`;L?IUQ zE^j;Q!1&p!hZEZM;X~1TPsg9x7InQN}E*x&nSHApgb(U+9`i{Nd-EOz* zgSRD`_#KCV<%GqS$rXS1Q!|@P?(@x`Ihyu{*eW5qfrQ*tjv$Ob(z>Sx52> zZ=j(diu9;Ss$x*&6xB<+D`P8?^gU}Fj%dW9saqd1=~?9qziszXfrX+*VEEoTIi=qLBX- z4-g_0bW35#-PPP25u@c${_NQ{ zidmqOKiKt*9>_lqeZU=L-d%fbpMKDSRV0@@La+T0n_V_AkUjz8{^6Uy3W;p>qKz+t z4%%2S_2>zlO@dqhO|npf^5LVBMfK8N2wyZ|&8=Iv%9CU*w|qh z(W6IS^wuO(iHqabc|DW)ZCCC(ch$F@710%`cCl-6<-v%o`D9m2IyUZfl15zcALa;H zc_NXJ`R$~7;W<1M_`7j|h)jmD zI(}VJ*mvJsE<;*>&fB}9vC+w3Wu(!?fdduOJrnZUa-J-1}^=xgbPd;Jyi+6 z3Kx4Qe6+Dy7&s&*CZ;nHah`DPMy3Qs*a1tWkA0b3EZD#GgSUWttI)>FY0v7%vekc7`* zW9F+Isk>-2Wi5xK>yS;20(n1-fVfM6{NXYfGJ{O2_1>ka?h{`agIph2LrB7=p}}z! zq4yQr*8~NtIfnrs3(1Z_0IQ^LU=>5#^{)6lG(05%n zE%ZRYp|4=GLKAfykH@c(F!`^c0Aen%-@twbnmB&SG>~`Jy~oslWVMcKp(&5z92hb% z^^0V>xW$RID6AweR6N~er>3Tc!Ia+6w01vkk12)7s7OM9n8%MEZ6@Tb+2rBp=O>fE zXdBzltT?Re&1Lt=^_5X>`ZTP;LOE~TO>sfL_QRXM{S*)oH~S)V~|Ak z%iiyR-OetQJujRX&AZV5>YgtGgcNHf2kql7)UO(o&8hkQCgO}5E$|;jp-{K0+-H0* zksxF;j5w@BEtv&R8K9;|;tyQ~h&#&-4GmLXpDiCA&YF*i`$tHT1`-MLe3G;hqttH) zds5kKcGH_T*R1X$)9e$kb$55ezL+C*t{xw%2N*gki{@p+aH4s$bj<9a3erxr*D_AD zhjOs~l_Xsh1n9eDI!O(A)6XU1yMMk3rA&5C&VFer0N0k50-G8$vDBH$>rd92%hPcH ztjUBarXd4+mpQnD%FH0HB0Xt5lUpeI^0~aS&ULdIMWoDcEb8fTZ^^@J{%TQETU%6S zW+vQHtrxAcDch~~ltDU9{^;=Hd6)b6f=w!mjuQy_Uae0ZiMJ%~;_-MLT`yzsut^I= z$TD@X--pvihd%h-S|a=D)Ai=y{=HT&YYc|gyiqC><*9{db>M8;>$6svQkWhkzJXl_ z%`iocC^C!1bAcR=<}s&1Y30Q)OeHrz*I<79AiwDarOUPg7~#jQ{K>jA*HUr^x^)rlvXb+ z)cNN`1K1+ikA`nM2K@hLb<bZ#OqhueO2}nNAr}p}>an zKJR?DEgYa=ekcX;SwlBi<6KKo8EnkJN_nL`_Mfm%_1C(nmgrf%Uj*=13cFg;UYQ;X zte9Rjt<7mHj>8EBP@M4Z7YT=cT*Gxe_KgNF7^@9!IBidBPAoMBKyz%>k_W%MGJ&9d zaP5Qo?)~yt(^8`J{$N&;(TXQvdD5T_dk^pRD&l5dnE+rl)4-ph+5a!SivQ&VJ0YIG X`i8@aoUQkvzyLNo>@iu}k6!v0sfh3d diff --git a/packages/smooth_app/test/pages/goldens/user_preferences_page-brown-dark.png b/packages/smooth_app/test/pages/goldens/user_preferences_page-brown-dark.png index 83e045c356e1708312ea4bcdb2d2216f8ce7dfb5..6a1c5f722db917ac2952f8f6fb165e7d22c5dd12 100644 GIT binary patch literal 7603 zcmd5>dpMM7|9^D!>L6PYa@f3OJ1i^5Fvd!Bq!0-+MIjS%9;Y$8rKS~Qe<>M&#%7F@~AnjoNMZx7YRC-gd9+eg1jwnd^R@`}F-BzTfBiaSQWx z5^@p{1g$%C(9{ZomMcThvQy%#z(0h*A1{HMn4guo36x#CbrAem;b(HlMjTvW;^%M> zq~LVO^m`k0(rA~Zds0xy%L((0k)w`@Hnuvx2aPX2rhjw0T>RRWutW&qOVORV~jJbLP zPOT=VR=`i{=efCJLd==fndsh`3Dzi>&cW~6+3Uc4`fFnd!fGvB0sd0?o0=|NYcV6a z)ShNLBv2=e9hchvlPUMEl!yifHC`~mgFLw1=BMm{ZW>_%)3oFFGv{^Ar z{$W?}#|e9ux)H-)JTHQvyAmr7icw~pb9xFW^PZFfF$lW#i}W4{QjUf|yTO06a%gDi z`O#E2E{}I4F;jvjbM;UHoC3W(vt@BD%tSE3p;zCYf*@l#v1JhSKuY=VZW4aRx${Cd zg4e=kR{h}+HCry~2*|6!N_K=T|7V8(f0sqb^;$)%sVOh=>#uCDBJT6)F*P;4=SzBchrl{j_Ii=D$?9W2B#QX-&7#qZv|J7sS_7?Ki5Qpn8A%+1TQew|&sHg;lS z;!aA6+IbatFL-K>5>PEF%SKWdc|~MOpHeShB_vcRc6Vrps;UbHQyN#)LZ=^Dv!UP& zII9cAvkRN^=xSG2S8GRyL7j`axp`{6`_wt5g~<0f6CAuxM^{&JsDJSr+`o?&8IxN;4^+`o+>=#2O% zn=RSv==EwDg#G$?e*R`ZKfifK1#x2Cp9Z%Xp~e*e#nN!X^adUuUqpoajI`$Ba5H_0 z-qj+Nz`($s+GGP*LWck){5}PKzo1_U8i>wbSm|By5BnhuGQNHLwzISI{qaH?Tx6IM zI#%?WRVthvM$e3&{kA2nKRHMOABEEk7_uputla$=#oez<%TsfEbQo32V}wqW%OE!? z%ACj=j_v1jGNufNpSkL?RbQqSuaDJbpjFl@89Aamn=|cLBW-z+)X}jqGt(yL8Vi^A zY4M1k($dnJv<3GP`(;nyHEq(g*V`E-P20_{5dJvTHZgFTrHbtx`VAvMybC6bcv&Uw|AOUxDi-JN{IU%_?T=1fw zugMzny_)g7&kh-W5?#&9@K=~Lj6mE6>4HZaSFPcJTv5m(Kj};@Qt3ZNSMX ziHT8u{k6C921*>^!K}?P`ms3`ew<|aF+arUs+%Lx8@D4#G1hL%S3d~^({(D z>VEKup4MC!DXEDXUFIE;`N+t~n`DEakiEa#m+t11U?^x)_o9*ns{IoLc6Xl6i$LiY zkR2LP0uE}{Q8rtfOoV57(63l9X}gB>jTvZGv|iZErEVX)97J@U8%ypT`)$B;SJMDQM<{PBAndGR;8gOYCWA$>&b4JY8TECk~6CM4>z}r*f=q0 z8BQCA&OKD?g(EVKw=5styMJ2)A*LSb2 zt!;5idY2b;IU~NbDc0?}%J}xKu4pou47AMO zUrR39EawFP^jciX%C~<6ZDtk-@a6a2#P+TQ{TvG~-5W2=&1EB6E@PJ4Z(vHMSh_+c@qvzcO zJp<6Nopycv6<8$}zE12johwWbUne6i?dXN*rK5Qds{&b*I~iK*bw;7D{QAi=iF zT@W;7OIvo%$0yg$y6kxH>|nZ!r)L(k1Bmqp%wAw(N7(Fm?URrF0$3n+7uJH8mz4#S z8c2f0v9@g+V^Wal>ZgoO9{BjWe170#0;|*aw z5|WZ`+`4ruyZ=H#M{aSkoPmMC_7Mqe25>K%_5xA(BtkqMWi= zC1S5hD&5YPd=FKYIF*Cd6gf#?_bzG#MHifT(`B%d&kWelQTQ+Et7+R}dh_PZ+-J`k zrVU2}4Q%b~T-@B!uQ-8uUw+U8B@l_~=d-7$0~WHF{co47QA4R%a1%J-kQu&UK4yTCcV<_=Mv<6p+t zzy}X$SeovGv&$a1i9IVR*_xP`2!wiMA;4STOilTB`{4C`dk>nL0#&$2P~Fxu z&ttMf*5~8}S98kd!V=QuYw^L=*7)FUmHc3(9ZPQG6RrN7=8b8Op2*0^I|&K<>Ri$v zJ`BkRnerLz)E;AC8A7$Sfq^-(G(eoRvOpj>f9&LtBd`zezZsQ&vJ@G+QTo5przXIC z$2n7iaSk)(lNI4mzCmHXm_be3)Acp=7+ z2BuaR#`iTxmCj98X&4wdpdEE{JmC!5uH<{q^rFb}4*A-GaOoc$PYRN&2xN!6O1j8u z**RzDZ6H<9mkVW8MC%1lo@+0};f};z*N}=`eIsGod!9{g<5_P@JNL?`?#WP`LI~IM_Pa|5|5BHQuO}tvI zv`KEG)I^JecN#25ml>8}w&Zzi9Ta?X}3=|_G`b_AY=cx*!38YAlrx*qj zY^YMjcvYOF@=!HDy*5TWhFU}sUbE^e_GMXhl2~)r3fZD*<&Qm9KT@TOLVzHA_i~J# z-_tF;ykHA@)$jWZxZ{IX)G3HrNf}`uY4#KK1qGrx>da)V()y{^bmC0nOg}}yQ)G)z z778U*KXy~Po8l{OR|fl!E>mMwiM){|$X_+|sV^?LGJ8$rFE=CBS2Ib2F%X z>^y4+SWJ1RwsBv7|B(b#c(@agwwD`x7c-=X&%KQm^FiVOie7-92L{{$-@Ha8>G^C! zgpTIFW+?_t4bOw}`ZjS(1Ej5d zD->evt#9eeK+t!3he<1egeMExULuW4KH?`Sg>HOIob`c@P@ zyZo_rdPBtlQ=mHs7BY@(C7K_Yni{gSv!0+%ne(l#t(8`!*PuG^yu8D1kM`6$vny;p zYcRwE%683|{%5Z2mM4?blsG8i&K(@6%fwVL3Vl>8QVbJx)VB2i_pLxaJC9BwhI8$y zlqoVO5c$kb4Zda-2YU)8Ft&qhZT2=}A)5&n{QWmde!8u$+!2b&w9#jS{z z-_E|O?o`a40bqUf$kRO`4%Kx-%Y$X{!g4 z3CiA}gycbMTu|1=1$nF|Fo${eC7AgTM^a$ck~o^av9^Srbni?jV&teX3PEesfSQaV?~#gm4EP|B*}T_Mvi~=xXYl^O^u_&OqP8`sa&{m-Eyde` zY#v&5@MD?}Xn*t4mz`r5#6Y5lY_UnJ1?B&>F%4d?+S}WIDk>^^_7L>C8oLCsPi?@T z*9N~_;J@OgE{wCqEeI%&>X&?Z!KH>~Owt;c;rNu2(1SrmE$`=qOyF z|Dct*_bGTvKluFBGNB%xLlK4~8HE>*7kVK&FeSv3`uorONQdga@IY||ds5&LMz`bR z*F+Zub6lTyjNVB~+M_jAd26>1kbt;+HAKl4rLghu?`cR$d6TDY+c_be8r?O~*S9cu znG$ZPdp>3u3k(+bl`_=Sn4sx)zwM&59A~tEY4#>aw7mcas!h-HEr>>4_38=gr8CY$ toLwHL7L;P$d;Hv=e;QeI_g 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 V5!6_$@)T|nIAMZD`}abW>UA7&G0$V~L92z} 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 literal 7762 zcmds6d03L^+JCXdno6TZOHCU*l`~dSI_`=!sI9hZYN1JKS-C`Rpx~LN2{pA&Q*Nk@ zPHArBVGK)&%C%G+7u0gcf)sZIR8+nPY}%)9=G3{a@A~}bL525yxS!v4-*4D%JKF_c zseJ`O(1NX7(0d_h#!3iMI5=lE_)EP14?bXl;r7~YhH_XM-Qbs*xXoMl&jCNdbB>ZB zXvM@<^rroRl)lzoyEtC@w zEbGj&=W!3Qj>3!{aYmA5GLG3UVQaNa}KD6&6j_vWL^BHH&Xej z=m^^k+}(SwgVh%-z~8AR4as`wLL5709ysW_w;;Hzzuyau&dSM&ms(g(jdqQ`OpU&| zv6+8zYHf9NY`;Vc>gnh#y0AEocIS@aWfM4dcKOs4v4u$@$v)iZLRtZb4=}_@W9?l< z$|%aSQ&j30%^c-+Z-4})pTqH3JCE8i+mp*FbLg%BYhk7L6ciw+@wJbdC6}j&PB4zj+Rp{%+WibrV`NC5e?iYu#G|D$q+gaJJ%83b2=dHmA8=qi z3doo38Y7J6KSi63G>1A!( zcPkVdl`BKC>k_Yr;4-xrC(Ty6gb3Mmy3<9spdb@X6w!Rxm+HmS!LgJrM_0B5@e(gb zN9ah6%S=3$a=V3RSz4An$p8~I>t`6rTNrL$8`KZ?@6k>iHmuxMD?-!6deS@ zO}0lYbCeTt(Aimi%ou`V4X1IBb%B}qa*FBFJmQjp`x38PU3L^>IDAh}lTGS|;SHof zOte69V8}R8P{nezNv#<)ZttK7hBfidmW$i2m333R{q0=+SEwmn(96Vtng^Q6Pxi~o z%3oyFye^H27cnlS=MBOc-EzOo>Maik*s;@B3l4(VACH zJ&GsH=~}^qn+gRiGi@!^&JaF@omeOF$MZ&7rUp$W2{$mj5&ZqO!jRQJhgk4xnqb3Y zyyUWmhKBO85YbbQq3*QgsNh3;mcZfOB_?{9LSq>(qcttULG@o<-z9j+8XRC`@Sz{Y z**NYhu*yZS;8#Tu-`mw&%^oYZ%N0yeCO>_qFUig}N zFj(CoW(*wOtG$wNojor{L-4_&;*4!viIwwAcRVBnf*e{tAiIQ%MQF$68E z{-x7r^xr+Jz+LF)KL2Kak;U&v5gPLG5rDI#a>|PrFTyH;b-7odXB-8JhQJX;wB(&f zm4L-KxBM^*cu3sKrI%16U0Tw>Uzt)Nm1J>aC)mB?hCIlGAnM&h(gPNEed?ylO247O z&Y}#5*sb6?H=;5n0!LBMH<|s_Ypz_KoSGSmvJRaH1t2@Xc(kKOEcw_wN@9M8{U^zZ zhRlA*94*ni`JI|)TC0}>Ljkh-YFdo<6)5agwcfLzu{k@?Qfg2=4|)X%dj@c|L4Til zD*v6R^f?jC{g<9uP%KJW%aT$~$;-cx4EoW3^uNH5=2~2X=vD5=?tqe6IJy z_&WgFcvmpInn)__%&Dr<`p-#`5n#k%# zUg%8rw-(=rLc7(Qo11g*-d&C|6%h-?MyN>bK4!Sq3Ieky58}3Mk~$1E_htJ2EPoGHw8mG9uF}mPoU92m#!v(u$X?{!NpKoGpxAOTVb~gX{z%UncVdB z={K^yfn@!>-5|=Qc)*LWZoBOFw{w2!_^OdLyON4q3j)e8Al#u42o+V;stq3fJT#hO zf?Ewlwlrx5l0PLOO$2NRlcJcZS<%d3eYW*GCSj2=J8vzy-R zfIy_^gxBgTEx1q=bH!;6l<^ybu_7TMVJHJFZg9?-xL{{R%J)SFH%1~94V zKFbmHHQ(@h|9?<~9#Vssj}h2^I#13cd-~DU&@ex-duYP(D&*jzZ6| z%064r`qIDP02Q`-ySlo%Z&zvL>m6YU1T#Y;qtu$?=z`WLY+00bYE3$RUFcn-W%EJ<9t0mMXvS0kUcTG= z$3=R4P%02`s-I669p33%0jC6!C$J?Xm= zp;SK9Rn}E|WBZk7v!GE}a`5n0wr-_CwQ{B9Cwg|HVNOW|nS9(ZVY>E5LP9JMh$IvV zGqf5K3P-x@$fJ`UUUJ5~JZoBW$`Bh6;P4}~V=Gfu>0DI*7=zx z<_8Jfe{;&N)tCLNjxXdqxvE>k7rJ?Pq{(4RdwNkQ1ZwM+~_V)JfUJd`?g8tFY^~zHM zv1dHLGKjI2(eL--3ynmq4rk}&*z8#X6iVMZ6avorQ7U0a@c`&Q1cj$C14yUgcX+tsf`}SH)43N-w;erMx(@gh{Nm>Q6 z!BsE1daD<`=R3&rR$X^-Rf16}+jBZLB+3*#=TI0}%*@OVP-h?;0UolbRNFmEu&sDu zxE%STi%kDY*p`*&iKhZ_KIoW6(Ki4!M!O(5jf#+<_m<&;$0=u(I0TS_n@5iwTg6I7xd_#e`#x}<<$SZ1WzkyE+hf-6 z^i+j96oZE!uQ@Z*+qUq9# ziV7g18JKyl{R@B{h$TP~Qvl-on(5o+d3zhZIns;nEL4N?>OpMcRwdMU=54E%#WFh} z-MS7rXs{$ECdy%3<*wh*C<_+3UJSfU8=w;)VEmOqy=?gYC#{9BPZ^Gp_Z39)!ceDf z|ALx6|4ht`>(^wkE{#-wy`$1Mjt4SKS=5RMo76o*CkW?_T!sb?2_P;@RQ!hQX~(+_ z;0==eMUX0t38Jh)DE0>+)Fps6{6-m{Z@9~NoaX~(k+LMkW*-=WAy)yCArN=&+?lSz zqfEVo2<6c36NU+JcrJ~$5C4=@U5ryHxkzkjA-9OG?DeW5lLs%Q7~cmn;EkpP5;2R~;9Rb&m?qkRAlua1y7X&kU+sWcd%B6304;mon@qu}zqL;`BK$x|!N*(fhZM*& zMRwu%rp?f5>VMN9Y~&nzYr-MZ9Ub0Vk5WLd%8{|#QMl;A%V&KeGVi@NnKAXKB9=<@etp zqw#~$={W^d2!AW;cB!n5-8TuEv851X!~N>bV>5aGc0dnsrf|h4RPb*-Ui?JFEEyli wFR_NpQ)ZhyASe)E4|af#>;JZ@lu8xtZ(k~{-11v9kX2}_wH-QVv+EE414C}|bN~PV diff --git a/packages/smooth_app/test/pages/goldens/user_preferences_page-green-dark.png b/packages/smooth_app/test/pages/goldens/user_preferences_page-green-dark.png index 83e045c356e1708312ea4bcdb2d2216f8ce7dfb5..6a1c5f722db917ac2952f8f6fb165e7d22c5dd12 100644 GIT binary patch literal 7603 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 toLwHL7L;P$d;Hv=e;QeI_g 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 From b55b6aa8d1e0147f71d19f202800d89e119f022d Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Wed, 4 May 2022 18:02:27 +0200 Subject: [PATCH 07/27] fix: Black camera screen (#1732) * This should fix the black screen with the camera scanner * Mark two methods as private * A few more comments * const constructor for CameraHelper * Update packages/smooth_app/lib/pages/scan/lifecycle_manager.dart Co-authored-by: monsieurtanuki * Update packages/smooth_app/lib/pages/scan/lifecycle_manager.dart Co-authored-by: monsieurtanuki Co-authored-by: monsieurtanuki --- .../smooth_app/lib/helpers/camera_helper.dart | 51 ++++++ packages/smooth_app/lib/main.dart | 7 +- .../lib/pages/scan/lifecycle_manager.dart | 63 ++++--- .../lib/pages/scan/ml_kit_scan_page.dart | 173 ++++++++++++------ .../lib/pages/scan/scanner_overlay.dart | 6 +- .../lib/widgets/screen_visibility.dart | 55 ++++++ 6 files changed, 268 insertions(+), 87 deletions(-) create mode 100644 packages/smooth_app/lib/helpers/camera_helper.dart create mode 100644 packages/smooth_app/lib/widgets/screen_visibility.dart diff --git a/packages/smooth_app/lib/helpers/camera_helper.dart b/packages/smooth_app/lib/helpers/camera_helper.dart new file mode 100644 index 00000000000..25421e567ae --- /dev/null +++ b/packages/smooth_app/lib/helpers/camera_helper.dart @@ -0,0 +1,51 @@ +import 'package:camera/camera.dart'; + +class CameraHelper { + const CameraHelper._(); + + static List? _cameras; + + /// Mandatory method to call before [findBestCamera] + static Future init() async { + _cameras = await availableCameras(); + } + + /// Find the most relevant camera to use if none of these criteria are met, + /// the default value of [_cameraIndex] will be used to select the first + /// camera in the global cameras list. + /// if non matching is found we fall back to the first in the list + /// initValue of [_cameraIndex]/ + static CameraDescription? findBestCamera({ + CameraLensDirection cameraLensDirection = CameraLensDirection.back, + }) { + if (_cameras == null) { + throw Exception('Please call [init] before!'); + } else if (_cameras!.isEmpty) { + return null; + } + + int cameraIndex = -1; + + if (_cameras!.any( + (CameraDescription element) => + element.lensDirection == cameraLensDirection && + element.sensorOrientation == 90, + )) { + cameraIndex = _cameras!.indexOf( + _cameras!.firstWhere((CameraDescription element) => + element.lensDirection == cameraLensDirection && + element.sensorOrientation == 90), + ); + } else if (_cameras!.any((CameraDescription element) => + element.lensDirection == cameraLensDirection)) { + cameraIndex = _cameras!.indexOf( + _cameras!.firstWhere( + (CameraDescription element) => + element.lensDirection == cameraLensDirection, + ), + ); + } + + return _cameras![cameraIndex]; + } +} diff --git a/packages/smooth_app/lib/main.dart b/packages/smooth_app/lib/main.dart index efd63bab281..5a2ad00394d 100644 --- a/packages/smooth_app/lib/main.dart +++ b/packages/smooth_app/lib/main.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:io' show Platform; -import 'package:camera/camera.dart'; import 'package:device_preview/device_preview.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -22,12 +21,11 @@ import 'package:smooth_app/database/dao_string.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/database/product_query.dart'; import 'package:smooth_app/helpers/analytics_helper.dart'; +import 'package:smooth_app/helpers/camera_helper.dart'; import 'package:smooth_app/pages/onboarding/onboarding_flow_navigator.dart'; import 'package:smooth_app/themes/smooth_theme.dart'; import 'package:smooth_app/themes/theme_provider.dart'; -List cameras = []; - late bool _screenshots; Future main({final bool screenshots = false}) async { @@ -103,8 +101,7 @@ Future _init1() async { _themeProvider = ThemeProvider(_userPreferences); ProductQuery.setQueryType(_userPreferences); - cameras = await availableCameras(); - + await CameraHelper.init(); await ProductQuery.setUuid(_localDatabase); _init1done = true; return true; diff --git a/packages/smooth_app/lib/pages/scan/lifecycle_manager.dart b/packages/smooth_app/lib/pages/scan/lifecycle_manager.dart index d5473df6478..4bea44ad9bb 100644 --- a/packages/smooth_app/lib/pages/scan/lifecycle_manager.dart +++ b/packages/smooth_app/lib/pages/scan/lifecycle_manager.dart @@ -1,19 +1,27 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:smooth_app/widgets/screen_visibility.dart'; import 'package:visibility_detector/visibility_detector.dart'; -/// This Widgets tracks if the child is currently visible on screen and if the -/// app gets minimized/resumed by the system +/// This Widgets tracks both the app lifecycle and the screen visibility +/// [onStart] will be called only when the Widget is displayed for the first time +/// (= during the [initState] phase) +/// [onResume] will be called once the app is reopened (eg: the app is minimized +/// and brought back to front) or this part of the Widget tree is visible again +/// [onPause] will be called once the app is minimized or if this part of the +/// tree is invisible class LifeCycleManager extends StatefulWidget { const LifeCycleManager({ required this.onResume, required this.onPause, required this.child, + this.onStart, Key? key, }) : super(key: key); final Function() onResume; final Function() onPause; + final Function()? onStart; final Widget child; @override @@ -22,29 +30,16 @@ class LifeCycleManager extends StatefulWidget { class LifeCycleManagerState extends State with WidgetsBindingObserver { - double visibleFraction = 100.0; AppLifecycleState appLifecycleState = AppLifecycleState.resumed; - void checkLifeCycle() { - if (appLifecycleState == AppLifecycleState.inactive || - visibleFraction == 0.0) { - widget.onPause.call(); - } else if (appLifecycleState == AppLifecycleState.resumed && - visibleFraction > 0.0) { - widget.onResume.call(); - } - } - @override void initState() { super.initState(); WidgetsBinding.instance!.addObserver(this); - } - @override - void dispose() { - WidgetsBinding.instance!.removeObserver(this); - super.dispose(); + if (widget.onStart != null) { + WidgetsBinding.instance!.addPostFrameCallback((_) => widget.onStart!()); + } } // Lifecycle changes are not handled by either of the used plugin. This means @@ -55,7 +50,28 @@ class LifeCycleManagerState extends State @override void didChangeAppLifecycleState(AppLifecycleState state) { appLifecycleState = state; - checkLifeCycle(); + _onLifeCycleChanged(); + } + + void _onLifeCycleChanged() { + switch (appLifecycleState) { + case AppLifecycleState.resumed: + widget.onResume(); + break; + case AppLifecycleState.inactive: + case AppLifecycleState.paused: + case AppLifecycleState.detached: + widget.onPause(); + break; + } + } + + void _onVisibilityChanged(bool visible) { + if (visible) { + widget.onResume(); + } else { + widget.onPause(); + } } @override @@ -63,10 +79,15 @@ class LifeCycleManagerState extends State return VisibilityDetector( key: const ValueKey('VisibilityDetector'), onVisibilityChanged: (VisibilityInfo info) { - visibleFraction = info.visibleFraction; - checkLifeCycle(); + _onVisibilityChanged(info.visible); }, child: widget.child, ); } + + @override + void dispose() { + WidgetsBinding.instance!.removeObserver(this); + super.dispose(); + } } diff --git a/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart b/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart index 24c2712ab06..b985b761c01 100644 --- a/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart @@ -6,31 +6,55 @@ import 'package:google_ml_barcode_scanner/google_ml_barcode_scanner.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/continuous_scan_model.dart'; import 'package:smooth_app/data_models/user_preferences.dart'; -import 'package:smooth_app/main.dart'; +import 'package:smooth_app/helpers/camera_helper.dart'; import 'package:smooth_app/pages/scan/abstract_camera_image_getter.dart'; import 'package:smooth_app/pages/scan/camera_image_cropper.dart'; import 'package:smooth_app/pages/scan/camera_image_full_getter.dart'; import 'package:smooth_app/pages/scan/lifecycle_manager.dart'; import 'package:smooth_app/pages/user_preferences_dev_mode.dart'; +import 'package:smooth_app/widgets/screen_visibility.dart'; -class MLKitScannerPage extends StatefulWidget { - const MLKitScannerPage({Key? key}) : super(key: key); +class MLKitScannerPage extends StatelessWidget { + const MLKitScannerPage({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return const ScreenVisibilityDetector( + child: _MLKitScannerPageContent(), + ); + } +} + +class _MLKitScannerPageContent extends StatefulWidget { + const _MLKitScannerPageContent({Key? key}) : super(key: key); @override MLKitScannerPageState createState() => MLKitScannerPageState(); } -class MLKitScannerPageState extends State { +class MLKitScannerPageState extends State<_MLKitScannerPageContent> { + /// If the camera is being closed (when [stoppingCamera] == true) and this + /// Widget is visible again, we add a post frame callback to detect if the + /// Widget is still visible + /// + /// If the time took by the "post frame callback" is less than this duration, + /// we considered, that the camera should be reinitialized + /// + /// On a 60Hz display, one frame =~ 16 ms => 100 ms =~ 6 frames. + static const int _postFrameCallBackMinDelay = 100; // in milliseconds + static const int _SKIPPED_FRAMES = 10; BarcodeScanner? barcodeScanner; - CameraLensDirection cameraLensDirection = CameraLensDirection.back; late ContinuousScanModel _model; late UserPreferences _userPreferences; CameraController? _controller; - int _cameraIndex = 0; + CameraDescription? _camera; bool isBusy = false; - //Used when rebuilding to stop the camera + /// Flag used to prevent the camera from being initialized. + /// When set to [false], [_startLiveStream] can be called. bool stoppingCamera = false; //We don't scan every image for performance reasons @@ -39,44 +63,28 @@ class MLKitScannerPageState extends State { @override void initState() { super.initState(); - - // Find the most relevant camera to use if none of these criteria are met, - // the default value of [_cameraIndex] will be used to select the first - // camera in the global cameras list. - // if non matching is found we fall back to the first in the list - // initValue of [_cameraIndex] - if (cameras.any( - (CameraDescription element) => - element.lensDirection == cameraLensDirection && - element.sensorOrientation == 90, - )) { - _cameraIndex = cameras.indexOf( - cameras.firstWhere((CameraDescription element) => - element.lensDirection == cameraLensDirection && - element.sensorOrientation == 90), - ); - } else if (cameras.any((CameraDescription element) => - element.lensDirection == cameraLensDirection)) { - _cameraIndex = cameras.indexOf( - cameras.firstWhere( - (CameraDescription element) => - element.lensDirection == cameraLensDirection, - ), - ); - } + _camera = CameraHelper.findBestCamera(); } @override - void dispose() { - _controller?.dispose(); - super.dispose(); + void didChangeDependencies() { + super.didChangeDependencies(); + + // Relaunch the feed after a hot reload + if (_controller == null) { + _startLiveFeed(); + } } @override Widget build(BuildContext context) { _model = context.watch(); _userPreferences = context.watch(); + + // [_startLiveFeed] is called both with [onResume] and [onPause] to cover + // all entry points return LifeCycleManager( + onStart: _startLiveFeed, onResume: _startLiveFeed, onPause: _stopImageStream, child: _buildScannerWidget(), @@ -86,12 +94,8 @@ class MLKitScannerPageState extends State { Widget _buildScannerWidget() { // Showing the black scanner background + the icon when the scanner is // loading or stopped - if (_controller == null || - _controller!.value.isInitialized == false || - stoppingCamera || - _controller!.value.isPreviewPaused || - !_controller!.value.isStreamingImages) { - return Container(); + if (isCameraNotInitialized) { + return const SizedBox(); } final Size size = MediaQuery.of(context).size; @@ -103,8 +107,8 @@ class MLKitScannerPageState extends State { double scale = size.aspectRatio * _controller!.value.aspectRatio; // to prevent scaling down, invert the value - if (scale < 1) { - scale = 1 / scale; + if (scale < 1.0) { + scale = 1.0 / scale; } return Transform.scale( @@ -118,33 +122,31 @@ class MLKitScannerPageState extends State { ); } + bool get isCameraNotInitialized { + return _controller == null || + _controller!.value.isInitialized == false || + stoppingCamera || + _controller!.value.isPreviewPaused || + !_controller!.value.isStreamingImages; + } + Future _startLiveFeed() async { - if (_controller != null || cameras.isEmpty) { + if (_controller != null || _camera == null) { return; } barcodeScanner = GoogleMlKit.vision.barcodeScanner(); - stoppingCamera = false; - final CameraDescription camera = cameras[_cameraIndex]; _controller = CameraController( - camera, + _camera!, ResolutionPreset.high, enableAudio: false, imageFormatGroup: ImageFormatGroup.yuv420, ); // If the controller is initialized update the UI. - _controller?.addListener(() { - if (mounted) { - setState(() {}); - } - if (_controller!.value.hasError) { - // TODO(M123): Handle errors better - debugPrint(_controller!.value.errorDescription); - } - }); + _controller?.addListener(_cameraListener); try { await _controller?.initialize(); @@ -158,21 +160,72 @@ class MLKitScannerPageState extends State { debugPrint(e.toString()); } } + + if (mounted) { + setState(() {}); + } + } + + void _cameraListener() { if (mounted) { setState(() {}); + + if (_controller?.value.hasError == true) { + // TODO(M123): Handle errors better + debugPrint(_controller!.value.errorDescription); + } } } Future _stopImageStream() async { + if (stoppingCamera) { + return; + } + stoppingCamera = true; if (mounted) { setState(() {}); } + + _controller?.removeListener(_cameraListener); await _controller?.dispose(); - barcodeScanner?.close(); + await barcodeScanner?.close(); + barcodeScanner = null; - _controller?.removeListener(() {}); _controller = null; + + _restartCameraIfNecessary(); + } + + /// The camera is fully closed at this step. + /// However, the user may have "reopened" this Widget during this + /// operation. In this case, [_startLiveFeed] should be called. + /// + /// To detect this behavior, we compute the time took by + /// [addPostFrameCallback]. If it's less than a few frames, it means the + /// camera should be restarted immediately + void _restartCameraIfNecessary() { + if (mounted && ScreenVisibilityDetector.visible(context)) { + final DateTime referentialTime = DateTime.now(); + + WidgetsBinding.instance?.addPostFrameCallback((_) { + final int diff = + DateTime.now().difference(referentialTime).inMilliseconds; + + // The screen is still visible, we should restart the camera + if (diff < _postFrameCallBackMinDelay) { + _startLiveFeed(); + } + }); + } + } + + @override + void dispose() { + // /!\ This call is a Future, which may leads to some issues. + // This should be handled by [_restartCameraIfNecessary] + _stopImageStream(); + super.dispose(); } // Convert the [CameraImage] to a [InputImage] and checking this for barcodes @@ -230,13 +283,13 @@ class MLKitScannerPageState extends State { return; case DevModeScanMode.PREPROCESS_FULL_IMAGE: case DevModeScanMode.SCAN_FULL_IMAGE: - getter = CameraImageFullGetter(image, cameras[_cameraIndex]); + getter = CameraImageFullGetter(image, _camera!); break; case DevModeScanMode.PREPROCESS_HALF_IMAGE: case DevModeScanMode.SCAN_HALF_IMAGE: getter = CameraImageCropper( image, - cameras[_cameraIndex], + _camera!, left01: 0, top01: 0, width01: 1, diff --git a/packages/smooth_app/lib/pages/scan/scanner_overlay.dart b/packages/smooth_app/lib/pages/scan/scanner_overlay.dart index ab75ea2de3a..0bf24311535 100644 --- a/packages/smooth_app/lib/pages/scan/scanner_overlay.dart +++ b/packages/smooth_app/lib/pages/scan/scanner_overlay.dart @@ -55,11 +55,15 @@ class ScannerOverlay extends StatelessWidget { children: [ //Scanner if (backgroundChild != null) + // Force the child to take the full space, otherwise the + // [VisibilityDetector] may return incorrect results SmoothRevealAnimation( delay: 400, startOffset: Offset.zero, animationCurve: Curves.easeInOutBack, - child: backgroundChild!, + child: SizedBox.expand( + child: backgroundChild, + ), ), // Scanning area overlay SmoothRevealAnimation( diff --git a/packages/smooth_app/lib/widgets/screen_visibility.dart b/packages/smooth_app/lib/widgets/screen_visibility.dart new file mode 100644 index 00000000000..9a0b75eed6b --- /dev/null +++ b/packages/smooth_app/lib/widgets/screen_visibility.dart @@ -0,0 +1,55 @@ +import 'package:flutter/widgets.dart'; +import 'package:provider/provider.dart'; +import 'package:visibility_detector/visibility_detector.dart'; + +class ScreenVisibilityDetector extends StatefulWidget { + const ScreenVisibilityDetector({ + required this.child, + Key? key, + }) : super(key: key); + + final Widget child; + + @override + State createState() => + _ScreenVisibilityDetectorState(); + + static bool visible(BuildContext context) => + context.read().isVisible; +} + +class _ScreenVisibilityDetectorState extends State { + final ScreenVisibility _notifier = ScreenVisibility(false); + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider.value( + value: _notifier, + child: VisibilityDetector( + key: const ValueKey('ScreenVisibility'), + onVisibilityChanged: (VisibilityInfo info) { + _notifier.updateValue(info); + }, + child: widget.child, + ), + ); + } +} + +class ScreenVisibility extends ValueNotifier { + ScreenVisibility(bool value) : super(value); + + bool get isVisible => value; + + void updateValue(VisibilityInfo info) { + final bool visible = info.visible; + + if (value != visible) { + value = visible; + } + } +} + +extension VisibilityInfoExt on VisibilityInfo { + bool get visible => visibleBounds.height > 0.0; +} From e7eb8503029f3ffba9b0b4218b088a09794d33d7 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Wed, 4 May 2022 18:46:38 +0200 Subject: [PATCH 08/27] Scale preview if necessary (#1734) Co-authored-by: Pierre Slamich --- .../lib/pages/scan/ml_kit_scan_page.dart | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart b/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart index b985b761c01..bd1d95f37ff 100644 --- a/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart @@ -52,6 +52,7 @@ class MLKitScannerPageState extends State<_MLKitScannerPageContent> { CameraController? _controller; CameraDescription? _camera; bool isBusy = false; + double _previewScale = 1.0; /// Flag used to prevent the camera from being initialized. /// When set to [false], [_startLiveStream] can be called. @@ -104,15 +105,19 @@ class MLKitScannerPageState extends State<_MLKitScannerPageContent> { // this is actually size.aspectRatio / (1 / camera.aspectRatio) // because camera preview size is received as landscape // but we're calculating for portrait orientation - double scale = size.aspectRatio * _controller!.value.aspectRatio; - - // to prevent scaling down, invert the value - if (scale < 1.0) { - scale = 1.0 / scale; + _previewScale = size.aspectRatio * _controller!.value.aspectRatio; + + if (_previewScale < 1.0) { + // To prevent scaling down, invert the value + _previewScale = 1.0 / _previewScale; + } else { + // Scale up the size if the preview doesn't take the full width or height + _previewScale = _controller!.value.aspectRatio - size.aspectRatio; } return Transform.scale( - scale: scale, + alignment: Alignment.topCenter, + scale: _previewScale, child: Center( key: ValueKey(stoppingCamera), child: CameraPreview( @@ -260,8 +265,15 @@ class MLKitScannerPageState extends State<_MLKitScannerPageContent> { switch (scanMode) { case DevModeScanMode.PREPROCESS_HALF_IMAGE: case DevModeScanMode.SCAN_HALF_IMAGE: - // Half center top - return const Offset(0.5, 0.25); + // Half center top focus point + + if (_previewScale == 1.0) { + return const Offset(0.5, 0.25); + } else { + // Since we use a [Alignment.topCenter] alignment for the preview, we + // have to recompute the position of the focus point + return Offset(0.5, 0.25 / _previewScale); + } case DevModeScanMode.CAMERA_ONLY: case DevModeScanMode.PREPROCESS_FULL_IMAGE: case DevModeScanMode.SCAN_FULL_IMAGE: From 5e00af877c55c8178f3cddcdb314b7bcdb77b490 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 May 2022 20:21:02 +0200 Subject: [PATCH 09/27] chore(deps): bump actions/setup-java from 3.2.0 to 3.3.0 (#1737) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3.2.0...v3.3.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/android-release.yml | 2 +- .github/workflows/ios-release.yml | 2 +- .github/workflows/postsubmit.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml index 1977c6aee9a..766b1143c84 100644 --- a/.github/workflows/android-release.yml +++ b/.github/workflows/android-release.yml @@ -19,7 +19,7 @@ jobs: run: echo ${{ env.RELEASE_VERSION }} - name: Setup Java JDK - uses: actions/setup-java@v3.2.0 + uses: actions/setup-java@v3.3.0 with: distribution: 'zulu' java-version: 11 diff --git a/.github/workflows/ios-release.yml b/.github/workflows/ios-release.yml index b4b8a767841..b0364148f2e 100644 --- a/.github/workflows/ios-release.yml +++ b/.github/workflows/ios-release.yml @@ -26,7 +26,7 @@ jobs: ruby-version: 3.0.2 - name: Setup Java JDK - uses: actions/setup-java@v3.2.0 + uses: actions/setup-java@v3.3.0 with: distribution: 'zulu' java-version: 11 diff --git a/.github/workflows/postsubmit.yml b/.github/workflows/postsubmit.yml index 4b75f35119d..96fe41df030 100644 --- a/.github/workflows/postsubmit.yml +++ b/.github/workflows/postsubmit.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v3 - name: Setup Java JDK - uses: actions/setup-java@v3.2.0 + uses: actions/setup-java@v3.3.0 with: distribution: 'zulu' java-version: 11 From 01f906d8aa8ef820262e611ed2afb7b1be0ee9ec Mon Sep 17 00:00:00 2001 From: Aman Raj <57723319+AshAman999@users.noreply.github.com> Date: Thu, 5 May 2022 11:07:59 +0530 Subject: [PATCH 10/27] make app name resize itself (#1745) --- .../smooth_app/lib/pages/user_preferences_settings.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/lib/pages/user_preferences_settings.dart b/packages/smooth_app/lib/pages/user_preferences_settings.dart index 0a6ef2f2b89..7f762cfb864 100644 --- a/packages/smooth_app/lib/pages/user_preferences_settings.dart +++ b/packages/smooth_app/lib/pages/user_preferences_settings.dart @@ -139,9 +139,11 @@ class UserPreferencesSettings extends AbstractUserPreferences { ListTile( leading: Image.asset('assets/app/smoothie-icon.1200x1200.png'), - title: Text( - packageInfo.appName, - style: themeData.textTheme.headline1, + title: FittedBox( + child: Text( + packageInfo.appName, + style: themeData.textTheme.headline1, + ), ), subtitle: Text( '${packageInfo.version}+${packageInfo.buildNumber}', From d9ecd4e5e9ebb82c14e27bb9bea7989b94ad0ad6 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 5 May 2022 10:19:28 +0200 Subject: [PATCH 11/27] Bump Xcode to its latest version (#1744) --- packages/smooth_app/ios/fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/smooth_app/ios/fastlane/Fastfile b/packages/smooth_app/ios/fastlane/Fastfile index 5be7c90705e..b2ec68c8ae4 100644 --- a/packages/smooth_app/ios/fastlane/Fastfile +++ b/packages/smooth_app/ios/fastlane/Fastfile @@ -2,7 +2,7 @@ setup_travis default_platform(:ios) before_all do - xcversion(version: "~> 12.3") + xcversion(version: "~> 13.3") end platform :ios do From e050800799df6d6bdd2cd8f6a3bc13e984fb0a6b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 May 2022 12:59:35 +0200 Subject: [PATCH 12/27] chore: New Crowdin translations to review and merge (#1727) * chore: New Crowdin translations * Apply suggestions from code review * Apply suggestions from code review Co-authored-by: Crowdin Bot Co-authored-by: Pierre Slamich --- .../ios/Runner/fr.lproj/InfoPlist.strings | 2 +- packages/smooth_app/lib/l10n/app_bg.arb | 16 +++--- packages/smooth_app/lib/l10n/app_he.arb | 4 +- packages/smooth_app/lib/l10n/app_hr.arb | 32 ++++++------ packages/smooth_app/lib/l10n/app_tr.arb | 52 +++++++++---------- 5 files changed, 53 insertions(+), 53 deletions(-) diff --git a/packages/smooth_app/ios/Runner/fr.lproj/InfoPlist.strings b/packages/smooth_app/ios/Runner/fr.lproj/InfoPlist.strings index ccf72e779cf..4d2434a42a4 100644 --- a/packages/smooth_app/ios/Runner/fr.lproj/InfoPlist.strings +++ b/packages/smooth_app/ios/Runner/fr.lproj/InfoPlist.strings @@ -1 +1 @@ -"NSCameraUsageDescription" = "This app needs camera access to scan barcodes and to take product photos"; +"NSCameraUsageDescription" = "Cette application a besoin d'un accès à l'appareil photo pour scanner des codes à barres et pour prendre des photos de produits"; diff --git a/packages/smooth_app/lib/l10n/app_bg.arb b/packages/smooth_app/lib/l10n/app_bg.arb index fc6d4eae286..b15c41ae82d 100644 --- a/packages/smooth_app/lib/l10n/app_bg.arb +++ b/packages/smooth_app/lib/l10n/app_bg.arb @@ -36,7 +36,7 @@ "@error_occurred": {}, "featureInProgress": "Все още работим по тази функция, следвай ни", "@featureInProgress": {}, - "label_web": "View on the web", + "label_web": "Преглед в интернет", "@label_web": {}, "learnMore": "Научи повече", "@learnMore": {}, @@ -66,7 +66,7 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", + "offUtility": "Избери храна, която е полезна за теб и за планетата.", "@offUtility": { "description": "Description of what a user can use Open Food Facts for." }, @@ -455,11 +455,11 @@ "@uploading_image_type_front": { "description": "Message when a new front picture is being uploaded to the server" }, - "uploading_image_type_ingredients": "Uploading ingredients image to Open Food Facts", + "uploading_image_type_ingredients": "Качване на снимката на съставките в Open Food Facts", "@uploading_image_type_ingredients": { "description": "Message when a new ingredients picture is being uploaded to the server" }, - "uploading_image_type_nutrition": "Uploading nutrition image to Open Food Facts", + "uploading_image_type_nutrition": "Качване на снимката на хранителните стойности в Open Food Facts", "@uploading_image_type_nutrition": { "description": "Message when a new nutrition picture is being uploaded to the server" }, @@ -471,7 +471,7 @@ "@uploading_image_type_other": { "description": "Message when a new other picture is being uploaded to the server" }, - "uploading_image_type_generic": "Uploading image to Open Food Facts", + "uploading_image_type_generic": "Качване на снимката в Open Food Facts", "@uploading_image_type_generic": { "description": "Message when a new picture is being uploaded to the server" }, @@ -658,7 +658,7 @@ "@consent_analytics_title": { "description": "Title for the consent analytics UI Page" }, - "consent_analytics_body1": "Help the Open Food Facts volunteers to improve the app. You decide whether to submit anonymous analytics.", + "consent_analytics_body1": "Помогни на доброволците на Open Food Facts да подобрят приложението. Ти решаваш дали искаш да изпращаш анонимни данни.", "@conset_analytics_body1": { "description": "first paragraph for the consent analytics UI Page" }, @@ -740,7 +740,7 @@ "@crash_reporting_toggle_title": { "description": "Title for the Crash reporting toggle" }, - "crash_reporting_toggle_subtitle": "When enabled, crash reports are automatically submitted to Open Food Facts' error tracking system, so that bugs can be fixed and thus improve the app.", + "crash_reporting_toggle_subtitle": "Когато е активирано, докладите за сривове се изпращат автоматично до системата за проследяване на грешки на Open Food Facts, така че те да бъдат коригирани и да се подобри приложението.", "@crash_reporting_toggle_subtitle": { "description": "SubTitle for the Crash reporting toggle" }, @@ -877,7 +877,7 @@ "@user_list_name_hint": { "description": "Hint of a user list name text-field in a 'user list' dialog" }, - "user_list_name_error_empty": "The name cannot be empty", + "user_list_name_error_empty": "Името е задължително", "@user_list_name_error_empty": { "description": "Validation error about the name that cannot be empty" }, diff --git a/packages/smooth_app/lib/l10n/app_he.arb b/packages/smooth_app/lib/l10n/app_he.arb index 37cd824c97f..f9413a7577a 100644 --- a/packages/smooth_app/lib/l10n/app_he.arb +++ b/packages/smooth_app/lib/l10n/app_he.arb @@ -36,7 +36,7 @@ "@error_occurred": {}, "featureInProgress": "אנו עדיין עובדים על היכולת הזאת, מוטב לבדוק אותה שוב", "@featureInProgress": {}, - "label_web": "View on the web", + "label_web": "הצגה בדפדפן", "@label_web": {}, "learnMore": "מידע נוסף", "@learnMore": {}, @@ -66,7 +66,7 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", + "offUtility": "בחירה במזון שטוב לך ולכדור הארץ.", "@offUtility": { "description": "Description of what a user can use Open Food Facts for." }, diff --git a/packages/smooth_app/lib/l10n/app_hr.arb b/packages/smooth_app/lib/l10n/app_hr.arb index 0007e175720..11b7ec288ef 100644 --- a/packages/smooth_app/lib/l10n/app_hr.arb +++ b/packages/smooth_app/lib/l10n/app_hr.arb @@ -1,51 +1,51 @@ { "app_name": "OpenFoodFacts", "@Utils": {}, - "yes": "Yes", + "yes": "Da", "@yes": {}, "add": "Dodaj", "@add": {}, - "okay": "Okay", + "okay": "Dobro", "@okay": {}, - "applyButtonText": "Apply", + "applyButtonText": "Primijeni", "@applyButtonText": {}, "next_label": "Next", "@next_label": { "description": "A label on a button that says 'Next', pressing the button takes the user to the next screen." }, "save": "Spremi", - "save_confirmation": "Are you sure you want to save?", + "save_confirmation": "Jeste li sigurni da želite spremiti?", "skip": "Skip", "cancel": "Otkaži", "@cancel": {}, "close": "Zatvori", "@close": {}, - "no": "No", + "no": "Ne", "@no": {}, - "stop": "Stop", + "stop": "Zaustavi", "@stop": {}, "finish": "Finish", "@finish": {}, - "reset_food_prefs": "Reset food preferences", + "reset_food_prefs": "Resetiraj preferencije hrane", "@reset": { "description": "Button label, clicking on the button will reset user's food preferences." }, "error": "Dogodila se greška.", "@error": {}, - "error_occurred": "An error occurred", + "error_occurred": "Dogodila se pogreška", "@error_occurred": {}, - "featureInProgress": "We're still working on this feature, stay tuned", + "featureInProgress": "Još uvijek radimo na ovom svojstvu, ostanite s nama", "@featureInProgress": {}, - "label_web": "View on the web", + "label_web": "Pogledajte na webu", "@label_web": {}, - "learnMore": "Learn more", + "learnMore": "Saznajte više", "@learnMore": {}, - "general_confirmation": "Are you sure?", - "incompatible": "Incompatible", + "general_confirmation": "Jeste li sigurni?", + "incompatible": "Nespojivo", "@incompatible": { "description": "Short label for product list view: the product is incompatible with your preferences" }, - "compatible": "Compatible", + "compatible": "Kompatibilno", "@compatible": { "description": "Short label for product list view: the product is compatible with your preferences" }, @@ -55,12 +55,12 @@ }, "licenses": "Licences", "@licenses": {}, - "looking_for": "Looking for", + "looking_for": "Tražim", "@looking_for": { "description": "Looking for: ${BARCODE}" }, "@Introduction screen": {}, - "welcomeToOpenFoodFacts": "Welcome to Open Food Facts", + "welcomeToOpenFoodFacts": "Dobrodošli na otvorene činjenice o hrani", "@welcomeToOpenFoodFacts": {}, "whatIsOff": "Open Food Facts is a global non-profit powered by local communities.", "@whatIsOff": { diff --git a/packages/smooth_app/lib/l10n/app_tr.arb b/packages/smooth_app/lib/l10n/app_tr.arb index a474e430753..432717a650d 100644 --- a/packages/smooth_app/lib/l10n/app_tr.arb +++ b/packages/smooth_app/lib/l10n/app_tr.arb @@ -36,7 +36,7 @@ "@error_occurred": {}, "featureInProgress": "Bu özellik üzerinde halâ çalışıyoruz, takipte kal", "@featureInProgress": {}, - "label_web": "View on the web", + "label_web": "Web'de görüntüle", "@label_web": {}, "learnMore": "Daha fazla bilgi edin", "@learnMore": {}, @@ -66,7 +66,7 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", + "offUtility": "Kendiniz ve gezegen için iyi olan yiyecekleri seçiniz.", "@offUtility": { "description": "Description of what a user can use Open Food Facts for." }, @@ -455,38 +455,38 @@ "@uploading_image_type_front": { "description": "Message when a new front picture is being uploaded to the server" }, - "uploading_image_type_ingredients": "Uploading ingredients image to Open Food Facts", + "uploading_image_type_ingredients": "İçindekiler görseli Open Food Facts'e yükleniyor", "@uploading_image_type_ingredients": { "description": "Message when a new ingredients picture is being uploaded to the server" }, - "uploading_image_type_nutrition": "Uploading nutrition image to Open Food Facts", + "uploading_image_type_nutrition": "Besin değerleri görseli Open Food Facts'e yükleniyor", "@uploading_image_type_nutrition": { "description": "Message when a new nutrition picture is being uploaded to the server" }, - "uploading_image_type_packaging": "Uploading packaging image to Open Food Facts", + "uploading_image_type_packaging": "Ambalaj görseli Open Food Facts'e yükleniyor", "@uploading_image_type_packaging": { "description": "Message when a new packaging picture is being uploaded to the server" }, - "uploading_image_type_other": "Uploading other image to Open Food Facts", + "uploading_image_type_other": "\"Diğer\" görseli Open Food Facts'e yükleniyor", "@uploading_image_type_other": { "description": "Message when a new other picture is being uploaded to the server" }, - "uploading_image_type_generic": "Uploading image to Open Food Facts", + "uploading_image_type_generic": "Görsel Open Food Facts'e yükleniyor", "@uploading_image_type_generic": { "description": "Message when a new picture is being uploaded to the server" }, - "score_add_missing_ingredients": "Add missing ingredients", - "score_add_missing_nutrition_facts": "Add missing nutrition facts", - "score_add_missing_product_category": "Add missing product category", - "score_update_nutrition_facts": "Update nutrition facts", + "score_add_missing_ingredients": "Eksik içindekiler bilgileri ekle", + "score_add_missing_nutrition_facts": "Eksik besin değerlerini ekle", + "score_add_missing_product_category": "Eksik ürün kategori bilgisini ekle", + "score_update_nutrition_facts": "Besin değerleri bilgilerini güncelle", "nutrition_page_title": "Besin Değerleri", - "nutrition_page_unspecified": "Nutrition facts are not specified on the product", + "nutrition_page_unspecified": "Ürünün üzerinde besin değerleri bilgisi yer almıyor", "nutrition_page_per_100g": "100g başına", "nutrition_page_per_serving": "porsiyon başına", "nutrition_page_add_nutrient": "Besin ögesi ekle", "nutrition_page_serving_size": "Porsiyon ölçüsü", "nutrition_page_invalid_number": "Geçersiz numara", - "nutrition_page_update_running": "Updating the product on the server...", + "nutrition_page_update_running": "Ürün bilgileri güncelleniyor...", "nutrition_page_update_done": "Ürün güncellendi!", "more_photos": "Daha ilginç fotoğraflar", "@more_photos": {}, @@ -507,7 +507,7 @@ "@could_not_refresh": { "description": "The product data couldn't be refreshed" }, - "product_internet_error": "Impossible to fetch information about this product due to a network error.", + "product_internet_error": "Bir ağ hatasından dolayı ürün bilgileri çekilemedi.", "cached_results_from": "Sonuçların gösterildiği:", "@cached_results_from": { "description": "Cached results from: x time ago (time ago should not be added to the string)" @@ -523,11 +523,11 @@ "@product_improvement_add_category": { "description": "Message for ProductImprovement.ADD_CATEGORY" }, - "product_improvement_add_nutrition_facts": "Add nutrition facts to calculate the Nutri-Score.", + "product_improvement_add_nutrition_facts": "Nutri-Score puanını hesaplamak için besin değerleri bilgisi ekleyin.", "@product_improvement_add_nutrition_facts": { "description": "Message for ProductImprovement.ADD_NUTRITION_FACTS" }, - "product_improvement_add_nutrition_facts_and_category": "Add nutrition facts and a category to calculate the Nutri-Score.", + "product_improvement_add_nutrition_facts_and_category": "Nutri-Score puanını hesaplamak için besin değerleri ve bir kategori bilgisi ekleyin.", "@product_improvement_add_nutrition_facts_and_category": { "description": "Message for ProductImprovement.ADD_NUTRITION_FACTS_AND_CATEGORY" }, @@ -841,23 +841,23 @@ "@edit_ingredients_extrait_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, - "edit_ingredients_refresh_photo_btn_text": "Refresh photo", + "edit_ingredients_refresh_photo_btn_text": "Fotoğrafı yenileyin", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "user_list_dialog_new_title": "New list of products", + "user_list_dialog_new_title": "Ürünlerin yeni listesi", "@user_list_dialog_new_title": { "description": "Title of the 'new user list' dialog" }, - "user_list_dialog_rename_title": "Rename list", + "user_list_dialog_rename_title": "Listeyi yeniden adlandırın", "@user_list_dialog_rename_title": { "description": "Title of the 'rename user list' dialog" }, - "user_list_subtitle_product": "Lists", + "user_list_subtitle_product": "Listeler", "@user_list_subtitle_product": { "description": "Subtitle of a paragraph about user lists in a product context" }, - "user_list_button_new": "New list", + "user_list_button_new": "Yeni liste", "@user_list_button_new": { "description": "Short label of a 'new list' button" }, @@ -869,23 +869,23 @@ "@user_list_popup_clear": { "description": "Short label of a 'clear list' popup" }, - "user_list_popup_rename": "Rename", + "user_list_popup_rename": "Yeniden adlandırın", "@user_list_popup_rename": { "description": "Short label of a 'rename list' popup" }, - "user_list_name_hint": "My list", + "user_list_name_hint": "Listem", "@user_list_name_hint": { "description": "Hint of a user list name text-field in a 'user list' dialog" }, - "user_list_name_error_empty": "The name cannot be empty", + "user_list_name_error_empty": "İsim boş bırakılamaz", "@user_list_name_error_empty": { "description": "Validation error about the name that cannot be empty" }, - "user_list_name_error_already": "That name is already used", + "user_list_name_error_already": "Bu isim zaten kullanılmakta", "@user_list_name_error_already": { "description": "Validation error about the name that is already used for another list" }, - "user_list_name_error_same": "That is the same name", + "user_list_name_error_same": "Bu aynı isim", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" } From 58b9bc5a12482469bcce01d00462d7c296b33ead Mon Sep 17 00:00:00 2001 From: Aman Raj <57723319+AshAman999@users.noreply.github.com> Date: Thu, 5 May 2022 21:44:03 +0530 Subject: [PATCH 13/27] fix: added confirmation dialog (#1746) * added confirmation dialog * make await show dailog to pass the flutter tests * make more readable confirmation message * added translations * formatting code --- packages/smooth_app/lib/l10n/app_en.arb | 5 +++ .../product/common/product_list_page.dart | 31 +++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 30202d0790e..44ae009b3b6 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -888,5 +888,10 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } + } \ No newline at end of file diff --git a/packages/smooth_app/lib/pages/product/common/product_list_page.dart b/packages/smooth_app/lib/pages/product/common/product_list_page.dart index 20ec5fa34ad..e79931f7867 100644 --- a/packages/smooth_app/lib/pages/product/common/product_list_page.dart +++ b/packages/smooth_app/lib/pages/product/common/product_list_page.dart @@ -8,7 +8,9 @@ import 'package:smooth_app/database/dao_product.dart'; import 'package:smooth_app/database/dao_product_list.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/database/product_query.dart'; +import 'package:smooth_app/generic_lib/buttons/smooth_action_button.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; import 'package:smooth_app/generic_lib/loading_dialog.dart'; import 'package:smooth_app/helpers/robotoff_insight_helper.dart'; import 'package:smooth_app/pages/personalized_ranking_page.dart'; @@ -69,9 +71,32 @@ class _ProductListPageState extends State { onSelected: (final String action) async { switch (action) { case _popupActionClear: - await daoProductList.clear(productList); - await daoProductList.get(productList); - setState(() {}); + await showDialog( + context: context, + builder: (BuildContext context) { + return SmoothAlertDialog( + body: Text(appLocalizations.confirm_clear), + actions: [ + SmoothActionButton( + onPressed: () async { + await daoProductList.clear(productList); + await daoProductList.get(productList); + setState(() {}); + Navigator.of(context).pop(); + }, + text: appLocalizations.yes, + ), + SmoothActionButton( + onPressed: () { + Navigator.of(context).pop(); + }, + text: appLocalizations.no, + ), + ], + ); + }, + ); + break; case _popupActionRename: final ProductList? renamedProductList = From 1b62e8728ba7d61302e0d00ece1577027ff5fbc2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 May 2022 19:51:26 +0200 Subject: [PATCH 14/27] chore(deps): bump percent_indicator in /packages/smooth_app (#1755) Bumps [percent_indicator](https://github.com/diegoveloper/flutter_percent_indicator) from 4.0.0 to 4.0.1. - [Release notes](https://github.com/diegoveloper/flutter_percent_indicator/releases) - [Changelog](https://github.com/diegoveloper/flutter_percent_indicator/blob/master/CHANGELOG.md) - [Commits](https://github.com/diegoveloper/flutter_percent_indicator/compare/4.0.0...4.0.1) --- updated-dependencies: - dependency-name: percent_indicator dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/pubspec.lock | 2 +- packages/smooth_app/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index b552822b4c2..a717ed6d3f9 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -744,7 +744,7 @@ packages: name: percent_indicator url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.0.1" permission_handler: dependency: "direct main" description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index ba22e396bdc..f714d696c56 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -42,7 +42,7 @@ dependencies: url_launcher: ^6.1.0 visibility_detector: ^0.2.2 camera: ^0.9.4+20 - percent_indicator: ^4.0.0 + percent_indicator: ^4.0.1 mailto: ^2.0.0 flutter_native_splash: ^2.1.6 # Fork from cli1005 with iOS fix cf: https://github.com/openfoodfacts/smooth-app/issues/1155 From 18ee2847e1d731a84df3211f017a5df135f7d8aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 May 2022 19:51:32 +0200 Subject: [PATCH 15/27] chore(deps): bump image_cropper in /packages/smooth_app (#1756) Bumps [image_cropper](https://github.com/hnvn/flutter_image_cropper) from 2.0.0 to 2.0.1. - [Release notes](https://github.com/hnvn/flutter_image_cropper/releases) - [Commits](https://github.com/hnvn/flutter_image_cropper/compare/v2.0.0...v2.0.1) --- updated-dependencies: - dependency-name: image_cropper dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/pubspec.lock | 4 ++-- packages/smooth_app/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index a717ed6d3f9..d0ac93a6dfb 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -431,14 +431,14 @@ packages: name: image_cropper url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" image_cropper_for_web: dependency: transitive description: name: image_cropper_for_web url: "https://pub.dartlang.org" source: hosted - version: "0.0.2" + version: "0.0.3" image_cropper_platform_interface: dependency: transitive description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index f714d696c56..3067ecbc4f1 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -50,7 +50,7 @@ dependencies: git: url: https://github.com/cli1005/google_ml_barcode_scanner.git ref: master - image_cropper: ^2.0.0 + image_cropper: ^2.0.1 auto_size_text: ^3.0.0 dev_dependencies: From e8a336e904db783b2525358c580647886f155242 Mon Sep 17 00:00:00 2001 From: Aman Raj <57723319+AshAman999@users.noreply.github.com> Date: Fri, 6 May 2022 00:00:05 +0530 Subject: [PATCH 16/27] fix: properly managed state (#1758) --- .../lib/pages/onboarding/country_selector.dart | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/smooth_app/lib/pages/onboarding/country_selector.dart b/packages/smooth_app/lib/pages/onboarding/country_selector.dart index 6e6bbc927a2..a666f0736c7 100644 --- a/packages/smooth_app/lib/pages/onboarding/country_selector.dart +++ b/packages/smooth_app/lib/pages/onboarding/country_selector.dart @@ -62,7 +62,7 @@ class _CountrySelectorState extends State { return GestureDetector( onTap: () async { List filteredList = List.from(_countryList); - await showDialog( + final Country? country = await showDialog( context: context, builder: (BuildContext context) { return StatefulBuilder( @@ -109,12 +109,8 @@ class _CountrySelectorState extends State { final Country country = filteredList[index]; return ListTile( title: Text(country.name), - onTap: () async { - _chosenValue = country; - await _setUserCountry( - _chosenValue.countryCode); - setState(() {}); - Navigator.of(context).pop(); + onTap: () { + Navigator.of(context).pop(country); }, ); }, @@ -134,6 +130,11 @@ class _CountrySelectorState extends State { ); }, ); + if (country != null) { + _chosenValue = country; + await _setUserCountry(_chosenValue.countryCode); + } + setState(() {}); }, child: Container( decoration: BoxDecoration( From e175ebbe13e4865a71ea3fee9aef6e5d2debdfa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Prima=C3=ABl=20Qu=C3=A9merais?= <34269530+PrimaelQuemerais@users.noreply.github.com> Date: Fri, 6 May 2022 09:50:11 +0200 Subject: [PATCH 17/27] fix: Creating a product from barcode search is not working (#1752) --- .../pages/product/common/product_dialog_helper.dart | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/lib/pages/product/common/product_dialog_helper.dart b/packages/smooth_app/lib/pages/product/common/product_dialog_helper.dart index 24424524c84..b9836e4aebd 100644 --- a/packages/smooth_app/lib/pages/product/common/product_dialog_helper.dart +++ b/packages/smooth_app/lib/pages/product/common/product_dialog_helper.dart @@ -8,6 +8,7 @@ import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/generic_lib/buttons/smooth_action_button.dart'; import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; import 'package:smooth_app/generic_lib/loading_dialog.dart'; +import 'package:smooth_app/pages/product/add_new_product_page.dart'; /// Dialog helper for product barcode search class ProductDialogHelper { @@ -59,9 +60,13 @@ class ProductDialogHelper { ), SmoothActionButton( text: AppLocalizations.of(context)!.contribute, - - onPressed: () => Navigator.pop( - context), // TODO(monsieurtanuki): to be implemented + onPressed: () => Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => + AddNewProductPage(barcode), + ), + ), ), ], ); From b6e253a2dbc1d2cf9dd0110e907e2b096f26bc2a Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Fri, 6 May 2022 11:14:43 +0200 Subject: [PATCH 18/27] feat: #960 - 2 lines (instead of 1) for "importance", and radio button on top (#1760) Impacted files: * `attribute_button.dart`: 2 lines (instead of 1) for "importance", radio button on top, smaller title style, info on the right, minimum target size * `user_preferences_page-blue-dark.png`: golden refresh * `user_preferences_page-blue-light.png`: golden refresh * `user_preferences_page-brown-dark.png`: golden refresh * `user_preferences_page-brown-light.png`: golden refresh * `user_preferences_page-green-dark.png`: golden refresh * `user_preferences_page-green-light.png`: golden refresh --- .../lib/widgets/attribute_button.dart | 56 ++++++------------ .../user_preferences_page-blue-dark.png | Bin 7603 -> 7440 bytes .../user_preferences_page-blue-light.png | Bin 7669 -> 7497 bytes .../user_preferences_page-brown-dark.png | Bin 7603 -> 7440 bytes .../user_preferences_page-brown-light.png | Bin 7679 -> 7517 bytes .../user_preferences_page-green-dark.png | Bin 7603 -> 7440 bytes .../user_preferences_page-green-light.png | Bin 7679 -> 7508 bytes 7 files changed, 18 insertions(+), 38 deletions(-) diff --git a/packages/smooth_app/lib/widgets/attribute_button.dart b/packages/smooth_app/lib/widgets/attribute_button.dart index 6e5a00e853f..39d45502416 100644 --- a/packages/smooth_app/lib/widgets/attribute_button.dart +++ b/packages/smooth_app/lib/widgets/attribute_button.dart @@ -28,14 +28,13 @@ class AttributeButton extends StatelessWidget { @override Widget build(BuildContext context) { final ThemeData themeData = Theme.of(context); - final IconThemeData iconThemeData = IconTheme.of(context); final String currentImportanceId = productPreferences.getImportanceIdForAttributeId(attribute.id!); const double horizontalPadding = LARGE_SPACE; final double widgetWidth = MediaQuery.of(context).size.width - 2 * horizontalPadding; final double importanceWidth = widgetWidth / 4; - final TextStyle style = themeData.textTheme.headline3!; + final TextStyle style = themeData.textTheme.headline4!; final String? info = attribute.settingNote; final List children = []; for (final String importanceId in _importanceIds) { @@ -59,26 +58,26 @@ class AttributeButton extends StatelessWidget { ), ); }, - child: SizedBox( + child: Container( width: importanceWidth, - height: MINIMUM_TARGET_SIZE, + constraints: const BoxConstraints(minHeight: MINIMUM_TARGET_SIZE), child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ - AutoSizeText( - productPreferences - .getPreferenceImportanceFromImportanceId(importanceId)! - .name!, - maxLines: 1, - textAlign: TextAlign.center, - ), Icon( currentImportanceId == importanceId ? Icons.radio_button_checked : Icons.radio_button_off, color: themeData.colorScheme.primary, ), + AutoSizeText( + productPreferences + .getPreferenceImportanceFromImportanceId(importanceId)! + .name!, + maxLines: 2, + textAlign: TextAlign.center, + ), ], ), ), @@ -94,31 +93,12 @@ class AttributeButton extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - GestureDetector( - child: SizedBox( - height: MINIMUM_TARGET_SIZE, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - if (info != null) const Icon(Icons.info_outline), - Container( - padding: info == null - ? null - : const EdgeInsets.only(left: SMALL_SPACE), - child: SizedBox( - width: widgetWidth - - SMALL_SPACE - - (iconThemeData.size ?? DEFAULT_ICON_SIZE), - child: AutoSizeText( - attribute.settingName ?? attribute.name!, - maxLines: 2, - style: style, - ), - ), - ), - ], - ), + ListTile( + trailing: info == null ? null : const Icon(Icons.info_outline), + title: AutoSizeText( + attribute.settingName ?? attribute.name!, + maxLines: 2, + style: style, ), onTap: info == null ? null @@ -141,7 +121,7 @@ class AttributeButton extends StatelessWidget { ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: children, ), ], diff --git a/packages/smooth_app/test/pages/goldens/user_preferences_page-blue-dark.png b/packages/smooth_app/test/pages/goldens/user_preferences_page-blue-dark.png index 6a1c5f722db917ac2952f8f6fb165e7d22c5dd12..d3e58ff3e1244aba50409a1ce99a0f2f7afbfb6f 100644 GIT binary patch literal 7440 zcmd5>c~n!^*1s6*P!vj06oEpauV_VlhzbHB4j|Q5q^Kasps0XE!w?xVkf2lrWss+c z1PCBcK^cOg1PGHdDHK6?AE{fod4 ze$lZo2vRTFWwC94P$Iv>z%wzBG(O_7%s~~e=65e|^)|WV(E?KQ#g$!EsO67X8ZqBG zrPXE_e|2G3Z{|zntljg+WmH@K;(8v~`u-JP7)? z(&xD()f3LU1`8Xhq7GD6R#s(Qo%LcG z&v0vXO-)ZnAbZ_$9fqJ<&3lS%k|V{-3avbcKkYxAhMx|5NG3uVwD9oo>j?>KdmWKT z1>FFKtfMdtLBhfiq$G!!}c6gEAx^-36)zzurm>L=? z_xJb1S}x3f?{B6o?SMBp_?5+CvG_WfZ2t0S`mI|F@)c!$w&U=TBdNS~7QfDHU?JNe zDm64TR0lItUgZY&3ky~A^70ON_vqqfLI0sKNjozec`6!&X(96{9$)-ydg>h01-DLH zyHqN{F^OlAl9I*;X+sPAP7P7|HGBK5mW)lopwN2z5D?SrM>Fk1DwS$nuBxgs4xTv8 zK#K-DE}^+~LNn2CPp$-w4Yb%~VWua9WUjV$9T~2sNf-)VfnHj{aAo6G=VdYIOHXZlshRx4J}RLly5|2q|hvoTbESe)3u#}PO{e3c3a(~ zw+c2?CMD?U>)*<8I7c9RRQe>Qnq-S#_cc5smfvpRUgnDZ{ITSUd+vxK-Evp7yb9>G zowC4Z+wLzfZw(O_C-of1Voj{cW-WsDv9W-u(YUe!Oil-?hQo1Zpg|d2fx6aDbtw|V z?%usi<_@+ODzDIYdWFep=&QW>Qyi8IgHp)tX8{QOyKhqMGM~?1sj0bsBNIi%k#SSw zz7Y`-OR7kgaKcox0RN;tcjgiJRQ8yeAk8FL0YhGIpU&N)ha3|S=1o12W$S+e2LB0U z(x#U%>guY&)77><-CHc?Bq%A3ysFm$<(Z5JRpDCFDR z+*})>iuP9PcH#CUK zVD}0NR;KSw9>ff?N^riQAjw>^8RlySXugY^D6VBJfs;jLOP)thg(5=lzI&2O8v`LV zE1epB3VJm05Ymo%3vF7ksU&~BYs1jm8swfKE+ezeV|%?QFKR;Jax_9>4B!n*rlGmk zP6a-x+(PSgWhH}UNELY4n}$?zG`wL>;Wwo3l_%yJQ=789_HYAykl0hMrMKAjQA`qx zk!(+8{CeceujbI;U-sjl-{5|qEpHY)v2j)8&LR2esA?9=B~_@c9ZW|^#SCziEWrS1 z-1}{OGWQzpTO*?sK_s67<^Q>LER zL4xb;Hj?Gir;`q{U|)DXaO@!H`%I4USE{M?V+QMzOnti^og;HilB_K(CP;Dm&OD3) z1dacMdI$>O4=J9L?Z3RFdzP(eX0f71Mn<-y`2jR;VNJAV&Ev;EPLKfqN>>3wJ|z4e zWWK9YMeqGe`pdOH*9{TZ{8Ir#9&~XToHXe`8QIy{xp{b`|LP2i+G^KrxeZ1}_O%b1 znwn%PM}5cap;rCLeZ8hjQw0IGpIR6e*4WtSNo|AE)kRFh8_oT; zFMWw{daUV+7@WCWr{(;|3>hr}lCUd@)ah&3i{OhDH&hH`RWQyMSDj~G@jFi53k4|= z7i)Z^o-)iOE)FIT%x|TqD+-%$-@d)=6fCM3l+`%ho6sO=2XJN((gEP2seInCBS((d z#GOCdn@we11OeZn%0ZXkkmrk1xh=-VtNU$lx@2nNaJYIIGaxsvQc|kt2SoRRUL71n zF$`;_g%QI=*G-GiN>z2b(ADgEuLoGE^AZS3fj+&5{=Bn3>C>H=EC>>AFfdSh`t)hA zYkC{My0&)rz`(%O+_eyIdkFOW%3O6dZ~o!Oua|2bJ$iJcjV;N~Dye++O0f;d;y^eP zUBWH!@3%W`l4P6H%Vi3&2RLHb;UM91t+I(mN_Sw{q_YD~&ZWDbQWiBS8jABM;}5#JY7R$1#+{g+9BkVC{*>p zz{$ooDCO3yO6yy@l?=z(HJOL(SS<)x4xXl#Zwp;b1vxJ|;0>TK*ejg4(?X<2i`ei|GUb@EH8eE5TUu(~sj+7?p`u53IR0dr{b`%z2@TYN`Ye8o>w86h^L6~zX}k~1WGKTfYU!A zSU5cz2sZm0?#j?n2n>5j+y^DF#ySL`^-?`Oz5ONUY~T5}&P681#>W3*^5SOH!J@b7 z;FqG^uwxz`y5^GudGCj==@LqCzaSPGx(k~BohjrhPBhAh>5dUV-6ac& z3qQLt)OmL#vd0W6buGsJAn7Z~1YNDxF;0E=yKDuW^dQ4x$>ztE2JWxj7P90+6)2z z^p#<7<+L+SbJmA$hZC<$n0Kg9?400c#l4c2)yr+_>Q9i{7I2e~aHb5OB}%)V&q)j$ zRKk14W4D++yg7khfE9YBwgA|w0h+9VqpfXcZ=cqI5}Dao3EF{ZJVZq;cNBywnuh_n zB6BA&r!s>O{in~@cIzpi@=-{;U={Jh?ryh4^WY+GAx<<{Rfy(d$+*$qcA4SE^n&UA zOp3_Ns*pG4p^sER(M^bwxY4-hy1KeO9D2ezcWQoq_p|tlX_(>hXOXLTWnvgk=87g%G1rUuUCJss|(!L`0$ZbAQ(D2I<}+zapWfTc9JCnJcuPylEKS6 zc+Ndf)t=(AZX-@AnKs6aon)XB5)yp-o3d9(CV+yBh>k{xm@b&!*p;dn3315OpSOR2 z&xebc3JMA?##9F2ir#VU623_v2+)+KHM!l8o}*i#$3_FPl3Z_my|1hJG`cmv1x0I7DFO^%JHN=DSj z*ZRyHA*yI+n$n8(E?HPLsOBsr7ZPXe+ij7RlcPfFXl?xgV+08~Z&5cRwxpy4h^uq% znsDs0D_5?-8F2h~?(@V=3uzpnN>aC^I7ZrKHfCd$fk^Z5`DlavNdjYLboTKp%;*wm zc;BDThLV9H3(@feB*o!yb{96awzkGBeq&N*xOvm_zSC|*qSPi@Lsd20J#P!38yP^R zEcnoE$_-^)-wpdMDUcP8WacahxB9RVY(Wu)v0;iU|b1Wptj zsIz(d6&d9qk((D5jrz_XTE3 za?1~{WtyVrjFU-hX;>FQ!pVdqARGHRg)sa#Npud;{HIG$$RXUxs?7B6WEQOz4EO3I zr4wvobUKb5m%H|HmkfJ}=i>zk_4$vLgpPv!P7^euey^i6Pk6#?x=v9`IOmpG^d4FI zJ&}mtfGTvF)3;Sl+V>&=he>R90CrR0@W0Z0z(<4_h*VSXiv{ zxaapRiDrc#jc;=vRR(p&iG5E*J=tY&bVdzXl0aQptoFF~-TI3!lg2Of5wo%KHmdJ} zd-7(k;b);y31$u|$9#S#PfdlniCHQeH_z#rTUVt^z4KZkGVLiUq!OZ(kO;?ZKBcei z=I_6$l^?)BA24Hp(YZ{0r*1-wcZOb%kMG0eBs23bit?;IGW6=YJKg*9-5Wh(G=aye z?rTWLk!gWLE{UdrIov`Zy(;rO7%!N`glQ}TeKiwBe2ykSfVAA zvTWXOVW#hc=MqB?C1`c%?D9A9uzOVM3gF$J52RT|yZQOu;}%{})Kno|3Ty7@Shvxh z$~{4UnCFH)+S4vrhZ96NY&nq5IS=KJGq zCOPNa&+y*q+5c8C&&cG?3}A14N4l$k4ffFkRwF3WGT5>O%wa1oD9Y0v(7DLL!9f)g?9N>M`~T7le@IpC_j%wQ5QNzDXYM#tvKYX> z@!9Xc|K1IS%DIXJ`bHxj@||JVYT4@-8yFaYkBLNJ?f~Wupk!dIUkqf<)$8ydz3s)@ z8@IB+3%r5=zGIj8itgT>78bOQ&92XNlks1(@q#_6EqB;uVb~$Iz{s^1Z$acPgf9LM dY>+?-d8b63Ko@t7f}?kk8=P3 literal 7603 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 dY>+?-d8b63Ko@t7f}?kk8=P3 literal 7603 zcmd5>dpMM7|9^D!>L6PYa@f3OJ1i^5Fvd!Bq!0-+MIjS%9;Y$8rKS~Qe<>M&#%7F@~AnjoNMZx7YRC-gd9+eg1jwnd^R@`}F-BzTfBiaSQWx z5^@p{1g$%C(9{ZomMcThvQy%#z(0h*A1{HMn4guo36x#CbrAem;b(HlMjTvW;^%M> zq~LVO^m`k0(rA~Zds0xy%L((0k)w`@Hnuvx2aPX2rhjw0T>RRWutW&qOVORV~jJbLP zPOT=VR=`i{=efCJLd==fndsh`3Dzi>&cW~6+3Uc4`fFnd!fGvB0sd0?o0=|NYcV6a z)ShNLBv2=e9hchvlPUMEl!yifHC`~mgFLw1=BMm{ZW>_%)3oFFGv{^Ar z{$W?}#|e9ux)H-)JTHQvyAmr7icw~pb9xFW^PZFfF$lW#i}W4{QjUf|yTO06a%gDi z`O#E2E{}I4F;jvjbM;UHoC3W(vt@BD%tSE3p;zCYf*@l#v1JhSKuY=VZW4aRx${Cd zg4e=kR{h}+HCry~2*|6!N_K=T|7V8(f0sqb^;$)%sVOh=>#uCDBJT6)F*P;4=SzBchrl{j_Ii=D$?9W2B#QX-&7#qZv|J7sS_7?Ki5Qpn8A%+1TQew|&sHg;lS z;!aA6+IbatFL-K>5>PEF%SKWdc|~MOpHeShB_vcRc6Vrps;UbHQyN#)LZ=^Dv!UP& zII9cAvkRN^=xSG2S8GRyL7j`axp`{6`_wt5g~<0f6CAuxM^{&JsDJSr+`o?&8IxN;4^+`o+>=#2O% zn=RSv==EwDg#G$?e*R`ZKfifK1#x2Cp9Z%Xp~e*e#nN!X^adUuUqpoajI`$Ba5H_0 z-qj+Nz`($s+GGP*LWck){5}PKzo1_U8i>wbSm|By5BnhuGQNHLwzISI{qaH?Tx6IM zI#%?WRVthvM$e3&{kA2nKRHMOABEEk7_uputla$=#oez<%TsfEbQo32V}wqW%OE!? z%ACj=j_v1jGNufNpSkL?RbQqSuaDJbpjFl@89Aamn=|cLBW-z+)X}jqGt(yL8Vi^A zY4M1k($dnJv<3GP`(;nyHEq(g*V`E-P20_{5dJvTHZgFTrHbtx`VAvMybC6bcv&Uw|AOUxDi-JN{IU%_?T=1fw zugMzny_)g7&kh-W5?#&9@K=~Lj6mE6>4HZaSFPcJTv5m(Kj};@Qt3ZNSMX ziHT8u{k6C921*>^!K}?P`ms3`ew<|aF+arUs+%Lx8@D4#G1hL%S3d~^({(D z>VEKup4MC!DXEDXUFIE;`N+t~n`DEakiEa#m+t11U?^x)_o9*ns{IoLc6Xl6i$LiY zkR2LP0uE}{Q8rtfOoV57(63l9X}gB>jTvZGv|iZErEVX)97J@U8%ypT`)$B;SJMDQM<{PBAndGR;8gOYCWA$>&b4JY8TECk~6CM4>z}r*f=q0 z8BQCA&OKD?g(EVKw=5styMJ2)A*LSb2 zt!;5idY2b;IU~NbDc0?}%J}xKu4pou47AMO zUrR39EawFP^jciX%C~<6ZDtk-@a6a2#P+TQ{TvG~-5W2=&1EB6E@PJ4Z(vHMSh_+c@qvzcO zJp<6Nopycv6<8$}zE12johwWbUne6i?dXN*rK5Qds{&b*I~iK*bw;7D{QAi=iF zT@W;7OIvo%$0yg$y6kxH>|nZ!r)L(k1Bmqp%wAw(N7(Fm?URrF0$3n+7uJH8mz4#S z8c2f0v9@g+V^Wal>ZgoO9{BjWe170#0;|*aw z5|WZ`+`4ruyZ=H#M{aSkoPmMC_7Mqe25>K%_5xA(BtkqMWi= zC1S5hD&5YPd=FKYIF*Cd6gf#?_bzG#MHifT(`B%d&kWelQTQ+Et7+R}dh_PZ+-J`k zrVU2}4Q%b~T-@B!uQ-8uUw+U8B@l_~=d-7$0~WHF{co47QA4R%a1%J-kQu&UK4yTCcV<_=Mv<6p+t zzy}X$SeovGv&$a1i9IVR*_xP`2!wiMA;4STOilTB`{4C`dk>nL0#&$2P~Fxu z&ttMf*5~8}S98kd!V=QuYw^L=*7)FUmHc3(9ZPQG6RrN7=8b8Op2*0^I|&K<>Ri$v zJ`BkRnerLz)E;AC8A7$Sfq^-(G(eoRvOpj>f9&LtBd`zezZsQ&vJ@G+QTo5przXIC z$2n7iaSk)(lNI4mzCmHXm_be3)Acp=7+ z2BuaR#`iTxmCj98X&4wdpdEE{JmC!5uH<{q^rFb}4*A-GaOoc$PYRN&2xN!6O1j8u z**RzDZ6H<9mkVW8MC%1lo@+0};f};z*N}=`eIsGod!9{g<5_P@JNL?`?#WP`LI~IM_Pa|5|5BHQuO}tvI zv`KEG)I^JecN#25ml>8}w&Zzi9Ta?X}3=|_G`b_AY=cx*!38YAlrx*qj zY^YMjcvYOF@=!HDy*5TWhFU}sUbE^e_GMXhl2~)r3fZD*<&Qm9KT@TOLVzHA_i~J# z-_tF;ykHA@)$jWZxZ{IX)G3HrNf}`uY4#KK1qGrx>da)V()y{^bmC0nOg}}yQ)G)z z778U*KXy~Po8l{OR|fl!E>mMwiM){|$X_+|sV^?LGJ8$rFE=CBS2Ib2F%X z>^y4+SWJ1RwsBv7|B(b#c(@agwwD`x7c-=X&%KQm^FiVOie7-92L{{$-@Ha8>G^C! zgpTIFW+?_t4bOw}`ZjS(1Ej5d zD->evt#9eeK+t!3he<1egeMExULuW4KH?`Sg>HOIob`c@P@ zyZo_rdPBtlQ=mHs7BY@(C7K_Yni{gSv!0+%ne(l#t(8`!*PuG^yu8D1kM`6$vny;p zYcRwE%683|{%5Z2mM4?blsG8i&K(@6%fwVL3Vl>8QVbJx)VB2i_pLxaJC9BwhI8$y zlqoVO5c$kb4Zda-2YU)8Ft&qhZT2=}A)5&n{QWmde!8u$+!2b&w9#jS{z z-_E|O?o`a40bqUf$kRO`4%Kx-%Y$X{!g4 z3CiA}gycbMTu|1=1$nF|Fo${eC7AgTM^a$ck~o^av9^Srbni?jV&teX3PEesfSQaV?~#gm4EP|B*}T_Mvi~=xXYl^O^u_&OqP8`sa&{m-Eyde` zY#v&5@MD?}Xn*t4mz`r5#6Y5lY_UnJ1?B&>F%4d?+S}WIDk>^^_7L>C8oLCsPi?@T z*9N~_;J@OgE{wCqEeI%&>X&?Z!KH>~Owt;c;rNu2(1SrmE$`=qOyF z|Dct*_bGTvKluFBGNB%xLlK4~8HE>*7kVK&FeSv3`uorONQdga@IY||ds5&LMz`bR z*F+Zub6lTyjNVB~+M_jAd26>1kbt;+HAKl4rLghu?`cR$d6TDY+c_be8r?O~*S9cu znG$ZPdp>3u3k(+bl`_=Sn4sx)zwM&59A~tEY4#>aw7mcas!h-HEr>>4_38=gr8CY$ toLwHL7L;P$d;Hv=e;QeI_d011|_Pv0LiWAj}f*2n56BHB#lz9*ZXTXVhP*6Zn5W+kpu@*rQ&??H51f-NQ zgoqSlm|~Sd!4MHb%9JQU!W0995CSCmoq%n9zJ6b;^?kpWe{yqg?mcJkbM{(muY1+b zX5aFqic28~T7F>v-eV9XqXI$Fj*Az8GZ|suUIbrK@MHTdp_1kegW$&kxaENpi@_&m z@tFh&QkFficlU{iEOrmYKZ}nT7^6J(U0isZgs`2Px<(K_bB{0J)@sJb* zy;{5qoJ#sahu0@{Om>-Vlv5KwDz2`*)WQhxiS{r0d8e2!uGna6gnreo(V9&{w3oT3 z4qGjoTBPLfewM6}aO`V54iWwqg5MM09781rzghmLn4_=-X%0X+GYc;>* zMD43D8Ld}>rNrGrx^_n4MJZyZPG<BKF5XA1E$R&vJsi3KK^7N?3*{ha|0W9v zLg|?q*@Fhr6h7s~34eIO@qkWg>&+#&h`s=Vv^R8ryAXnYkXHfsD@sX! z>BDn-YXhj6k~O?+J2x$9FzEXk=Av!#hfKk>Jx|pBOT+(VSnJtmr|8wuV|5B1x6AKx zBBw@A>nSEh@Td+r@iII~6s4C*t|?{<%S9@9SPO%@5(=gHmG|DVH5-gXTj$CLl7wN0 zZEWt`FWM;6ml;@d)z)12^X()PvV%wL*YfiCs_|<)?3-sdH^sVi&G-v?P|zyXpAA)v0avlFv1S}YRQu=jvz zJYE&S?+GuWTkd@{x2?XhfS^+_KRrbm;vLDD;CNSNX+?!IZ&yvjpD*CK5F>QYy{DO( znWaRcQ$GT+ud*k(r>7?^E$zNY_weDv6BlARc%E#eFhPVtLfPg~OILwl0_F#7<&tEA zne|D&<<4#tWz#6VciqHRUUysD39v*tkNThAQme!yCPa+B-W?+nunK6!mRc0JW3wH) zL{P63So`K_Jh=W7jq)!FS1>eT68|=%x(W-C@GOWJG3J?reBC!I;FkXUa~rRFjM=bB z^-6C>Q&W>0#cFSHadB;&oWe1@Q=B`-r}ko2j*%Pu+_{2LErZZ$!@fu}4>X2#-?i*6 zfAwqrhgJ9Yat|W=u2~e!p;r%t7`aiZCte+D@hh*uD8XPU-en!U4PXy^V=<+SRx%1d_ zHS9!{O>Rp9fq^jItfqG8*OMty<79nCZ9W#^+-QyIFT&ScOGt2VkF1-fTw|qnfjH-4KU;eU0q#JtJBj_Sw^9SS~C~r)Y1CY%C{cvbT7kv&P)UMjR;$(SR1$lkj44h}{1 zdj8acKalo=Bq!PAm$`&Qz~Q>P^!1y%DI8xyS7~LX((2W#+mTnUUcFj_<9wJFVNt$> zaR;us zeIO$=>H;HznPd<%b&&>_Z^rrChaX`*MA9ZY&BPg^$_J#9LE-G_(3y0*31M+AMy9W~ zE-_AY=@yqoX?XSO7!BT#0!v8%kKQiX^a}E&4<3A_u-#QXgq$#4_3+T4LvhIa280qP z>P~c*$gS0XX4Ze2(QC+!fL=m}E(Db^}aaN>(& zUR}Lo*Dm`;AcY>kR^Mq+;z4q6bcVy>lFdH(ueky_cW`DwA79xhM7_SDfj{vpo6VN6 z1?eHsIm;4i7C!4J^YMy`in2}V`SsU?rn_2ve+}?B)PM_WMApT{C5YWwUcv$>>J=WY zZ@sTFI&xS?K|W}DVz5MP<3l20 zWMuE&+GqR2k)Frzg0jfe4-69~zCa*NH(jgVZpG%)T3v~7c_M2ygsFq&0LlAFcriVx zm4nCQ8|v%pF&k$FT5=H=WERnzn{B#@@cdySsL}Wy2%2zUNcRmAk1EY_s-xU6ohNOZ1pk_4f8Y=p=`V8W>!C18klt zDjspN-Q6=f+E_8k`ug?TaGx|@F#+42m@qY#g4`gxVuSkGZ46TTuzfmfCF%|JILahu zN*giVioH{Q_g6YSIYFJLpgHUmNGev4A8Yau>8ya6xi&i2AaOLD51K?I64Np=I$ITO zF(y}2Q&V3}F0c?zDXoH{#>X099Ko(aoj`_kHfGiX2(W)7`cP4op~LpYI2?Phl+R&s zxB<|*5a|UdOx4W0%9DXoD8-=PSnOr0b?%NE{!(@;1AdXt*7%KL7C}4TO1M$wh^>^4 z&M^e(wlJuQSL{=r&lUPt7t&--8T?P6#-HnqzdWn!%v%I<%<%{O_~5~@MrSpftc23i z(qrvIselntQf&bQ<}`0OuXv}vzP|Q*1)n78a%d~tg$D3XO{TyUcthi?w{3tktKek zVzH==X|EyTVZ{Zv%S8jWqBeb%@?ObB>(w?-0!G2%rYP~G zL2j~23YVe{7p?bh7K^^I@ay$K^7&)3BA((2%{YsK4gYw)^bea6z%8)jtZ(N1#Rpwb+_j2+qaKG27zv@u6lT~3L9#)=WNj08GRRm zzkTdl0WMKNtA1$6j|OK^uqkyA}O8Mo$RnIL->y`M|yibpI4qvGfadm*3XyMmba^K z+`M_y(a}*|uj~9SIdb!h7i((zFUiO*B~#gv6_W5LmZjD?g^)QXV%HYkFE9U^R^q0i zXKZY&1S$@+#>Qcq{VWz%zyk?S%gTxwq5+~aLCj7ScvK?A2w-94BQ697>(mG*yYdli z;B{O_qtTXS)vnw!idpm!P4yb-;lAVzS1ZFgVL)R`1kO4oB@I0n2ZX4yKYVDGOKKSm z>CReiapC;=^R>X|aPkcc3ffWPN_@owE63`s=F>Go$SG#i>f7Ba+IX%l)ss3P=k%&b zU4V9SWNGT}bn>_HY7V3xXLt4VBy|x26)+25lYktENDix1_G!-AqF4Fok>hv(G(_I! zC^4^qbz-NnY15|C`}gg9A9kEyn}JSG4K9_9te+2R?gL=^Z+KqvDqqA) z%V;Uo2jCv#0X!2R1&*~F1@-Q|o|KgOz#cDw>1Ej<5j4Dq)>#~o4VRXznwPvW(jdZ} z7YAPEtb@TAtzHBIfe9ESmVR`H1Rnifk93snFg2~tZwLTO`L^lqOjWMu*5x;V*=1xl zJNonq7uYpG@$J}gv`LVVz-J)MS8OzK^nEx))4E5W;m?vC3}G!@0x49*xc=uwx*it= zr0!!b?nCWr#`)1e;y>=Z$Qz;-66}`Fhch4PoB-i9N)}ohMSesP6eSEw;J@36dPsMxet>$wCnfPF{djzfw6ngR; z3gq@_-DmQrwdC%<*6P+pbjX%JbyP#d_CUBlIhbS+I!R&10nyq1?S|hW`RQ)dvY#4o z_Orw0;^SNVg)P|Gf>tGb8T((ddL!f^662Z& z9uL%`cx-qkmcG0%_>bo=*nebp7ADRa+GcTfjyxsI$X9#6qR&usCgR#N7k|40w&KGE zVop?k;PW5ZB37c~aJWZdZ0DQ~@NsnM>Jl>qB;(+|{oU2kgqJ&Qv1ZC%US4h#Km;ku z#%qBc7FR;7s8IAk2+saH7how)-?Szv>EEOJg_?#>475CgvutQ^V7IpT>b=58j`uzP zhzAZWxdBXw2H*!SC2!xpy*^dL;Z?t?Y5={;X<&I#ZzRSzykt}>7FdTtgRcOiL`7aG ziZCAzxzgCHIT`pcfL1)MIqssM<$j$?rIxUovF0$~TL9cPN0_Lp3g=C>Kb zN^dk$RQZ9A|L2nZGU)KuWE6FALnJgfuzqV|*+2%PU|Q4uw7U|%U%+7|BIc)+KGPiZ` zk)aZ*^Hoa1?=1A0)7@Ri@h^M(Onp5pCkO7OGIO*;_m%ebKy8`xTFOjHD%;-L z+S(HsuP@J+b!h4t>*_KyWFqEsDN{%VHgA9pc+YZdKJ$OseEdKEVg9YaR1H8=4GoRF z;?UmOs}ezQ7U#YMbbRY9Kq7wkTVz(N%q!VB$IP>tc3p7%jR6RXCpTz9uki>`$CK2}mcym4iZz}<4h(G5| zphPo6&}#wc@c~$P0WWuA;3ziyc$TD}Q+yP~^P{?`$IY*)7{*yoI{W}hdJB*qI$&k9 Kx5V<)xBmy+4Y4)= literal 7679 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 diff --git a/packages/smooth_app/test/pages/goldens/user_preferences_page-green-dark.png b/packages/smooth_app/test/pages/goldens/user_preferences_page-green-dark.png index 6a1c5f722db917ac2952f8f6fb165e7d22c5dd12..d3e58ff3e1244aba50409a1ce99a0f2f7afbfb6f 100644 GIT binary patch literal 7440 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 dY>+?-d8b63Ko@t7f}?kk8=P3 literal 7603 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 ZO+~ns*0Z_mKJZ Date: Fri, 6 May 2022 12:02:44 +0200 Subject: [PATCH 19/27] chore: New Crowdin translations to review and merge (#1762) * chore: New Crowdin translations * Apply suggestions from code review Co-authored-by: Crowdin Bot Co-authored-by: Pierre Slamich --- packages/smooth_app/lib/l10n/app_aa.arb | 4 ++++ packages/smooth_app/lib/l10n/app_af.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ak.arb | 4 ++++ packages/smooth_app/lib/l10n/app_am.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ar.arb | 6 +++++- packages/smooth_app/lib/l10n/app_as.arb | 4 ++++ packages/smooth_app/lib/l10n/app_az.arb | 4 ++++ packages/smooth_app/lib/l10n/app_be.arb | 4 ++++ packages/smooth_app/lib/l10n/app_bg.arb | 4 ++++ packages/smooth_app/lib/l10n/app_bm.arb | 4 ++++ packages/smooth_app/lib/l10n/app_bn.arb | 4 ++++ packages/smooth_app/lib/l10n/app_bo.arb | 4 ++++ packages/smooth_app/lib/l10n/app_br.arb | 4 ++++ packages/smooth_app/lib/l10n/app_bs.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ca.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ce.arb | 4 ++++ packages/smooth_app/lib/l10n/app_co.arb | 4 ++++ packages/smooth_app/lib/l10n/app_cs.arb | 4 ++++ packages/smooth_app/lib/l10n/app_cv.arb | 4 ++++ packages/smooth_app/lib/l10n/app_cy.arb | 4 ++++ packages/smooth_app/lib/l10n/app_da.arb | 4 ++++ packages/smooth_app/lib/l10n/app_de.arb | 4 ++++ packages/smooth_app/lib/l10n/app_el.arb | 4 ++++ packages/smooth_app/lib/l10n/app_en.arb | 1 - packages/smooth_app/lib/l10n/app_eo.arb | 4 ++++ packages/smooth_app/lib/l10n/app_es.arb | 4 ++++ packages/smooth_app/lib/l10n/app_et.arb | 4 ++++ packages/smooth_app/lib/l10n/app_eu.arb | 4 ++++ packages/smooth_app/lib/l10n/app_fa.arb | 4 ++++ packages/smooth_app/lib/l10n/app_fi.arb | 4 ++++ packages/smooth_app/lib/l10n/app_fil.arb | 4 ++++ packages/smooth_app/lib/l10n/app_fo.arb | 4 ++++ packages/smooth_app/lib/l10n/app_fr.arb | 6 +++++- packages/smooth_app/lib/l10n/app_ga.arb | 4 ++++ packages/smooth_app/lib/l10n/app_gd.arb | 4 ++++ packages/smooth_app/lib/l10n/app_gl.arb | 4 ++++ packages/smooth_app/lib/l10n/app_gu.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ha.arb | 4 ++++ packages/smooth_app/lib/l10n/app_he.arb | 4 ++++ packages/smooth_app/lib/l10n/app_hi.arb | 4 ++++ packages/smooth_app/lib/l10n/app_hr.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ht.arb | 4 ++++ packages/smooth_app/lib/l10n/app_hu.arb | 4 ++++ packages/smooth_app/lib/l10n/app_hy.arb | 4 ++++ packages/smooth_app/lib/l10n/app_id.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ii.arb | 4 ++++ packages/smooth_app/lib/l10n/app_is.arb | 4 ++++ packages/smooth_app/lib/l10n/app_it.arb | 4 ++++ packages/smooth_app/lib/l10n/app_iu.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ja.arb | 4 ++++ packages/smooth_app/lib/l10n/app_jv.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ka.arb | 4 ++++ packages/smooth_app/lib/l10n/app_kk.arb | 4 ++++ packages/smooth_app/lib/l10n/app_km.arb | 4 ++++ packages/smooth_app/lib/l10n/app_kn.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ko.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ku.arb | 4 ++++ packages/smooth_app/lib/l10n/app_kw.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ky.arb | 4 ++++ packages/smooth_app/lib/l10n/app_la.arb | 4 ++++ packages/smooth_app/lib/l10n/app_lb.arb | 4 ++++ packages/smooth_app/lib/l10n/app_lo.arb | 4 ++++ packages/smooth_app/lib/l10n/app_lt.arb | 4 ++++ packages/smooth_app/lib/l10n/app_lv.arb | 4 ++++ packages/smooth_app/lib/l10n/app_mg.arb | 4 ++++ packages/smooth_app/lib/l10n/app_mi.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ml.arb | 4 ++++ packages/smooth_app/lib/l10n/app_mn.arb | 4 ++++ packages/smooth_app/lib/l10n/app_mr.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ms.arb | 4 ++++ packages/smooth_app/lib/l10n/app_mt.arb | 4 ++++ packages/smooth_app/lib/l10n/app_my.arb | 4 ++++ packages/smooth_app/lib/l10n/app_nb.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ne.arb | 4 ++++ packages/smooth_app/lib/l10n/app_nl.arb | 4 ++++ packages/smooth_app/lib/l10n/app_nn.arb | 4 ++++ packages/smooth_app/lib/l10n/app_no.arb | 4 ++++ packages/smooth_app/lib/l10n/app_nr.arb | 4 ++++ packages/smooth_app/lib/l10n/app_oc.arb | 4 ++++ packages/smooth_app/lib/l10n/app_pa.arb | 4 ++++ packages/smooth_app/lib/l10n/app_pl.arb | 4 ++++ packages/smooth_app/lib/l10n/app_pt.arb | 4 ++++ packages/smooth_app/lib/l10n/app_qu.arb | 4 ++++ packages/smooth_app/lib/l10n/app_rm.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ro.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ru.arb | 4 ++++ packages/smooth_app/lib/l10n/app_sa.arb | 4 ++++ packages/smooth_app/lib/l10n/app_sc.arb | 4 ++++ packages/smooth_app/lib/l10n/app_sd.arb | 4 ++++ packages/smooth_app/lib/l10n/app_sg.arb | 4 ++++ packages/smooth_app/lib/l10n/app_si.arb | 4 ++++ packages/smooth_app/lib/l10n/app_sk.arb | 4 ++++ packages/smooth_app/lib/l10n/app_sl.arb | 4 ++++ packages/smooth_app/lib/l10n/app_sn.arb | 4 ++++ packages/smooth_app/lib/l10n/app_so.arb | 4 ++++ packages/smooth_app/lib/l10n/app_sq.arb | 4 ++++ packages/smooth_app/lib/l10n/app_sr.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ss.arb | 4 ++++ packages/smooth_app/lib/l10n/app_st.arb | 4 ++++ packages/smooth_app/lib/l10n/app_sv.arb | 4 ++++ packages/smooth_app/lib/l10n/app_sw.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ta.arb | 4 ++++ packages/smooth_app/lib/l10n/app_te.arb | 4 ++++ packages/smooth_app/lib/l10n/app_tg.arb | 4 ++++ packages/smooth_app/lib/l10n/app_th.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ti.arb | 4 ++++ packages/smooth_app/lib/l10n/app_tl.arb | 4 ++++ packages/smooth_app/lib/l10n/app_tn.arb | 4 ++++ packages/smooth_app/lib/l10n/app_tr.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ts.arb | 4 ++++ packages/smooth_app/lib/l10n/app_tt.arb | 4 ++++ packages/smooth_app/lib/l10n/app_tw.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ty.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ug.arb | 4 ++++ packages/smooth_app/lib/l10n/app_uk.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ur.arb | 4 ++++ packages/smooth_app/lib/l10n/app_uz.arb | 4 ++++ packages/smooth_app/lib/l10n/app_ve.arb | 4 ++++ packages/smooth_app/lib/l10n/app_vi.arb | 4 ++++ packages/smooth_app/lib/l10n/app_wa.arb | 4 ++++ packages/smooth_app/lib/l10n/app_wo.arb | 4 ++++ packages/smooth_app/lib/l10n/app_xh.arb | 4 ++++ packages/smooth_app/lib/l10n/app_yo.arb | 4 ++++ packages/smooth_app/lib/l10n/app_zh.arb | 4 ++++ packages/smooth_app/lib/l10n/app_zu.arb | 4 ++++ 125 files changed, 498 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_aa.arb b/packages/smooth_app/lib/l10n/app_aa.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_aa.arb +++ b/packages/smooth_app/lib/l10n/app_aa.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_af.arb b/packages/smooth_app/lib/l10n/app_af.arb index 40414dfb6e4..dfafeb21634 100644 --- a/packages/smooth_app/lib/l10n/app_af.arb +++ b/packages/smooth_app/lib/l10n/app_af.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ak.arb b/packages/smooth_app/lib/l10n/app_ak.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_ak.arb +++ b/packages/smooth_app/lib/l10n/app_ak.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_am.arb b/packages/smooth_app/lib/l10n/app_am.arb index 7f073d3c332..03dfc16c805 100644 --- a/packages/smooth_app/lib/l10n/app_am.arb +++ b/packages/smooth_app/lib/l10n/app_am.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ar.arb b/packages/smooth_app/lib/l10n/app_ar.arb index 855ea78c43b..d93db30a1ac 100644 --- a/packages/smooth_app/lib/l10n/app_ar.arb +++ b/packages/smooth_app/lib/l10n/app_ar.arb @@ -1,5 +1,5 @@ { - "app_name": "OpenFoodFactsAr", + "app_name": "OpenFoodFacts", "@Utils": {}, "yes": "نعم", "@yes": {}, @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_as.arb b/packages/smooth_app/lib/l10n/app_as.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_as.arb +++ b/packages/smooth_app/lib/l10n/app_as.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_az.arb b/packages/smooth_app/lib/l10n/app_az.arb index 33bb80800eb..d725960efc2 100644 --- a/packages/smooth_app/lib/l10n/app_az.arb +++ b/packages/smooth_app/lib/l10n/app_az.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_be.arb b/packages/smooth_app/lib/l10n/app_be.arb index 0e0e124354f..352a8cfdd29 100644 --- a/packages/smooth_app/lib/l10n/app_be.arb +++ b/packages/smooth_app/lib/l10n/app_be.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bg.arb b/packages/smooth_app/lib/l10n/app_bg.arb index b15c41ae82d..3341253298d 100644 --- a/packages/smooth_app/lib/l10n/app_bg.arb +++ b/packages/smooth_app/lib/l10n/app_bg.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "Това е същото име", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bm.arb b/packages/smooth_app/lib/l10n/app_bm.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_bm.arb +++ b/packages/smooth_app/lib/l10n/app_bm.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bn.arb b/packages/smooth_app/lib/l10n/app_bn.arb index 7c7bd3363b6..ef156e39025 100644 --- a/packages/smooth_app/lib/l10n/app_bn.arb +++ b/packages/smooth_app/lib/l10n/app_bn.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bo.arb b/packages/smooth_app/lib/l10n/app_bo.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_bo.arb +++ b/packages/smooth_app/lib/l10n/app_bo.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_br.arb b/packages/smooth_app/lib/l10n/app_br.arb index e94886cdee2..8b8444b87f0 100644 --- a/packages/smooth_app/lib/l10n/app_br.arb +++ b/packages/smooth_app/lib/l10n/app_br.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bs.arb b/packages/smooth_app/lib/l10n/app_bs.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_bs.arb +++ b/packages/smooth_app/lib/l10n/app_bs.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ca.arb b/packages/smooth_app/lib/l10n/app_ca.arb index b8b9a7345c8..e1b0b71c8fc 100644 --- a/packages/smooth_app/lib/l10n/app_ca.arb +++ b/packages/smooth_app/lib/l10n/app_ca.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ce.arb b/packages/smooth_app/lib/l10n/app_ce.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_ce.arb +++ b/packages/smooth_app/lib/l10n/app_ce.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_co.arb b/packages/smooth_app/lib/l10n/app_co.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_co.arb +++ b/packages/smooth_app/lib/l10n/app_co.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cs.arb b/packages/smooth_app/lib/l10n/app_cs.arb index e5402bfbb0f..1711c633984 100644 --- a/packages/smooth_app/lib/l10n/app_cs.arb +++ b/packages/smooth_app/lib/l10n/app_cs.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cv.arb b/packages/smooth_app/lib/l10n/app_cv.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_cv.arb +++ b/packages/smooth_app/lib/l10n/app_cv.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cy.arb b/packages/smooth_app/lib/l10n/app_cy.arb index f0b3ba14f98..4b6b4d5e4c2 100644 --- a/packages/smooth_app/lib/l10n/app_cy.arb +++ b/packages/smooth_app/lib/l10n/app_cy.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_da.arb b/packages/smooth_app/lib/l10n/app_da.arb index 8c0b436243f..a6d209820a1 100644 --- a/packages/smooth_app/lib/l10n/app_da.arb +++ b/packages/smooth_app/lib/l10n/app_da.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "Det er samme navn", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_de.arb b/packages/smooth_app/lib/l10n/app_de.arb index 65e6aa9343e..883b14e134a 100644 --- a/packages/smooth_app/lib/l10n/app_de.arb +++ b/packages/smooth_app/lib/l10n/app_de.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "Das ist derselbe Name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_el.arb b/packages/smooth_app/lib/l10n/app_el.arb index 96092569740..f02372d2611 100644 --- a/packages/smooth_app/lib/l10n/app_el.arb +++ b/packages/smooth_app/lib/l10n/app_el.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "Αυτό είναι το ίδιο όνομα", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 44ae009b3b6..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -893,5 +893,4 @@ "@confirm_clear": { "description": "Asking about whether to clear the list or not" } - } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_eo.arb b/packages/smooth_app/lib/l10n/app_eo.arb index 76566bd57db..82f75078964 100644 --- a/packages/smooth_app/lib/l10n/app_eo.arb +++ b/packages/smooth_app/lib/l10n/app_eo.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_es.arb b/packages/smooth_app/lib/l10n/app_es.arb index 0696e434dd5..65a43fd96c2 100644 --- a/packages/smooth_app/lib/l10n/app_es.arb +++ b/packages/smooth_app/lib/l10n/app_es.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "Ese es el mismo nombre", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_et.arb b/packages/smooth_app/lib/l10n/app_et.arb index bc4fc57c958..8a545c3c0fa 100644 --- a/packages/smooth_app/lib/l10n/app_et.arb +++ b/packages/smooth_app/lib/l10n/app_et.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_eu.arb b/packages/smooth_app/lib/l10n/app_eu.arb index 49c5cb477cf..d1bcf7a7699 100644 --- a/packages/smooth_app/lib/l10n/app_eu.arb +++ b/packages/smooth_app/lib/l10n/app_eu.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fa.arb b/packages/smooth_app/lib/l10n/app_fa.arb index 5856d24d26f..05cec8a7f59 100644 --- a/packages/smooth_app/lib/l10n/app_fa.arb +++ b/packages/smooth_app/lib/l10n/app_fa.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fi.arb b/packages/smooth_app/lib/l10n/app_fi.arb index 07b9876957b..58e55f45534 100644 --- a/packages/smooth_app/lib/l10n/app_fi.arb +++ b/packages/smooth_app/lib/l10n/app_fi.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fil.arb b/packages/smooth_app/lib/l10n/app_fil.arb index d39005d27f6..212ee3d9ce0 100644 --- a/packages/smooth_app/lib/l10n/app_fil.arb +++ b/packages/smooth_app/lib/l10n/app_fil.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fo.arb b/packages/smooth_app/lib/l10n/app_fo.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_fo.arb +++ b/packages/smooth_app/lib/l10n/app_fo.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fr.arb b/packages/smooth_app/lib/l10n/app_fr.arb index 9ffdd1d718b..e4edda65402 100644 --- a/packages/smooth_app/lib/l10n/app_fr.arb +++ b/packages/smooth_app/lib/l10n/app_fr.arb @@ -1,5 +1,5 @@ { - "app_name": "OpenFoodFactsFr", + "app_name": "OpenFoodFacts", "@Utils": {}, "yes": "Oui", "@yes": {}, @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ga.arb b/packages/smooth_app/lib/l10n/app_ga.arb index 537d47f26b9..cad9b848ef5 100644 --- a/packages/smooth_app/lib/l10n/app_ga.arb +++ b/packages/smooth_app/lib/l10n/app_ga.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gd.arb b/packages/smooth_app/lib/l10n/app_gd.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_gd.arb +++ b/packages/smooth_app/lib/l10n/app_gd.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gl.arb b/packages/smooth_app/lib/l10n/app_gl.arb index 914905e8931..7e742b24c3c 100644 --- a/packages/smooth_app/lib/l10n/app_gl.arb +++ b/packages/smooth_app/lib/l10n/app_gl.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gu.arb b/packages/smooth_app/lib/l10n/app_gu.arb index 836d3f21b83..0856532f7aa 100644 --- a/packages/smooth_app/lib/l10n/app_gu.arb +++ b/packages/smooth_app/lib/l10n/app_gu.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ha.arb b/packages/smooth_app/lib/l10n/app_ha.arb index 1082fb5c275..2893875cd0a 100644 --- a/packages/smooth_app/lib/l10n/app_ha.arb +++ b/packages/smooth_app/lib/l10n/app_ha.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_he.arb b/packages/smooth_app/lib/l10n/app_he.arb index f9413a7577a..22f1f442e39 100644 --- a/packages/smooth_app/lib/l10n/app_he.arb +++ b/packages/smooth_app/lib/l10n/app_he.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "זה אותו השם", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hi.arb b/packages/smooth_app/lib/l10n/app_hi.arb index 309b23ed350..d950cc6e367 100644 --- a/packages/smooth_app/lib/l10n/app_hi.arb +++ b/packages/smooth_app/lib/l10n/app_hi.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hr.arb b/packages/smooth_app/lib/l10n/app_hr.arb index 11b7ec288ef..ff2e0cd7a64 100644 --- a/packages/smooth_app/lib/l10n/app_hr.arb +++ b/packages/smooth_app/lib/l10n/app_hr.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ht.arb b/packages/smooth_app/lib/l10n/app_ht.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_ht.arb +++ b/packages/smooth_app/lib/l10n/app_ht.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hu.arb b/packages/smooth_app/lib/l10n/app_hu.arb index 365491461e4..c58fcc07602 100644 --- a/packages/smooth_app/lib/l10n/app_hu.arb +++ b/packages/smooth_app/lib/l10n/app_hu.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hy.arb b/packages/smooth_app/lib/l10n/app_hy.arb index 41ca39c7d71..817287a762f 100644 --- a/packages/smooth_app/lib/l10n/app_hy.arb +++ b/packages/smooth_app/lib/l10n/app_hy.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_id.arb b/packages/smooth_app/lib/l10n/app_id.arb index d5d19ba86e8..94b49fd78dd 100644 --- a/packages/smooth_app/lib/l10n/app_id.arb +++ b/packages/smooth_app/lib/l10n/app_id.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ii.arb b/packages/smooth_app/lib/l10n/app_ii.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_ii.arb +++ b/packages/smooth_app/lib/l10n/app_ii.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_is.arb b/packages/smooth_app/lib/l10n/app_is.arb index 9994dc6559e..ef4742d5883 100644 --- a/packages/smooth_app/lib/l10n/app_is.arb +++ b/packages/smooth_app/lib/l10n/app_is.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_it.arb b/packages/smooth_app/lib/l10n/app_it.arb index aebd58000ef..03a54b2bddd 100644 --- a/packages/smooth_app/lib/l10n/app_it.arb +++ b/packages/smooth_app/lib/l10n/app_it.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "Questo è lo stesso nome", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_iu.arb b/packages/smooth_app/lib/l10n/app_iu.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_iu.arb +++ b/packages/smooth_app/lib/l10n/app_iu.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ja.arb b/packages/smooth_app/lib/l10n/app_ja.arb index cb4cc45b91d..3464d67c341 100644 --- a/packages/smooth_app/lib/l10n/app_ja.arb +++ b/packages/smooth_app/lib/l10n/app_ja.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_jv.arb b/packages/smooth_app/lib/l10n/app_jv.arb index 7046f69fa0a..963c19f19db 100644 --- a/packages/smooth_app/lib/l10n/app_jv.arb +++ b/packages/smooth_app/lib/l10n/app_jv.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ka.arb b/packages/smooth_app/lib/l10n/app_ka.arb index 4b477e81190..32b38491687 100644 --- a/packages/smooth_app/lib/l10n/app_ka.arb +++ b/packages/smooth_app/lib/l10n/app_ka.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kk.arb b/packages/smooth_app/lib/l10n/app_kk.arb index 999100aba6b..66f1d970810 100644 --- a/packages/smooth_app/lib/l10n/app_kk.arb +++ b/packages/smooth_app/lib/l10n/app_kk.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_km.arb b/packages/smooth_app/lib/l10n/app_km.arb index e46c10a3aa5..e3a9fbe5ae7 100644 --- a/packages/smooth_app/lib/l10n/app_km.arb +++ b/packages/smooth_app/lib/l10n/app_km.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kn.arb b/packages/smooth_app/lib/l10n/app_kn.arb index 5fdd75dc595..2dedb80e686 100644 --- a/packages/smooth_app/lib/l10n/app_kn.arb +++ b/packages/smooth_app/lib/l10n/app_kn.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ko.arb b/packages/smooth_app/lib/l10n/app_ko.arb index a52f7d20f75..8dd53ec3757 100644 --- a/packages/smooth_app/lib/l10n/app_ko.arb +++ b/packages/smooth_app/lib/l10n/app_ko.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ku.arb b/packages/smooth_app/lib/l10n/app_ku.arb index 72b4f80424d..3f00690f63e 100644 --- a/packages/smooth_app/lib/l10n/app_ku.arb +++ b/packages/smooth_app/lib/l10n/app_ku.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kw.arb b/packages/smooth_app/lib/l10n/app_kw.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_kw.arb +++ b/packages/smooth_app/lib/l10n/app_kw.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ky.arb b/packages/smooth_app/lib/l10n/app_ky.arb index 6ce0f687f16..2a496825c85 100644 --- a/packages/smooth_app/lib/l10n/app_ky.arb +++ b/packages/smooth_app/lib/l10n/app_ky.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_la.arb b/packages/smooth_app/lib/l10n/app_la.arb index 1b2babf2c40..16e3a0a787d 100644 --- a/packages/smooth_app/lib/l10n/app_la.arb +++ b/packages/smooth_app/lib/l10n/app_la.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lb.arb b/packages/smooth_app/lib/l10n/app_lb.arb index 9290eccfcc7..f1a46a6442a 100644 --- a/packages/smooth_app/lib/l10n/app_lb.arb +++ b/packages/smooth_app/lib/l10n/app_lb.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lo.arb b/packages/smooth_app/lib/l10n/app_lo.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_lo.arb +++ b/packages/smooth_app/lib/l10n/app_lo.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lt.arb b/packages/smooth_app/lib/l10n/app_lt.arb index 17f7d8c17f0..cfce3056351 100644 --- a/packages/smooth_app/lib/l10n/app_lt.arb +++ b/packages/smooth_app/lib/l10n/app_lt.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lv.arb b/packages/smooth_app/lib/l10n/app_lv.arb index 3bca4df1ece..b5daea0a6d4 100644 --- a/packages/smooth_app/lib/l10n/app_lv.arb +++ b/packages/smooth_app/lib/l10n/app_lv.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mg.arb b/packages/smooth_app/lib/l10n/app_mg.arb index d7daaba0e45..004e70611eb 100644 --- a/packages/smooth_app/lib/l10n/app_mg.arb +++ b/packages/smooth_app/lib/l10n/app_mg.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mi.arb b/packages/smooth_app/lib/l10n/app_mi.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_mi.arb +++ b/packages/smooth_app/lib/l10n/app_mi.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ml.arb b/packages/smooth_app/lib/l10n/app_ml.arb index 13e522f60c2..0f708a2bbdf 100644 --- a/packages/smooth_app/lib/l10n/app_ml.arb +++ b/packages/smooth_app/lib/l10n/app_ml.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mn.arb b/packages/smooth_app/lib/l10n/app_mn.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_mn.arb +++ b/packages/smooth_app/lib/l10n/app_mn.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mr.arb b/packages/smooth_app/lib/l10n/app_mr.arb index cc2f6f837af..1931e3f6198 100644 --- a/packages/smooth_app/lib/l10n/app_mr.arb +++ b/packages/smooth_app/lib/l10n/app_mr.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ms.arb b/packages/smooth_app/lib/l10n/app_ms.arb index 71e457496bd..a9fc25536b8 100644 --- a/packages/smooth_app/lib/l10n/app_ms.arb +++ b/packages/smooth_app/lib/l10n/app_ms.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mt.arb b/packages/smooth_app/lib/l10n/app_mt.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_mt.arb +++ b/packages/smooth_app/lib/l10n/app_mt.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_my.arb b/packages/smooth_app/lib/l10n/app_my.arb index 455e21e8f6d..2eb996a19da 100644 --- a/packages/smooth_app/lib/l10n/app_my.arb +++ b/packages/smooth_app/lib/l10n/app_my.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nb.arb b/packages/smooth_app/lib/l10n/app_nb.arb index 06792dc35fa..223ca6ff66b 100644 --- a/packages/smooth_app/lib/l10n/app_nb.arb +++ b/packages/smooth_app/lib/l10n/app_nb.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ne.arb b/packages/smooth_app/lib/l10n/app_ne.arb index cf5794ed8b6..dc9da850aa4 100644 --- a/packages/smooth_app/lib/l10n/app_ne.arb +++ b/packages/smooth_app/lib/l10n/app_ne.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nl.arb b/packages/smooth_app/lib/l10n/app_nl.arb index 442eeaa96d7..ff75d8a7b15 100644 --- a/packages/smooth_app/lib/l10n/app_nl.arb +++ b/packages/smooth_app/lib/l10n/app_nl.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nn.arb b/packages/smooth_app/lib/l10n/app_nn.arb index 1b5a255f959..7811a740989 100644 --- a/packages/smooth_app/lib/l10n/app_nn.arb +++ b/packages/smooth_app/lib/l10n/app_nn.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_no.arb b/packages/smooth_app/lib/l10n/app_no.arb index 1b5a255f959..7811a740989 100644 --- a/packages/smooth_app/lib/l10n/app_no.arb +++ b/packages/smooth_app/lib/l10n/app_no.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nr.arb b/packages/smooth_app/lib/l10n/app_nr.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_nr.arb +++ b/packages/smooth_app/lib/l10n/app_nr.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_oc.arb b/packages/smooth_app/lib/l10n/app_oc.arb index 7990f4f22a3..982a2c933d6 100644 --- a/packages/smooth_app/lib/l10n/app_oc.arb +++ b/packages/smooth_app/lib/l10n/app_oc.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pa.arb b/packages/smooth_app/lib/l10n/app_pa.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_pa.arb +++ b/packages/smooth_app/lib/l10n/app_pa.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pl.arb b/packages/smooth_app/lib/l10n/app_pl.arb index 7e15af1b5cc..3150cb2599a 100644 --- a/packages/smooth_app/lib/l10n/app_pl.arb +++ b/packages/smooth_app/lib/l10n/app_pl.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pt.arb b/packages/smooth_app/lib/l10n/app_pt.arb index ddf609f7935..c16b2e2d62e 100644 --- a/packages/smooth_app/lib/l10n/app_pt.arb +++ b/packages/smooth_app/lib/l10n/app_pt.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_qu.arb b/packages/smooth_app/lib/l10n/app_qu.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_qu.arb +++ b/packages/smooth_app/lib/l10n/app_qu.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_rm.arb b/packages/smooth_app/lib/l10n/app_rm.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_rm.arb +++ b/packages/smooth_app/lib/l10n/app_rm.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ro.arb b/packages/smooth_app/lib/l10n/app_ro.arb index 36b02daecd5..850012238c2 100644 --- a/packages/smooth_app/lib/l10n/app_ro.arb +++ b/packages/smooth_app/lib/l10n/app_ro.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "Este același nume", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ru.arb b/packages/smooth_app/lib/l10n/app_ru.arb index 818297a1562..32fb74d6ef5 100644 --- a/packages/smooth_app/lib/l10n/app_ru.arb +++ b/packages/smooth_app/lib/l10n/app_ru.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "Это то же самое название", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sa.arb b/packages/smooth_app/lib/l10n/app_sa.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_sa.arb +++ b/packages/smooth_app/lib/l10n/app_sa.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sc.arb b/packages/smooth_app/lib/l10n/app_sc.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_sc.arb +++ b/packages/smooth_app/lib/l10n/app_sc.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sd.arb b/packages/smooth_app/lib/l10n/app_sd.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_sd.arb +++ b/packages/smooth_app/lib/l10n/app_sd.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sg.arb b/packages/smooth_app/lib/l10n/app_sg.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_sg.arb +++ b/packages/smooth_app/lib/l10n/app_sg.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_si.arb b/packages/smooth_app/lib/l10n/app_si.arb index 621f835c602..01b4b4294ea 100644 --- a/packages/smooth_app/lib/l10n/app_si.arb +++ b/packages/smooth_app/lib/l10n/app_si.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sk.arb b/packages/smooth_app/lib/l10n/app_sk.arb index 842f3c51b90..f88668316d1 100644 --- a/packages/smooth_app/lib/l10n/app_sk.arb +++ b/packages/smooth_app/lib/l10n/app_sk.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sl.arb b/packages/smooth_app/lib/l10n/app_sl.arb index cba1dcfd41b..a2e59df22b3 100644 --- a/packages/smooth_app/lib/l10n/app_sl.arb +++ b/packages/smooth_app/lib/l10n/app_sl.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sn.arb b/packages/smooth_app/lib/l10n/app_sn.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_sn.arb +++ b/packages/smooth_app/lib/l10n/app_sn.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_so.arb b/packages/smooth_app/lib/l10n/app_so.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_so.arb +++ b/packages/smooth_app/lib/l10n/app_so.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sq.arb b/packages/smooth_app/lib/l10n/app_sq.arb index 67ef795f6e6..31a2e8d5959 100644 --- a/packages/smooth_app/lib/l10n/app_sq.arb +++ b/packages/smooth_app/lib/l10n/app_sq.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sr.arb b/packages/smooth_app/lib/l10n/app_sr.arb index 88397853f27..7dfe78bb3aa 100644 --- a/packages/smooth_app/lib/l10n/app_sr.arb +++ b/packages/smooth_app/lib/l10n/app_sr.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ss.arb b/packages/smooth_app/lib/l10n/app_ss.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_ss.arb +++ b/packages/smooth_app/lib/l10n/app_ss.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_st.arb b/packages/smooth_app/lib/l10n/app_st.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_st.arb +++ b/packages/smooth_app/lib/l10n/app_st.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sv.arb b/packages/smooth_app/lib/l10n/app_sv.arb index 0135771c0c2..04e4e60a481 100644 --- a/packages/smooth_app/lib/l10n/app_sv.arb +++ b/packages/smooth_app/lib/l10n/app_sv.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sw.arb b/packages/smooth_app/lib/l10n/app_sw.arb index c707b3151d8..47c19f3399b 100644 --- a/packages/smooth_app/lib/l10n/app_sw.arb +++ b/packages/smooth_app/lib/l10n/app_sw.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ta.arb b/packages/smooth_app/lib/l10n/app_ta.arb index efc7c00e38f..c2f872acbee 100644 --- a/packages/smooth_app/lib/l10n/app_ta.arb +++ b/packages/smooth_app/lib/l10n/app_ta.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_te.arb b/packages/smooth_app/lib/l10n/app_te.arb index c7d23310dac..fc29ff7499a 100644 --- a/packages/smooth_app/lib/l10n/app_te.arb +++ b/packages/smooth_app/lib/l10n/app_te.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tg.arb b/packages/smooth_app/lib/l10n/app_tg.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_tg.arb +++ b/packages/smooth_app/lib/l10n/app_tg.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_th.arb b/packages/smooth_app/lib/l10n/app_th.arb index b74034272fa..ff399c8e231 100644 --- a/packages/smooth_app/lib/l10n/app_th.arb +++ b/packages/smooth_app/lib/l10n/app_th.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ti.arb b/packages/smooth_app/lib/l10n/app_ti.arb index 49df47470c6..db7997ac278 100644 --- a/packages/smooth_app/lib/l10n/app_ti.arb +++ b/packages/smooth_app/lib/l10n/app_ti.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tl.arb b/packages/smooth_app/lib/l10n/app_tl.arb index c4be84b70bd..fce803c0d87 100644 --- a/packages/smooth_app/lib/l10n/app_tl.arb +++ b/packages/smooth_app/lib/l10n/app_tl.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tn.arb b/packages/smooth_app/lib/l10n/app_tn.arb index c67f391d53c..be17fe8efaa 100644 --- a/packages/smooth_app/lib/l10n/app_tn.arb +++ b/packages/smooth_app/lib/l10n/app_tn.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tr.arb b/packages/smooth_app/lib/l10n/app_tr.arb index 432717a650d..c18d10f4fb0 100644 --- a/packages/smooth_app/lib/l10n/app_tr.arb +++ b/packages/smooth_app/lib/l10n/app_tr.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "Bu aynı isim", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ts.arb b/packages/smooth_app/lib/l10n/app_ts.arb index c67f391d53c..be17fe8efaa 100644 --- a/packages/smooth_app/lib/l10n/app_ts.arb +++ b/packages/smooth_app/lib/l10n/app_ts.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tt.arb b/packages/smooth_app/lib/l10n/app_tt.arb index 3e2013caaa4..d515032309a 100644 --- a/packages/smooth_app/lib/l10n/app_tt.arb +++ b/packages/smooth_app/lib/l10n/app_tt.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tw.arb b/packages/smooth_app/lib/l10n/app_tw.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_tw.arb +++ b/packages/smooth_app/lib/l10n/app_tw.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ty.arb b/packages/smooth_app/lib/l10n/app_ty.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_ty.arb +++ b/packages/smooth_app/lib/l10n/app_ty.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ug.arb b/packages/smooth_app/lib/l10n/app_ug.arb index db017ab75d1..19908d37d1e 100644 --- a/packages/smooth_app/lib/l10n/app_ug.arb +++ b/packages/smooth_app/lib/l10n/app_ug.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_uk.arb b/packages/smooth_app/lib/l10n/app_uk.arb index 65317667257..6fa1d40f566 100644 --- a/packages/smooth_app/lib/l10n/app_uk.arb +++ b/packages/smooth_app/lib/l10n/app_uk.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ur.arb b/packages/smooth_app/lib/l10n/app_ur.arb index 60873c96624..a8e808ffd93 100644 --- a/packages/smooth_app/lib/l10n/app_ur.arb +++ b/packages/smooth_app/lib/l10n/app_ur.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_uz.arb b/packages/smooth_app/lib/l10n/app_uz.arb index e186d61c0d0..c3bb0331eac 100644 --- a/packages/smooth_app/lib/l10n/app_uz.arb +++ b/packages/smooth_app/lib/l10n/app_uz.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ve.arb b/packages/smooth_app/lib/l10n/app_ve.arb index c67f391d53c..be17fe8efaa 100644 --- a/packages/smooth_app/lib/l10n/app_ve.arb +++ b/packages/smooth_app/lib/l10n/app_ve.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_vi.arb b/packages/smooth_app/lib/l10n/app_vi.arb index 16961a8f652..0ffa29dd870 100644 --- a/packages/smooth_app/lib/l10n/app_vi.arb +++ b/packages/smooth_app/lib/l10n/app_vi.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "Tên bị trùng", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_wa.arb b/packages/smooth_app/lib/l10n/app_wa.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_wa.arb +++ b/packages/smooth_app/lib/l10n/app_wa.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_wo.arb b/packages/smooth_app/lib/l10n/app_wo.arb index c67f391d53c..be17fe8efaa 100644 --- a/packages/smooth_app/lib/l10n/app_wo.arb +++ b/packages/smooth_app/lib/l10n/app_wo.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_xh.arb b/packages/smooth_app/lib/l10n/app_xh.arb index 30202d0790e..569bf9d9a75 100644 --- a/packages/smooth_app/lib/l10n/app_xh.arb +++ b/packages/smooth_app/lib/l10n/app_xh.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_yo.arb b/packages/smooth_app/lib/l10n/app_yo.arb index f66d4690a1a..d5084dd7cbb 100644 --- a/packages/smooth_app/lib/l10n/app_yo.arb +++ b/packages/smooth_app/lib/l10n/app_yo.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_zh.arb b/packages/smooth_app/lib/l10n/app_zh.arb index cf5394aedd4..176063805a3 100644 --- a/packages/smooth_app/lib/l10n/app_zh.arb +++ b/packages/smooth_app/lib/l10n/app_zh.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_zu.arb b/packages/smooth_app/lib/l10n/app_zu.arb index 1626fc9f190..01fd504d3ea 100644 --- a/packages/smooth_app/lib/l10n/app_zu.arb +++ b/packages/smooth_app/lib/l10n/app_zu.arb @@ -888,5 +888,9 @@ "user_list_name_error_same": "That is the same name", "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" + }, + "confirm_clear": "Do you really want to clear?", + "@confirm_clear": { + "description": "Asking about whether to clear the list or not" } } \ No newline at end of file From 4b053d8af1c8662a50c8963572f9132a2176f1e0 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Fri, 6 May 2022 12:30:59 +0200 Subject: [PATCH 20/27] fix: #1673 - force preferences refresh when we changed languages (#1759) Impacted file: * `product_preferences.dart` --- .../lib/data_models/product_preferences.dart | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/smooth_app/lib/data_models/product_preferences.dart b/packages/smooth_app/lib/data_models/product_preferences.dart index cddfbce3cbe..124dc2390f1 100644 --- a/packages/smooth_app/lib/data_models/product_preferences.dart +++ b/packages/smooth_app/lib/data_models/product_preferences.dart @@ -108,19 +108,25 @@ class ProductPreferences extends ProductPreferencesManager with ChangeNotifier { /// The downloaded strings are automatically stored in the database. Future _loadFromNetwork(String languageCode) async { try { + final bool differentLanguages; + if (daoString != null) { + final String? latestLanguage = + await daoString!.get(_DAO_STRING_KEY_LANGUAGE); + differentLanguages = latestLanguage != languageCode; + } else { + differentLanguages = true; + } final String importanceUrl = AvailablePreferenceImportances.getUrl(languageCode); final String attributeGroupUrl = AvailableAttributeGroups.getUrl(languageCode); - final DownloadableString downloadableImportance; - downloadableImportance = + final DownloadableString downloadableImportance = DownloadableString(Uri.parse(importanceUrl), dao: daoString); final bool differentImportance = await downloadableImportance.download(); final DownloadableString downloadableAttributes = DownloadableString(Uri.parse(attributeGroupUrl), dao: daoString); final bool differentAttributes = await downloadableAttributes.download(); - // the downloaded values are identical to what was stored locally. - if ((!differentImportance) && (!differentAttributes)) { + if (!(differentImportance || differentAttributes || differentLanguages)) { return false; } final String preferenceImportancesString = downloadableImportance.value!; From 2a18366486cffd65a37c4afca9ca70d43cb310cb Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 6 May 2022 14:11:43 +0200 Subject: [PATCH 21/27] ContinuousScanModel injected twice in the Widget tree (#1767) --- packages/smooth_app/lib/pages/scan/scan_page.dart | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/smooth_app/lib/pages/scan/scan_page.dart b/packages/smooth_app/lib/pages/scan/scan_page.dart index 16f770216be..497ed0f83ea 100644 --- a/packages/smooth_app/lib/pages/scan/scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/scan_page.dart @@ -51,17 +51,10 @@ class _ScanPageState extends State { return AnnotatedRegion( value: SystemUiOverlayStyle.light, child: Scaffold( - body: MultiProvider( - providers: >[ - ChangeNotifierProvider( - create: (_) => PermissionListener( - permission: Permission.camera, - ), - ), - ChangeNotifierProvider( - create: (BuildContext context) => _model!, - ) - ], + body: ChangeNotifierProvider( + create: (_) => PermissionListener( + permission: Permission.camera, + ), child: const ScannerOverlay( backgroundChild: _ScanPageBackgroundWidget(), topChild: _ScanPageTopWidget(), From a04b3072ec369c3f5f6f4fecd523a3d5f0664e39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 May 2022 20:03:06 +0200 Subject: [PATCH 22/27] chore(deps): bump crowdin/github-action from 1.4.8 to 1.4.9 (#1774) Bumps [crowdin/github-action](https://github.com/crowdin/github-action) from 1.4.8 to 1.4.9. - [Release notes](https://github.com/crowdin/github-action/releases) - [Commits](https://github.com/crowdin/github-action/compare/1.4.8...1.4.9) --- updated-dependencies: - dependency-name: crowdin/github-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/crowdin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 7cd592f11cd..f207b6e673c 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -15,7 +15,7 @@ jobs: uses: actions/checkout@v3 - name: crowdin action - uses: crowdin/github-action@1.4.8 + uses: crowdin/github-action@1.4.9 continue-on-error: true with: # Upload sources to Crowdin From 89d440ebc644cc509d7b8c8a7b9bbe54dbd15ed0 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 6 May 2022 20:49:10 +0200 Subject: [PATCH 23/27] fix: Fix image_cropper import (#1772) * Fix unused import * Upgrade image_cropper to 2.0.2 --- .../smooth_app/lib/pages/image_crop_page.dart | 1 - packages/smooth_app/pubspec.lock | 26 +++++++++---------- packages/smooth_app/pubspec.yaml | 2 +- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/smooth_app/lib/pages/image_crop_page.dart b/packages/smooth_app/lib/pages/image_crop_page.dart index ad9b40044f2..34c543c7dcd 100644 --- a/packages/smooth_app/lib/pages/image_crop_page.dart +++ b/packages/smooth_app/lib/pages/image_crop_page.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:image_cropper/image_cropper.dart'; -import 'package:image_cropper_platform_interface/image_cropper_platform_interface.dart'; import 'package:image_picker/image_picker.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/themes/theme_provider.dart'; diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index d0ac93a6dfb..0a8d3266216 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -77,21 +77,21 @@ packages: name: built_value url: "https://pub.dartlang.org" source: hosted - version: "8.2.0" + version: "8.2.3" camera: dependency: "direct main" description: name: camera url: "https://pub.dartlang.org" source: hosted - version: "0.9.4+20" + version: "0.9.4+21" camera_platform_interface: dependency: transitive description: name: camera_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" + version: "2.1.6" camera_web: dependency: transitive description: @@ -154,7 +154,7 @@ packages: name: cross_file url: "https://pub.dartlang.org" source: hosted - version: "0.3.2" + version: "0.3.3" crypto: dependency: transitive description: @@ -340,7 +340,7 @@ packages: name: flutter_widget_from_html_core url: "https://pub.dartlang.org" source: hosted - version: "0.8.5+1" + version: "0.8.5+3" freezed_annotation: dependency: transitive description: @@ -366,7 +366,7 @@ packages: name: fwfh_text_style url: "https://pub.dartlang.org" source: hosted - version: "2.7.3+1" + version: "2.7.3+2" glob: dependency: transitive description: @@ -431,7 +431,7 @@ packages: name: image_cropper url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" image_cropper_for_web: dependency: transitive description: @@ -473,7 +473,7 @@ packages: name: image_picker_ios url: "https://pub.dartlang.org" source: hosted - version: "0.8.4+11" + version: "0.8.5" image_picker_platform_interface: dependency: transitive description: @@ -513,7 +513,7 @@ packages: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "4.4.0" + version: "4.5.0" latlong2: dependency: "direct main" description: @@ -702,7 +702,7 @@ packages: name: path_provider_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.12" + version: "2.0.13" path_provider_ios: dependency: transitive description: @@ -856,7 +856,7 @@ packages: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "3.0.1+1" + version: "3.1.0" rubber: dependency: "direct main" description: @@ -1050,7 +1050,7 @@ packages: name: url_launcher_android url: "https://pub.dartlang.org" source: hosted - version: "6.0.15" + version: "6.0.16" url_launcher_ios: dependency: transitive description: @@ -1141,7 +1141,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.5.1" + version: "2.5.2" wkt_parser: dependency: transitive description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index 3067ecbc4f1..5cbaa123f02 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -50,7 +50,7 @@ dependencies: git: url: https://github.com/cli1005/google_ml_barcode_scanner.git ref: master - image_cropper: ^2.0.1 + image_cropper: ^2.0.2 auto_size_text: ^3.0.0 dev_dependencies: From f008f00660f78878e5edf64978374571e6a3fe07 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 6 May 2022 22:37:09 +0200 Subject: [PATCH 24/27] fix: setState shouldn't be called from onDispose (#1769) * setState shouldn't be called from onDispose * Add missing statement * A few more doc Co-authored-by: Pierre Slamich --- .../smooth_app/lib/pages/scan/ml_kit_scan_page.dart | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart b/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart index bd1d95f37ff..fa5c9b64345 100644 --- a/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart @@ -182,13 +182,17 @@ class MLKitScannerPageState extends State<_MLKitScannerPageContent> { } } - Future _stopImageStream() async { + /// Stop the camera feed + /// [fromDispose] allows us to know if we can call [setState] + Future _stopImageStream({ + bool fromDispose = false, + }) async { if (stoppingCamera) { return; } stoppingCamera = true; - if (mounted) { + if (mounted && !fromDispose) { setState(() {}); } @@ -229,7 +233,7 @@ class MLKitScannerPageState extends State<_MLKitScannerPageContent> { void dispose() { // /!\ This call is a Future, which may leads to some issues. // This should be handled by [_restartCameraIfNecessary] - _stopImageStream(); + _stopImageStream(fromDispose: true); super.dispose(); } From 9518e2ee67e1fe5c1445d109ffa995ddc76f2fd9 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt <47862474+bhattabhi013@users.noreply.github.com> Date: Sat, 7 May 2022 03:54:02 +0530 Subject: [PATCH 25/27] feat: Add basic details page UI (#1515) * initial commit * ui for add basic details page * localization * removed comments * sent data to back-end * preloaded data * added padding * removed margin from carousel * added loader Co-authored-by: Pierre Slamich --- packages/smooth_app/lib/l10n/app_en.arb | 16 +- .../pages/product/add_basic_details_page.dart | 181 ++++++++++++++++++ .../lib/pages/product/summary_card.dart | 11 +- 3 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 packages/smooth_app/lib/pages/product/add_basic_details_page.dart diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 569bf9d9a75..45ef8d24f4e 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -889,8 +889,22 @@ "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" }, + "basic_details": "Basic Details", + "product_name": "Product Name", + "add_basic_details_product_name_error": "Please enter the product name", + "brand_name": "Brand name", + "add_basic_details_brand_name_error": "Please enter the brand name", + "weight_gram": "Weight in gram", + "add_basic_details_weight_gram_error": "Please enter the weight", + "barcode": "Barcode", + "basic_details_add_success": "Basic details added succesfully", + "basic_details_add_error": "Unable to add basic details. Please try again after some time", + "@basic_details_add_error":{ + "description": "Error message when error occurs while submitting basic details" + }, "confirm_clear": "Do you really want to clear?", "@confirm_clear": { "description": "Asking about whether to clear the list or not" } -} \ No newline at end of file +} + diff --git a/packages/smooth_app/lib/pages/product/add_basic_details_page.dart b/packages/smooth_app/lib/pages/product/add_basic_details_page.dart new file mode 100644 index 00000000000..baba9c3353c --- /dev/null +++ b/packages/smooth_app/lib/pages/product/add_basic_details_page.dart @@ -0,0 +1,181 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:openfoodfacts/openfoodfacts.dart'; +import 'package:smooth_app/cards/product_cards/product_image_carousel.dart'; +import 'package:smooth_app/database/product_query.dart'; +import 'package:smooth_app/generic_lib/buttons/smooth_action_button.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; +import 'package:smooth_app/generic_lib/loading_dialog.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_text_form_field.dart'; + +class AddBasicDetailsPage extends StatefulWidget { + const AddBasicDetailsPage(this.product); + final Product product; + @override + State createState() => _AddBasicDetailsPageState(); +} + +class _AddBasicDetailsPageState extends State { + final TextEditingController _productNameController = TextEditingController(); + final TextEditingController _brandNameController = TextEditingController(); + final TextEditingController _weightController = TextEditingController(); + + final double _heightSpace = LARGE_SPACE; + final GlobalKey _formKey = GlobalKey(); + @override + void initState() { + super.initState(); + _initializeProduct(); + } + + void _initializeProduct() { + _productNameController.text = widget.product.productName ?? ''; + _weightController.text = widget.product.quantity ?? ''; + _brandNameController.text = widget.product.brands ?? ''; + } + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context)!; + final Size size = MediaQuery.of(context).size; + final ColorScheme colorScheme = Theme.of(context).colorScheme; + return Scaffold( + appBar: AppBar(title: Text(appLocalizations.basic_details)), + body: Form( + key: _formKey, + child: ListView( + children: [ + Align( + alignment: Alignment.topLeft, + child: ProductImageCarousel( + widget.product, + height: size.height * 0.20, + onUpload: (_) {}, + ), + ), + SizedBox(height: _heightSpace), + if (widget.product.barcode != null) + Padding( + padding: EdgeInsets.symmetric(horizontal: size.width * 0.05), + child: Column( + children: [ + Text( + '${appLocalizations.barcode}: ${widget.product.barcode!}', + style: TextStyle( + color: colorScheme.onBackground, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: _heightSpace), + SmoothTextFormField( + controller: _productNameController, + type: TextFieldTypes.PLAIN_TEXT, + hintText: appLocalizations.product_name, + validator: (String? value) { + if (value == null || value.isEmpty) { + return appLocalizations + .add_basic_details_product_name_error; + } + return null; + }, + ), + SizedBox(height: _heightSpace), + SmoothTextFormField( + controller: _brandNameController, + type: TextFieldTypes.PLAIN_TEXT, + hintText: appLocalizations.brand_name, + validator: (String? value) { + if (value == null || value.isEmpty) { + return appLocalizations + .add_basic_details_brand_name_error; + } + return null; + }, + ), + SizedBox(height: _heightSpace), + SmoothTextFormField( + controller: _weightController, + type: TextFieldTypes.PLAIN_TEXT, + hintText: appLocalizations.weight_gram, + textInputType: TextInputType.number, + validator: (String? value) { + if (value == null || value.isEmpty) { + return appLocalizations + .add_basic_details_weight_gram_error; + } + return null; + }, + ), + SizedBox(height: _heightSpace), + ], + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SmoothActionButton( + text: appLocalizations.cancel, + onPressed: () => Navigator.pop(context), + ), + SmoothActionButton( + text: appLocalizations.save, + onPressed: () async { + if (!_formKey.currentState!.validate()) { + return; + } + final Status? status = await _saveData(); + if (status == null || status.error != null) { + _errormessageAlert( + appLocalizations.basic_details_add_error); + return; + } + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + appLocalizations.basic_details_add_success))); + Navigator.pop(context); + }), + ], + ), + ], + ), + ), + ); + } + + void _errormessageAlert(final String message) => showDialog( + context: context, + builder: (BuildContext context) => SmoothAlertDialog( + body: ListTile( + leading: const Icon(Icons.error_outline, color: Colors.red), + title: Text(message), + ), + actions: [ + SmoothActionButton( + text: AppLocalizations.of(context)!.close, + onPressed: () => Navigator.pop(context), + ), + ], + ), + ); + + Future _saveData() async { + final AppLocalizations appLocalizations = AppLocalizations.of(context)!; + final Product product = Product( + productName: _productNameController.text, + quantity: _weightController.text, + brands: _brandNameController.text, + barcode: widget.product.barcode, + ); + final Status? status = await LoadingDialog.run( + context: context, + future: OpenFoodAPIClient.saveProduct( + ProductQuery.getUser(), + product, + ), + title: appLocalizations.nutrition_page_update_running, + ); + return status; + } +} diff --git a/packages/smooth_app/lib/pages/product/summary_card.dart b/packages/smooth_app/lib/pages/product/summary_card.dart index 0c1d32ab85a..ee712e57f74 100644 --- a/packages/smooth_app/lib/pages/product/summary_card.dart +++ b/packages/smooth_app/lib/pages/product/summary_card.dart @@ -25,6 +25,7 @@ import 'package:smooth_app/helpers/robotoff_insight_helper.dart'; import 'package:smooth_app/helpers/score_card_helper.dart'; import 'package:smooth_app/helpers/smooth_matched_product.dart'; import 'package:smooth_app/helpers/ui_helpers.dart'; +import 'package:smooth_app/pages/product/add_basic_details_page.dart'; import 'package:smooth_app/pages/product/common/product_query_page_helper.dart'; import 'package:smooth_app/pages/question_page.dart'; @@ -290,7 +291,15 @@ class _SummaryCardState extends State { summaryCardButtons.add( addPanelButton( localizations.completed_basic_details_btn_text, - onPressed: () => _showNotImplemented(context), + onPressed: () async { + await Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => + AddBasicDetailsPage(widget._product), + ), + ); + }, ), ); } From 6b0410c8ddabbed0e6cc91dedd8a2686fbfe1090 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 7 May 2022 09:49:34 +0200 Subject: [PATCH 26/27] chore: New Crowdin translations to review and merge (#1777) * chore: New Crowdin translations * Update packages/smooth_app/lib/l10n/app_pt.arb Co-authored-by: Crowdin Bot Co-authored-by: Pierre Slamich --- packages/smooth_app/lib/l10n/app_bg.arb | 10 +++++----- packages/smooth_app/lib/l10n/app_da.arb | 2 +- packages/smooth_app/lib/l10n/app_de.arb | 2 +- packages/smooth_app/lib/l10n/app_es.arb | 2 +- packages/smooth_app/lib/l10n/app_fr.arb | 2 +- packages/smooth_app/lib/l10n/app_he.arb | 2 +- packages/smooth_app/lib/l10n/app_it.arb | 2 +- packages/smooth_app/lib/l10n/app_ja.arb | 2 +- packages/smooth_app/lib/l10n/app_ko.arb | 2 +- packages/smooth_app/lib/l10n/app_ru.arb | 2 +- packages/smooth_app/lib/l10n/app_vi.arb | 6 +++--- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_bg.arb b/packages/smooth_app/lib/l10n/app_bg.arb index 3341253298d..f991b2357d7 100644 --- a/packages/smooth_app/lib/l10n/app_bg.arb +++ b/packages/smooth_app/lib/l10n/app_bg.arb @@ -14,7 +14,7 @@ "description": "A label on a button that says 'Next', pressing the button takes the user to the next screen." }, "save": "Запис", - "save_confirmation": "Are you sure you want to save?", + "save_confirmation": "Сигурен ли си, че искаш да запазиш?", "skip": "Пропусни", "cancel": "Отмени", "@cancel": {}, @@ -451,7 +451,7 @@ "@uploading_image": { "description": "Message when a new picture is uploading to the server" }, - "uploading_image_type_front": "Uploading front image to Open Food Facts", + "uploading_image_type_front": "Качване на снимката на предната страна на продукта в Open Food Facts", "@uploading_image_type_front": { "description": "Message when a new front picture is being uploaded to the server" }, @@ -463,11 +463,11 @@ "@uploading_image_type_nutrition": { "description": "Message when a new nutrition picture is being uploaded to the server" }, - "uploading_image_type_packaging": "Uploading packaging image to Open Food Facts", + "uploading_image_type_packaging": "Качване на снимката на вида на опаковката в Open Food Facts", "@uploading_image_type_packaging": { "description": "Message when a new packaging picture is being uploaded to the server" }, - "uploading_image_type_other": "Uploading other image to Open Food Facts", + "uploading_image_type_other": "Качване на друга снимка в Open Food Facts", "@uploading_image_type_other": { "description": "Message when a new other picture is being uploaded to the server" }, @@ -703,7 +703,7 @@ "@product_list_empty_message": { "description": "When the history list is empty, body of the message explaining to start scanning" }, - "product_list_reloading_in_progress": "Refreshing products in your History", + "product_list_reloading_in_progress": "Актуализация на продуктите в историята", "@product_list_reloading_in_progress": { "description": "Message to show while loading previous scanned items" }, diff --git a/packages/smooth_app/lib/l10n/app_da.arb b/packages/smooth_app/lib/l10n/app_da.arb index a6d209820a1..7e59c9b83c1 100644 --- a/packages/smooth_app/lib/l10n/app_da.arb +++ b/packages/smooth_app/lib/l10n/app_da.arb @@ -889,7 +889,7 @@ "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" }, - "confirm_clear": "Do you really want to clear?", + "confirm_clear": "Sikker på, at listen skal ryddes?", "@confirm_clear": { "description": "Asking about whether to clear the list or not" } diff --git a/packages/smooth_app/lib/l10n/app_de.arb b/packages/smooth_app/lib/l10n/app_de.arb index 883b14e134a..6096a2ae0db 100644 --- a/packages/smooth_app/lib/l10n/app_de.arb +++ b/packages/smooth_app/lib/l10n/app_de.arb @@ -889,7 +889,7 @@ "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" }, - "confirm_clear": "Do you really want to clear?", + "confirm_clear": "Möchten Sie wirklich leeren?", "@confirm_clear": { "description": "Asking about whether to clear the list or not" } diff --git a/packages/smooth_app/lib/l10n/app_es.arb b/packages/smooth_app/lib/l10n/app_es.arb index 65a43fd96c2..a0f9d3f70f4 100644 --- a/packages/smooth_app/lib/l10n/app_es.arb +++ b/packages/smooth_app/lib/l10n/app_es.arb @@ -889,7 +889,7 @@ "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" }, - "confirm_clear": "Do you really want to clear?", + "confirm_clear": "¿Estás seguro que quieres borrar?", "@confirm_clear": { "description": "Asking about whether to clear the list or not" } diff --git a/packages/smooth_app/lib/l10n/app_fr.arb b/packages/smooth_app/lib/l10n/app_fr.arb index e4edda65402..c341e2d96df 100644 --- a/packages/smooth_app/lib/l10n/app_fr.arb +++ b/packages/smooth_app/lib/l10n/app_fr.arb @@ -889,7 +889,7 @@ "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" }, - "confirm_clear": "Do you really want to clear?", + "confirm_clear": "Voulez-vous vraiment effacer ?", "@confirm_clear": { "description": "Asking about whether to clear the list or not" } diff --git a/packages/smooth_app/lib/l10n/app_he.arb b/packages/smooth_app/lib/l10n/app_he.arb index 22f1f442e39..4e414bd1a38 100644 --- a/packages/smooth_app/lib/l10n/app_he.arb +++ b/packages/smooth_app/lib/l10n/app_he.arb @@ -889,7 +889,7 @@ "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" }, - "confirm_clear": "Do you really want to clear?", + "confirm_clear": "למחוק?", "@confirm_clear": { "description": "Asking about whether to clear the list or not" } diff --git a/packages/smooth_app/lib/l10n/app_it.arb b/packages/smooth_app/lib/l10n/app_it.arb index 03a54b2bddd..d16786a64ba 100644 --- a/packages/smooth_app/lib/l10n/app_it.arb +++ b/packages/smooth_app/lib/l10n/app_it.arb @@ -889,7 +889,7 @@ "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" }, - "confirm_clear": "Do you really want to clear?", + "confirm_clear": "Vuoi davvero cancellare?", "@confirm_clear": { "description": "Asking about whether to clear the list or not" } diff --git a/packages/smooth_app/lib/l10n/app_ja.arb b/packages/smooth_app/lib/l10n/app_ja.arb index 3464d67c341..33607621696 100644 --- a/packages/smooth_app/lib/l10n/app_ja.arb +++ b/packages/smooth_app/lib/l10n/app_ja.arb @@ -889,7 +889,7 @@ "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" }, - "confirm_clear": "Do you really want to clear?", + "confirm_clear": "本当に消去してよろしいですか?", "@confirm_clear": { "description": "Asking about whether to clear the list or not" } diff --git a/packages/smooth_app/lib/l10n/app_ko.arb b/packages/smooth_app/lib/l10n/app_ko.arb index 8dd53ec3757..31d59e6f9bf 100644 --- a/packages/smooth_app/lib/l10n/app_ko.arb +++ b/packages/smooth_app/lib/l10n/app_ko.arb @@ -889,7 +889,7 @@ "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" }, - "confirm_clear": "Do you really want to clear?", + "confirm_clear": "정말로 지우시겠습니까?", "@confirm_clear": { "description": "Asking about whether to clear the list or not" } diff --git a/packages/smooth_app/lib/l10n/app_ru.arb b/packages/smooth_app/lib/l10n/app_ru.arb index 32fb74d6ef5..8d50bd962a7 100644 --- a/packages/smooth_app/lib/l10n/app_ru.arb +++ b/packages/smooth_app/lib/l10n/app_ru.arb @@ -889,7 +889,7 @@ "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" }, - "confirm_clear": "Do you really want to clear?", + "confirm_clear": "Вы действительно хотите очистить?", "@confirm_clear": { "description": "Asking about whether to clear the list or not" } diff --git a/packages/smooth_app/lib/l10n/app_vi.arb b/packages/smooth_app/lib/l10n/app_vi.arb index 0ffa29dd870..b72b5d94f21 100644 --- a/packages/smooth_app/lib/l10n/app_vi.arb +++ b/packages/smooth_app/lib/l10n/app_vi.arb @@ -66,7 +66,7 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", + "offUtility": "Lựa chọn thực phẩm tốt cho bạn và hành tinh này.", "@offUtility": { "description": "Description of what a user can use Open Food Facts for." }, @@ -841,7 +841,7 @@ "@edit_ingredients_extrait_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, - "edit_ingredients_refresh_photo_btn_text": "Refresh photo", + "edit_ingredients_refresh_photo_btn_text": "Làm mới ảnh", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, @@ -889,7 +889,7 @@ "@user_list_name_error_same": { "description": "Validation error about the renamed name that is the same as the initial list name" }, - "confirm_clear": "Do you really want to clear?", + "confirm_clear": "Bạn thực sự muốn xóa?", "@confirm_clear": { "description": "Asking about whether to clear the list or not" } From 67523954cacc30056acfd484225f21f25adf478b Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt <47862474+bhattabhi013@users.noreply.github.com> Date: Sat, 7 May 2022 17:52:15 +0530 Subject: [PATCH 27/27] added onTap on tile click (#1778) --- .../product_cards/product_title_card.dart | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/packages/smooth_app/lib/cards/product_cards/product_title_card.dart b/packages/smooth_app/lib/cards/product_cards/product_title_card.dart index 534f304bd71..accdea1b78e 100644 --- a/packages/smooth_app/lib/cards/product_cards/product_title_card.dart +++ b/packages/smooth_app/lib/cards/product_cards/product_title_card.dart @@ -6,6 +6,7 @@ import 'package:smooth_app/data_models/continuous_scan_model.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/helpers/extension_on_text_helper.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; +import 'package:smooth_app/pages/product/add_basic_details_page.dart'; class ProductTitleCard extends StatelessWidget { const ProductTitleCard( @@ -47,17 +48,30 @@ class ProductTitleCard extends StatelessWidget { } return Align( alignment: Alignment.topLeft, - child: ListTile( - dense: dense, - contentPadding: EdgeInsets.zero, - title: Text( - getProductName(product, appLocalizations), - style: themeData.textTheme.headline4, - ).selectable(isSelectable: isSelectable), - subtitle: Text( - subtitleText, - ).selectable(isSelectable: isSelectable), - trailing: trailingWidget, + child: InkWell( + onTap: () async { + if (getProductName(product, appLocalizations) == + appLocalizations.unknownProductName) { + await Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => AddBasicDetailsPage(product), + ), + ); + } + }, + child: ListTile( + dense: dense, + contentPadding: EdgeInsets.zero, + title: Text( + getProductName(product, appLocalizations), + style: themeData.textTheme.headline4, + ).selectable(isSelectable: isSelectable), + subtitle: Text( + subtitleText, + ).selectable(isSelectable: isSelectable), + trailing: trailingWidget, + ), ), ); }