diff --git a/packages/smooth_app/lib/background/background_task_details.dart b/packages/smooth_app/lib/background/background_task_details.dart index 235116728b3..cece76980a5 100644 --- a/packages/smooth_app/lib/background/background_task_details.dart +++ b/packages/smooth_app/lib/background/background_task_details.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:openfoodfacts/model/ProductResultV3.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/background/abstract_background_task.dart'; @@ -113,12 +114,31 @@ class BackgroundTaskDetails extends AbstractBackgroundTask { /// Uploads the product changes. @override Future upload() async { - // TODO(AshAman999): check returned Status - await OpenFoodAPIClient.saveProduct( + if (_product.packagings != null) { + // For the moment, we can only save "packagings" with V3, + // and V3 can only save "packagings". + final ProductResultV3 result = + await OpenFoodAPIClient.temporarySaveProductV3( + getUser(), + _product.barcode!, + packagings: _product.packagings, + language: getLanguage(), + country: getCountry(), + ); + if (result.status != ProductResultV3.statusSuccess && + result.status != ProductResultV3.statusWarning) { + throw Exception('Could not save product - ${result.errors}'); + } + return; + } + final Status status = await OpenFoodAPIClient.saveProduct( getUser(), _product, language: getLanguage(), country: getCountry(), ); + if (status.status != 1) { + throw Exception('Could not save product - ${status.error}'); + } } } diff --git a/packages/smooth_app/lib/data_models/up_to_date_changes.dart b/packages/smooth_app/lib/data_models/up_to_date_changes.dart index bb5104ea4c4..6475cd92d8a 100644 --- a/packages/smooth_app/lib/data_models/up_to_date_changes.dart +++ b/packages/smooth_app/lib/data_models/up_to_date_changes.dart @@ -1,5 +1,3 @@ -// ignore_for_file: deprecated_member_use - import 'package:openfoodfacts/model/Product.dart'; import 'package:smooth_app/data_models/operation_type.dart'; import 'package:smooth_app/database/dao_transient_operation.dart'; @@ -73,9 +71,14 @@ class UpToDateChanges { if (change.ingredientsText != null) { initial.ingredientsText = change.ingredientsText; } + // ignore: deprecated_member_use if (change.packaging != null) { + // ignore: deprecated_member_use initial.packaging = change.packaging; } + if (change.packagings != null) { + initial.packagings = change.packagings; + } if (change.noNutritionData != null) { initial.noNutritionData = change.noNutritionData; } diff --git a/packages/smooth_app/lib/pages/product/common/product_refresher.dart b/packages/smooth_app/lib/pages/product/common/product_refresher.dart index 2723dee1434..60bbaf0b13d 100644 --- a/packages/smooth_app/lib/pages/product/common/product_refresher.dart +++ b/packages/smooth_app/lib/pages/product/common/product_refresher.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:openfoodfacts/model/ProductResultV3.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/database/dao_product.dart'; @@ -114,7 +115,7 @@ class ProductRefresher { ) async { try { // ignore: deprecated_member_use - final ProductResult result = await OpenFoodAPIClient.getProduct( + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( getBarcodeQueryConfiguration(barcode), ); if (result.product != null) { diff --git a/packages/smooth_app/lib/pages/product/edit_new_packagings.dart b/packages/smooth_app/lib/pages/product/edit_new_packagings.dart new file mode 100644 index 00000000000..a6b759929f3 --- /dev/null +++ b/packages/smooth_app/lib/pages/product/edit_new_packagings.dart @@ -0,0 +1,360 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:openfoodfacts/model/LocalizedTag.dart'; +import 'package:openfoodfacts/model/ProductPackaging.dart'; +import 'package:openfoodfacts/openfoodfacts.dart'; +import 'package:openfoodfacts/utils/TagType.dart'; +import 'package:provider/provider.dart'; +import 'package:smooth_app/background/background_task_details.dart'; +import 'package:smooth_app/database/local_database.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/widgets/smooth_card.dart'; +import 'package:smooth_app/pages/product/may_exit_page_helper.dart'; +import 'package:smooth_app/pages/product/simple_input_widget.dart'; +import 'package:smooth_app/widgets/smooth_app_bar.dart'; +import 'package:smooth_app/widgets/smooth_scaffold.dart'; + +/// Edit display of a product packagings (the new api V3 version). +class EditNewPackagings extends StatefulWidget { + const EditNewPackagings({ + required this.product, + }); + + final Product product; + + @override + State createState() => _EditNewPackagingsState(); +} + +class _EditNewPackagingsState extends State { + late final LocalDatabase _localDatabase; + + /// Current packagings. + final List _packagings = []; + + final List _controllerUnits = + []; + final List _controllerShapes = + []; + final List _controllerMaterials = + []; + final List _controllerRecyclings = + []; + + void _initPackagings() { + if (widget.product.packagings == null) { + return; + } + for (final ProductPackaging packaging in widget.product.packagings!) { + _addPackaging( + ProductPackaging() + ..material = packaging.material + ..shape = packaging.shape + ..recycling = packaging.recycling + ..numberOfUnits = packaging.numberOfUnits, + ); + } + } + + void _addPackaging(final ProductPackaging packaging) { + _packagings.add(packaging); + _controllerUnits.add(TextEditingController()); + _controllerShapes.add(TextEditingController()); + _controllerMaterials.add(TextEditingController()); + _controllerRecyclings.add(TextEditingController()); + } + + void _removePackagingAt(final int index) { + _packagings.removeAt(index); + _controllerUnits.removeAt(index); + _controllerShapes.removeAt(index); + _controllerMaterials.removeAt(index); + _controllerRecyclings.removeAt(index); + } + + @override + void initState() { + super.initState(); + _initPackagings(); + _localDatabase = context.read(); + _localDatabase.upToDate.showInterest(widget.product.barcode!); + } + + @override + void dispose() { + _localDatabase.upToDate.loseInterest(widget.product.barcode!); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final List children = []; + int index = 0; + for (final ProductPackaging packaging in _packagings) { + // needed for deleteCallback (if not final, will take unreachable value) + final int deleteIndex = index; + children.add( + _EditSinglePackagings( + packaging: packaging, + index: index, + deleteCallback: () => setState(() => _removePackagingAt(deleteIndex)), + controllerUnits: _controllerUnits[index], + controllerShape: _controllerShapes[index], + controllerMaterial: _controllerMaterials[index], + controllerRecycling: _controllerRecyclings[index], + ), + ); + index++; + } + children.add( + ElevatedButton.icon( + label: + const Text('Ajouter un élément'), // TODO(monsieurtanuki): localize + icon: const Icon(Icons.add), + onPressed: () => setState(() => _addPackaging(ProductPackaging())), + ), + ); + children.add( + Padding( + padding: const EdgeInsets.symmetric(horizontal: SMALL_SPACE), + child: SmoothActionButtonsBar( + axis: Axis.horizontal, + positiveAction: SmoothActionButton( + text: appLocalizations.save, + onPressed: () async => _exitPage( + await _mayExitPage(saving: true), + ), + ), + negativeAction: SmoothActionButton( + text: appLocalizations.cancel, + onPressed: () async => _exitPage( + await _mayExitPage(saving: false), + ), + ), + ), + ), + ); + return WillPopScope( + onWillPop: () async => _mayExitPage(saving: false), + child: SmoothScaffold( + appBar: SmoothAppBar( + title: Text(appLocalizations.edit_product_form_item_packaging_title), + subTitle: widget.product.productName != null + ? Text( + widget.product.productName!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ) + : null, + ), + body: ListView(children: children), + ), + ); + } + + /// Exits the page if the [flag] is `true`. + void _exitPage(final bool flag) { + if (flag) { + Navigator.of(context).pop(); + } + } + + LocalizedTag? _getLocalizedTag(final TextEditingController controller) { + final String text = controller.text; + if (text.isEmpty) { + return null; + } + return LocalizedTag()..lcName = text; + } + + void _loadPackagingsFromControllers() { + for (int i = 0; i < _packagings.length; i++) { + final ProductPackaging packaging = _packagings[i]; + packaging.shape = _getLocalizedTag(_controllerShapes[i]); + packaging.material = _getLocalizedTag(_controllerMaterials[i]); + packaging.recycling = _getLocalizedTag(_controllerRecyclings[i]); + packaging.numberOfUnits = int.tryParse(_controllerUnits[i] + .text); // TODO(monsieurtanuki): handle the "not a number" case + } + } + + bool _isPackagingDifferent( + final ProductPackaging p1, + final ProductPackaging p2, + ) { + return p1.shape?.lcName != p2.shape?.lcName || + p1.material?.lcName != p2.material?.lcName || + p1.recycling?.lcName != p2.recycling?.lcName || + p1.numberOfUnits != p2.numberOfUnits; + } + + bool _hasPackagingsChanged() { + if (widget.product.packagings == null) { + return _packagings.isEmpty; + } + if (widget.product.packagings!.length != _packagings.length) { + return true; + } + for (int i = 0; i < _packagings.length; i++) { + if (_isPackagingDifferent( + _packagings[i], + widget.product.packagings![i], + )) { + return true; + } + } + return false; + } + + /// Returns `true` if we should really exit the page. + /// + /// Parameter [saving] tells about the context: are we leaving the page, + /// or have we clicked on the "save" button? + Future _mayExitPage({required final bool saving}) async { + _loadPackagingsFromControllers(); + final bool changed = _hasPackagingsChanged(); + if (!changed) { + return true; + } + + final Product changedProduct = Product(barcode: widget.product.barcode) + ..packagings = _packagings; + + if (!saving) { + final bool? pleaseSave = + await MayExitPageHelper().openSaveBeforeLeavingDialog(context); + if (pleaseSave == null) { + return false; + } + if (pleaseSave == false) { + return true; + } + } + await BackgroundTaskDetails.addTask( + changedProduct, + widget: this, + ); + return true; + } +} + +/// Edit display of a single [ProductPackaging]. +class _EditSinglePackagings extends StatelessWidget { + const _EditSinglePackagings({ + required this.packaging, + required this.index, + required this.deleteCallback, + required this.controllerUnits, + required this.controllerShape, + required this.controllerMaterial, + required this.controllerRecycling, + }); + + final ProductPackaging packaging; + final int index; + final VoidCallback deleteCallback; + final TextEditingController controllerUnits; + final TextEditingController controllerShape; + final TextEditingController controllerMaterial; + final TextEditingController controllerRecycling; + + @override + Widget build(BuildContext context) { + if (packaging.numberOfUnits != null) { + controllerUnits.text = '${packaging.numberOfUnits!}'; + } + if (packaging.shape?.lcName != null) { + controllerShape.text = (packaging.shape?.lcName)!; + } + if (packaging.material?.lcName != null) { + controllerMaterial.text = (packaging.material?.lcName)!; + } + if (packaging.recycling?.lcName != null) { + controllerRecycling.text = (packaging.recycling?.lcName)!; + } + return SmoothCard( + color: + Colors.grey[300], // TODO(monsieurtanuki): different color? +dark mode + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListTile( + title: Text( + 'Element ${index + 1}'), // TODO(monsieurtanuki): localize + trailing: IconButton( + icon: const Icon(Icons.delete), + onPressed: deleteCallback, + )), + _EditLine( + // TODO(monsieurtanuki): different display for numbers + title: 'Number of units', // TODO(monsieurtanuki): localize + controller: controllerUnits, + tagType: null, + hintText: 'hintText', // TODO(monsieurtanuki): localize and specific + ), + _EditLine( + title: 'Shape', // TODO(monsieurtanuki): localize + controller: controllerShape, + tagType: TagType.PACKAGING_SHAPES, + hintText: 'hintText', // TODO(monsieurtanuki): localize and specific + ), + _EditLine( + title: 'Material', // TODO(monsieurtanuki): localize + controller: controllerMaterial, + tagType: TagType.PACKAGING_MATERIALS, + hintText: 'hintText', // TODO(monsieurtanuki): localize and specific + ), + _EditLine( + title: 'Recycling', // TODO(monsieurtanuki): localize + controller: controllerRecycling, + tagType: TagType.PACKAGING_RECYCLING, + hintText: 'hintText', // TODO(monsieurtanuki): localize and specific + ), + ], + ), + ); + } +} + +/// Edit display of a single line inside a [ProductPackaging], e.g. its shape. +class _EditLine extends StatelessWidget { + const _EditLine({ + required this.title, + required this.controller, + required this.tagType, + required this.hintText, + }); + + final String title; + final TextEditingController controller; + final TagType? tagType; + final String hintText; + + @override + Widget build(BuildContext context) => LayoutBuilder( + builder: (_, BoxConstraints constraints) => Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: constraints.maxWidth / 2, + child: Text(title), + ), + SizedBox( + width: constraints.maxWidth / 2, + child: SimpleInputWidgetField( + focusNode: FocusNode(), + autocompleteKey: UniqueKey(), + constraints: constraints, + tagType: tagType, + hintText: hintText, + controller: controller, + ), + ), + ], + ), + ); +} diff --git a/packages/smooth_app/lib/pages/product/edit_product_page.dart b/packages/smooth_app/lib/pages/product/edit_product_page.dart index c7056386ef9..4a913862f57 100644 --- a/packages/smooth_app/lib/pages/product/edit_product_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_product_page.dart @@ -16,6 +16,7 @@ import 'package:smooth_app/pages/product/add_basic_details_page.dart'; import 'package:smooth_app/pages/product/add_other_details_page.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; import 'package:smooth_app/pages/product/edit_ingredients_page.dart'; +import 'package:smooth_app/pages/product/edit_new_packagings.dart'; import 'package:smooth_app/pages/product/nutrition_page_loaded.dart'; import 'package:smooth_app/pages/product/ocr_ingredients_helper.dart'; import 'package:smooth_app/pages/product/ocr_packaging_helper.dart'; @@ -201,6 +202,26 @@ class _EditProductPageState extends State { ), ), _getSimpleListTileItem(SimpleInputPageLabelHelper()), + _ListTitleItem( + leading: const Icon( + Icons.recycling), // TODO(monsieurtanuki): different logo? + title: + '(Beta) Structured packaging', // TODO(monsieurtanuki): localize + onTap: () async { + if (!await ProductRefresher().checkIfLoggedIn(context)) { + return; + } + await Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => EditNewPackagings( + product: _product, + ), + fullscreenDialog: true, + ), + ); + }, + ), _ListTitleItem( leading: const Icon(Icons.recycling), title: appLocalizations.edit_product_form_item_packaging_title, diff --git a/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart b/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart index 1844df44a93..c75c87a4dce 100644 --- a/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart +++ b/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart @@ -1,5 +1,3 @@ -// ignore_for_file: deprecated_member_use - import 'dart:async'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -10,10 +8,12 @@ import 'package:smooth_app/pages/product/ocr_helper.dart'; /// OCR Helper for packaging. class OcrPackagingHelper extends OcrHelper { @override + // ignore: deprecated_member_use String getText(final Product product) => product.packaging ?? ''; @override Product getMinimalistProduct(Product product, final String text) { + // ignore: deprecated_member_use product.packaging = text; return product; } diff --git a/packages/smooth_app/lib/pages/product/simple_input_page.dart b/packages/smooth_app/lib/pages/product/simple_input_page.dart index 8c0ab35cf49..09973acec46 100644 --- a/packages/smooth_app/lib/pages/product/simple_input_page.dart +++ b/packages/smooth_app/lib/pages/product/simple_input_page.dart @@ -76,6 +76,7 @@ class _SimpleInputPageState extends State { child: SimpleInputWidget( helper: widget.helpers[i], product: widget.product, + controller: _controllers[i], ), ), ), @@ -182,7 +183,9 @@ class _SimpleInputPageState extends State { @override void dispose() { - // Disposed is managed by the provider + for (final TextEditingController controller in _controllers) { + controller.dispose(); + } _controllers.clear(); super.dispose(); } diff --git a/packages/smooth_app/lib/pages/product/simple_input_widget.dart b/packages/smooth_app/lib/pages/product/simple_input_widget.dart index 849dc9d399e..9a056dfcc1a 100644 --- a/packages/smooth_app/lib/pages/product/simple_input_widget.dart +++ b/packages/smooth_app/lib/pages/product/simple_input_widget.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/utils/TagType.dart'; -import 'package:provider/provider.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/pages/product/autocomplete.dart'; import 'package:smooth_app/pages/product/explanation_widget.dart'; @@ -14,10 +13,12 @@ class SimpleInputWidget extends StatefulWidget { const SimpleInputWidget({ required this.helper, required this.product, + required this.controller, }); final AbstractSimpleInputPageHelper helper; final Product product; + final TextEditingController controller; @override State createState() => _SimpleInputWidgetState(); @@ -60,61 +61,96 @@ class _SimpleInputWidgetState extends State { children: [ Flexible( flex: 1, - child: _SimpleInputWidgetField( + child: SimpleInputWidgetField( autocompleteKey: _autocompleteKey, focusNode: _focusNode, constraints: constraints, - helper: widget.helper, + tagType: widget.helper.getTagType(), + hintText: widget.helper.getAddHint(appLocalizations), + controller: widget.controller, ), ), - _SimpleInputWidgetFieldButton(helper: widget.helper) + IconButton( + onPressed: () { + if (widget.helper + .addItemsFromController(widget.controller)) { + setState(() {}); + } + }, + icon: const Icon(Icons.add_circle), + ) ], ); }, ), Divider(color: themeData.colorScheme.onBackground), - _SimpleInputWidgetItems(helper: widget.helper), + ListView.builder( + itemCount: widget.helper.terms.length, + itemBuilder: (BuildContext context, int position) { + final String term = widget.helper.terms[position]; + return KeyedSubtree( + key: ValueKey(term), + child: ListTile( + trailing: Tooltip( + message: appLocalizations + .edit_product_form_item_remove_item_tooltip, + child: InkWell( + customBorder: const CircleBorder(), + onTap: () { + if (widget.helper.removeTerm(term)) { + setState(() {}); + } + }, + child: const Padding( + padding: EdgeInsets.symmetric( + horizontal: MEDIUM_SPACE, + vertical: SMALL_SPACE, + ), + child: Icon(Icons.delete), + ), + ), + ), + contentPadding: const EdgeInsetsDirectional.only( + start: LARGE_SPACE, + ), + title: Text(term), + ), + ); + }, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + ), ], ); } - - static TextEditingController controller( - BuildContext context, { - bool listen = false, - }) => - Provider.of( - context, - listen: listen, - ); } -class _SimpleInputWidgetField extends StatelessWidget { - const _SimpleInputWidgetField({ +// TODO(monsieurtanuki): put it in its own file as it's not private anymore. +class SimpleInputWidgetField extends StatelessWidget { + const SimpleInputWidgetField({ required this.focusNode, required this.autocompleteKey, required this.constraints, - required this.helper, - Key? key, - }) : super(key: key); + required this.tagType, + required this.hintText, + required this.controller, + }); final FocusNode focusNode; final Key autocompleteKey; final BoxConstraints constraints; - final AbstractSimpleInputPageHelper helper; + final TagType? tagType; + final String hintText; + final TextEditingController controller; @override Widget build(BuildContext context) { - final AppLocalizations appLocalizations = AppLocalizations.of(context); - return Padding( padding: const EdgeInsets.only(left: LARGE_SPACE), child: RawAutocomplete( key: autocompleteKey, focusNode: focusNode, - textEditingController: _SimpleInputWidgetState.controller( - context, - listen: true, - ), + textEditingController: controller, optionsBuilder: (final TextEditingValue value) async { final List result = []; final String input = value.text.trim(); @@ -123,7 +159,6 @@ class _SimpleInputWidgetField extends StatelessWidget { return result; } - final TagType? tagType = helper.getTagType(); if (tagType == null) { return result; } @@ -131,7 +166,7 @@ class _SimpleInputWidgetField extends StatelessWidget { // TODO(monsieurtanuki): ask off-dart to return Strings instead of dynamic? final List data = await OpenFoodAPIClient.getAutocompletedSuggestions( - tagType, + tagType!, language: ProductQuery.getLanguage()!, limit: 1000000, // lower max count on the server anyway input: value.text.trim(), @@ -158,7 +193,7 @@ class _SimpleInputWidgetField extends StatelessWidget { horizontal: SMALL_SPACE, vertical: SMALL_SPACE, ), - hintText: helper.getAddHint(appLocalizations), + hintText: hintText, ), autofocus: true, focusNode: focusNode, @@ -201,85 +236,3 @@ class _SimpleInputWidgetField extends StatelessWidget { ); } } - -class _SimpleInputWidgetFieldButton extends StatelessWidget { - const _SimpleInputWidgetFieldButton({ - required this.helper, - Key? key, - }) : super(key: key); - - final AbstractSimpleInputPageHelper helper; - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (BuildContext context, TextEditingController controller, - Widget? child) { - final AppLocalizations appLocalizations = AppLocalizations.of(context); - final bool hasValue = controller.text.trim().isNotEmpty; - - return Tooltip( - message: !hasValue - ? appLocalizations.edit_product_form_item_add_invalid_item_tooltip - : appLocalizations.edit_product_form_item_add_valid_item_tooltip, - child: IconButton( - onPressed: hasValue - ? () { - helper.addItemsFromController( - controller, - ); - } - : null, - icon: const Icon(Icons.add_circle), - ), - ); - }, - ); - } -} - -class _SimpleInputWidgetItems extends StatelessWidget { - const _SimpleInputWidgetItems({ - required this.helper, - }); - - final AbstractSimpleInputPageHelper helper; - - @override - Widget build(BuildContext context) { - final AppLocalizations appLocalizations = AppLocalizations.of(context); - - return ListView.builder( - itemCount: helper.terms.length, - itemBuilder: (BuildContext context, int position) { - final String term = helper.terms[position]; - return KeyedSubtree( - key: ValueKey(term), - child: ListTile( - trailing: Tooltip( - message: - appLocalizations.edit_product_form_item_remove_item_tooltip, - child: InkWell( - customBorder: const CircleBorder(), - onTap: () => helper.removeTerm(term), - child: const Padding( - padding: EdgeInsets.symmetric( - horizontal: MEDIUM_SPACE, - vertical: SMALL_SPACE, - ), - child: Icon(Icons.delete), - ), - ), - ), - contentPadding: const EdgeInsetsDirectional.only( - start: LARGE_SPACE, - ), - title: Text(term), - ), - ); - }, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - ); - } -} diff --git a/packages/smooth_app/lib/query/paged_user_product_query.dart b/packages/smooth_app/lib/query/paged_user_product_query.dart index 0f7d6dcbe84..56b33c4ee04 100644 --- a/packages/smooth_app/lib/query/paged_user_product_query.dart +++ b/packages/smooth_app/lib/query/paged_user_product_query.dart @@ -22,7 +22,7 @@ class PagedUserProductQuery extends PagedProductQuery { pageSize: pageSize, pageNumber: pageNumber, language: language, - fields: ProductQuery.fields, + fields: ProductQuery.tmpFieldsForPackagingIssue, ); @override diff --git a/packages/smooth_app/lib/query/product_query.dart b/packages/smooth_app/lib/query/product_query.dart index 47f43d56425..2364b84d564 100644 --- a/packages/smooth_app/lib/query/product_query.dart +++ b/packages/smooth_app/lib/query/product_query.dart @@ -13,7 +13,7 @@ import 'package:uuid/uuid.dart'; // ignore: avoid_classes_with_only_static_members abstract class ProductQuery { - static const ProductQueryVersion productQueryVersion = ProductQueryVersion.v2; + static const ProductQueryVersion productQueryVersion = ProductQueryVersion.v3; static OpenFoodFactsCountry? _country; @@ -127,7 +127,7 @@ abstract class ProductQuery { } } - static List get fields => [ + static List get fields => const [ ProductField.NAME, ProductField.BRANDS, ProductField.BARCODE, @@ -145,6 +145,7 @@ abstract class ProductQuery { ProductField.PACKAGING_QUANTITY, // ignore: deprecated_member_use ProductField.PACKAGING, + ProductField.PACKAGINGS, ProductField.PACKAGING_TAGS, ProductField.PACKAGING_TEXT_IN_LANGUAGES, ProductField.PACKAGING_TEXT_ALL_LANGUAGES, @@ -176,4 +177,11 @@ abstract class ProductQuery { ProductField.ORIGINS, ProductField.WEBSITE, ]; + + // TODO(monsieurtanuki): remove this list when packagings are correctly dealt with in user-related searches. + static List get tmpFieldsForPackagingIssue { + final List result = List.from(fields); + result.remove(ProductField.PACKAGINGS); + return result; + } }