From 2b6b0b146c867bf8572cd75e66b904a715731f86 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Thu, 7 Apr 2022 22:34:44 +0200 Subject: [PATCH] feat: #1060 - added an "exclude ecoscore" switch in dev mode (#1510) Impacted files: * `product_cards_helper.dart`: added the exclusion of "excluded attributes" * `smooth_matched_product.dart`: added the exclusion of "excluded attributes" * `smooth_product_card_found.dart`: added the exclusion of "excluded attributes" * `summary_card.dart`: added the exclusion of "excluded attributes" * `user_preferences.dart`: added the list of "excluded attributes" * `user_preferences_attribute_group.dart`: added the exclusion of "excluded attributes" * `user_preferences_dev_mode.dart`: added a switch for "exclude ecoscore"; refactored --- .../smooth_product_card_found.dart | 16 ++++++--- .../lib/data_models/user_preferences.dart | 8 +++++ .../lib/helpers/product_cards_helper.dart | 4 +++ .../lib/helpers/smooth_matched_product.dart | 33 +++++++++++++++---- .../lib/pages/product/summary_card.dart | 11 +++++-- .../user_preferences_attribute_group.dart | 15 +++++---- .../lib/pages/user_preferences_dev_mode.dart | 25 +++++++++++--- 7 files changed, 89 insertions(+), 23 deletions(-) diff --git a/packages/smooth_app/lib/cards/product_cards/smooth_product_card_found.dart b/packages/smooth_app/lib/cards/product_cards/smooth_product_card_found.dart index 4d64af6114b..49494e8cd39 100644 --- a/packages/smooth_app/lib/cards/product_cards/smooth_product_card_found.dart +++ b/packages/smooth_app/lib/cards/product_cards/smooth_product_card_found.dart @@ -39,19 +39,27 @@ class SmoothProductCardFound extends StatelessWidget { @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context)!; + final UserPreferences userPreferences = context.watch(); + final ProductPreferences productPreferences = + context.watch(); final Size screenSize = MediaQuery.of(context).size; + final List excludedAttributeIds = + userPreferences.getExcludedAttributeIds(); final List scores = []; final double iconSize = IconWidgetSizer.getIconSizeFromContext(context); - final List attributes = - getPopulatedAttributes(product, SCORE_ATTRIBUTE_IDS); + final List attributes = getPopulatedAttributes( + product, + SCORE_ATTRIBUTE_IDS, + excludedAttributeIds, + ); for (final Attribute attribute in attributes) { scores.add(SvgIconChip(attribute.iconUrl!, height: iconSize)); } final MatchedProduct matchedProduct = MatchedProduct.getMatchedProduct( product, - context.watch(), - context.watch(), + productPreferences, + userPreferences, ); final ProductCompatibilityHelper helper = ProductCompatibilityHelper(matchedProduct); diff --git a/packages/smooth_app/lib/data_models/user_preferences.dart b/packages/smooth_app/lib/data_models/user_preferences.dart index ca4c0f47cfb..0cebce756b1 100644 --- a/packages/smooth_app/lib/data_models/user_preferences.dart +++ b/packages/smooth_app/lib/data_models/user_preferences.dart @@ -27,6 +27,7 @@ class UserPreferences extends ChangeNotifier { static const String _TAG_CAMERA_DECLINE = 'declined_camera_use_once'; static const String _TAG_CRASH_REPORTS = 'crash_reports'; static const String _TAG_ANALYTICS_REPORTS = 'analytics_reports'; + static const String _TAG_EXCLUDED_ATTRIBUTE_IDS = 'excluded_attributes'; Future init(final ProductPreferences productPreferences) async { if (_sharedPreferences.getBool(_TAG_INIT) != null) { @@ -109,6 +110,13 @@ class UserPreferences extends ChangeNotifier { bool? getFlag(final String key) => _sharedPreferences.getBool(_getFlagTag(key)); + List getExcludedAttributeIds() => + _sharedPreferences.getStringList(_TAG_EXCLUDED_ATTRIBUTE_IDS) ?? + []; + + Future setExcludedAttributeIds(final List value) async => + _sharedPreferences.setStringList(_TAG_EXCLUDED_ATTRIBUTE_IDS, value); + Future setDevMode(final int value) async => _sharedPreferences.setInt(_TAG_DEV_MODE, value); diff --git a/packages/smooth_app/lib/helpers/product_cards_helper.dart b/packages/smooth_app/lib/helpers/product_cards_helper.dart index cb154c102c4..4c110cda382 100644 --- a/packages/smooth_app/lib/helpers/product_cards_helper.dart +++ b/packages/smooth_app/lib/helpers/product_cards_helper.dart @@ -38,10 +38,14 @@ Widget buildProductSmoothCard({ List getPopulatedAttributes( final Product product, final List attributeIds, + final List excludedAttributeIds, ) { final List result = []; final Map attributes = product.getAttributes(attributeIds); for (final String attributeId in attributeIds) { + if (excludedAttributeIds.contains(attributeId)) { + continue; + } Attribute? attribute = attributes[attributeId]; // Some attributes selected in the user preferences might be unavailable for some products if (attribute == null) { diff --git a/packages/smooth_app/lib/helpers/smooth_matched_product.dart b/packages/smooth_app/lib/helpers/smooth_matched_product.dart index 5cd5cdbb3ea..e8e7c28bd01 100644 --- a/packages/smooth_app/lib/helpers/smooth_matched_product.dart +++ b/packages/smooth_app/lib/helpers/smooth_matched_product.dart @@ -25,12 +25,25 @@ abstract class MatchedProduct { final Product product, final ProductPreferencesManager productPreferencesManager, final UserPreferences userPreferences, - ) => - userPreferences.getFlag( - UserPreferencesDevMode.userPreferencesFlagLenientMatching) ?? - false - ? _StrongMatchedProduct(product, productPreferencesManager) - : _LenientMatchedProduct(product, productPreferencesManager); + ) { + final List excludedAttributeIds = + userPreferences.getExcludedAttributeIds(); + if (userPreferences.getFlag( + UserPreferencesDevMode.userPreferencesFlagStrongMatching, + ) ?? + false) { + return _StrongMatchedProduct( + product, + productPreferencesManager, + excludedAttributeIds, + ); + } + return _LenientMatchedProduct( + product, + productPreferencesManager, + excludedAttributeIds, + ); + } final Product product; double get score; @@ -61,6 +74,7 @@ class _StrongMatchedProduct extends MatchedProduct { _StrongMatchedProduct( final Product product, final ProductPreferencesManager productPreferencesManager, + final List excludedAttributeIds, ) : super(product) { final List? attributeGroups = product.attributeGroups; if (attributeGroups == null) { @@ -71,6 +85,9 @@ class _StrongMatchedProduct extends MatchedProduct { for (final AttributeGroup group in attributeGroups) { if (group.attributes != null) { for (final Attribute attribute in group.attributes!) { + if (excludedAttributeIds.contains(attribute.id)) { + continue; + } final PreferenceImportance? preferenceImportance = productPreferencesManager.getPreferenceImportanceFromImportanceId( productPreferencesManager.getImportanceIdForAttributeId( @@ -126,6 +143,7 @@ class _LenientMatchedProduct extends MatchedProduct { _LenientMatchedProduct( final Product product, final ProductPreferencesManager productPreferencesManager, + final List excludedAttributeIds, ) : super(product) { _score = 0.0; int numAttributesComputed = 0; @@ -133,6 +151,9 @@ class _LenientMatchedProduct extends MatchedProduct { for (final AttributeGroup group in product.attributeGroups!) { if (group.attributes != null) { for (final Attribute attribute in group.attributes!) { + if (excludedAttributeIds.contains(attribute.id)) { + continue; + } final String importanceLevel = productPreferencesManager .getImportanceIdForAttributeId(attribute.id!); // Check whether any mandatory attribute is incompatible diff --git a/packages/smooth_app/lib/pages/product/summary_card.dart b/packages/smooth_app/lib/pages/product/summary_card.dart index 3a89e34d99a..474235623da 100644 --- a/packages/smooth_app/lib/pages/product/summary_card.dart +++ b/packages/smooth_app/lib/pages/product/summary_card.dart @@ -149,8 +149,15 @@ class _SummaryCardState extends State { Widget _buildSummaryCardContent(BuildContext context) { final LocalDatabase localDatabase = context.read(); final AppLocalizations localizations = AppLocalizations.of(context)!; - final List scoreAttributes = - getPopulatedAttributes(widget._product, SCORE_ATTRIBUTE_IDS); + final UserPreferences userPreferences = context.read(); + + final List excludedAttributeIds = + userPreferences.getExcludedAttributeIds(); + final List scoreAttributes = getPopulatedAttributes( + widget._product, + SCORE_ATTRIBUTE_IDS, + excludedAttributeIds, + ); // Header takes 1 row. // Product Title Tile takes 2 rows to render. diff --git a/packages/smooth_app/lib/pages/user_preferences_attribute_group.dart b/packages/smooth_app/lib/pages/user_preferences_attribute_group.dart index c96f18829a3..e0dd0973062 100644 --- a/packages/smooth_app/lib/pages/user_preferences_attribute_group.dart +++ b/packages/smooth_app/lib/pages/user_preferences_attribute_group.dart @@ -75,13 +75,14 @@ class UserPreferencesAttributeGroup extends AbstractUserPreferences { ), ); } - final List attributes = group.attributes!; - result.addAll( - List.generate( - attributes.length, - (int index) => AttributeButton(attributes[index], productPreferences), - ), - ); + final List excludedAttributeIds = + userPreferences.getExcludedAttributeIds(); + for (final Attribute attribute in group.attributes!) { + if (excludedAttributeIds.contains(attribute.id)) { + continue; + } + result.add(AttributeButton(attribute, productPreferences)); + } return result; } } diff --git a/packages/smooth_app/lib/pages/user_preferences_dev_mode.dart b/packages/smooth_app/lib/pages/user_preferences_dev_mode.dart index d4f1d81ea1e..1b391cc3576 100644 --- a/packages/smooth_app/lib/pages/user_preferences_dev_mode.dart +++ b/packages/smooth_app/lib/pages/user_preferences_dev_mode.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:openfoodfacts/model/Attribute.dart'; import 'package:openfoodfacts/utils/OpenFoodAPIConfiguration.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/product_list.dart'; @@ -37,7 +38,7 @@ class UserPreferencesDevMode extends AbstractUserPreferences { static const String userPreferencesFlagProd = '__devWorkingOnProd'; static const String userPreferencesTestEnvHost = '__testEnvHost'; static const String userPreferencesFlagUseMLKit = '__useMLKit'; - static const String userPreferencesFlagLenientMatching = '__lenientMatching'; + static const String userPreferencesFlagStrongMatching = '__lenientMatching'; static const String userPreferencesFlagAdditionalButton = '__additionalButtonOnProductPage'; static const String userPreferencesFlagEditIngredients = '__editIngredients'; @@ -189,12 +190,12 @@ class UserPreferencesDevMode extends AbstractUserPreferences { title: const Text('Switch between strong and lenient matching'), subtitle: Text( 'Current matching level is ' - '${(userPreferences.getFlag(userPreferencesFlagLenientMatching) ?? false) ? 'strong' : 'lenient'}', + '${(userPreferences.getFlag(userPreferencesFlagStrongMatching) ?? false) ? 'strong' : 'lenient'}', ), onTap: () async { await userPreferences.setFlag( - userPreferencesFlagLenientMatching, - !(userPreferences.getFlag(userPreferencesFlagLenientMatching) ?? + userPreferencesFlagStrongMatching, + !(userPreferences.getFlag(userPreferencesFlagStrongMatching) ?? false)); setState(() {}); }, @@ -243,6 +244,22 @@ class UserPreferencesDevMode extends AbstractUserPreferences { } }, ), + SwitchListTile( + title: const Text('Exclude ecoscore'), + value: userPreferences + .getExcludedAttributeIds() + .contains(Attribute.ATTRIBUTE_ECOSCORE), + onChanged: (bool value) async { + const String tag = Attribute.ATTRIBUTE_ECOSCORE; + final List list = userPreferences.getExcludedAttributeIds(); + list.removeWhere((final String element) => element == tag); + if (value) { + list.add(tag); + } + await userPreferences.setExcludedAttributeIds(list); + setState(() {}); + }, + ), ]; Future _changeTestEnvHost() async {