Skip to content

Commit

Permalink
feat: 5643 - removed irrelevant editors for non-FOOD products
Browse files Browse the repository at this point in the history
Impacted files:
* `add_new_product_page.dart`: editors different when not FOOD; minor refactoring
* `edit_product_page.dart`: no ingredient editor for PRODUCTS
* `image_field_extension.dart`: now the main image fields depend on product type; minor refactoring (more compact `switch` syntax)
* `knowledge_panels_builder.dart`: minor fix
* `product_cards_helper.dart`: now the main image fields depend on product type
* `product_image_gallery_view.dart`: now the main image fields depend on product type
* `product_image_swipeable_view.dart`: now the main image fields depend on product type
  • Loading branch information
monsieurtanuki committed Oct 3, 2024
1 parent 778b3fb commit 2becf35
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 107 deletions.
116 changes: 54 additions & 62 deletions packages/smooth_app/lib/helpers/image_field_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,26 @@ import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dar
import 'package:smooth_app/pages/product/product_image_swipeable_view.dart';

extension ImageFieldSmoothieExtension on ImageField {
static const List<ImageField> orderedMain = <ImageField>[
ImageField.FRONT,
ImageField.INGREDIENTS,
ImageField.NUTRITION,
ImageField.PACKAGING,
];
static List<ImageField> getOrderedMainImageFields(
final ProductType? productType,
) =>
switch (productType) {
ProductType.product => const <ImageField>[
ImageField.FRONT,
ImageField.PACKAGING,
],
ProductType.beauty => const <ImageField>[
ImageField.FRONT,
ImageField.INGREDIENTS,
ImageField.PACKAGING,
],
null || ProductType.food || ProductType.petFood => const <ImageField>[
ImageField.FRONT,
ImageField.INGREDIENTS,
ImageField.NUTRITION,
ImageField.PACKAGING,
],
};

void setUrl(final Product product, final String url) {
switch (this) {
Expand All @@ -31,67 +45,45 @@ extension ImageFieldSmoothieExtension on ImageField {
}
}

String getProductImageButtonText(final AppLocalizations appLocalizations) {
switch (this) {
case ImageField.FRONT:
return appLocalizations.front_photo;
case ImageField.INGREDIENTS:
return appLocalizations.ingredients_photo;
case ImageField.NUTRITION:
return appLocalizations.nutrition_facts_photo;
case ImageField.PACKAGING:
return appLocalizations.packaging_information_photo;
case ImageField.OTHER:
return appLocalizations.more_photos;
}
}
String getProductImageButtonText(final AppLocalizations appLocalizations) =>
switch (this) {
ImageField.FRONT => appLocalizations.front_photo,
ImageField.INGREDIENTS => appLocalizations.ingredients_photo,
ImageField.NUTRITION => appLocalizations.nutrition_facts_photo,
ImageField.PACKAGING => appLocalizations.packaging_information_photo,
ImageField.OTHER => appLocalizations.more_photos,
};

/// Returns a verbose description of the image field.
String getImagePageTitle(final AppLocalizations appLocalizations) {
switch (this) {
case ImageField.FRONT:
return appLocalizations.front_packaging_photo_title;
case ImageField.INGREDIENTS:
return appLocalizations.ingredients_photo_title;
case ImageField.NUTRITION:
return appLocalizations.nutritional_facts_photo_title;
case ImageField.PACKAGING:
return appLocalizations.recycling_photo_title;
case ImageField.OTHER:
return appLocalizations.take_more_photo_title;
}
}
String getImagePageTitle(final AppLocalizations appLocalizations) =>
switch (this) {
ImageField.FRONT => appLocalizations.front_packaging_photo_title,
ImageField.INGREDIENTS => appLocalizations.ingredients_photo_title,
ImageField.NUTRITION => appLocalizations.nutritional_facts_photo_title,
ImageField.PACKAGING => appLocalizations.recycling_photo_title,
ImageField.OTHER => appLocalizations.take_more_photo_title,
};

/// Returns a compact description of the image field.
String getProductImageTitle(final AppLocalizations appLocalizations) {
switch (this) {
case ImageField.FRONT:
return appLocalizations.product;
case ImageField.INGREDIENTS:
return appLocalizations.ingredients;
case ImageField.NUTRITION:
return appLocalizations.nutrition;
case ImageField.PACKAGING:
return appLocalizations.packaging_information;
case ImageField.OTHER:
return appLocalizations.more_photos;
}
}
String getProductImageTitle(final AppLocalizations appLocalizations) =>
switch (this) {
ImageField.FRONT => appLocalizations.product,
ImageField.INGREDIENTS => appLocalizations.ingredients,
ImageField.NUTRITION => appLocalizations.nutrition,
ImageField.PACKAGING => appLocalizations.packaging_information,
ImageField.OTHER => appLocalizations.more_photos,
};

String getAddPhotoButtonText(final AppLocalizations appLocalizations) {
switch (this) {
case ImageField.FRONT:
return appLocalizations.front_packaging_photo_button_label;
case ImageField.INGREDIENTS:
return appLocalizations.ingredients_photo_button_label;
case ImageField.NUTRITION:
return appLocalizations.nutritional_facts_photo_button_label;
case ImageField.PACKAGING:
return appLocalizations.recycling_photo_button_label;
case ImageField.OTHER:
return appLocalizations.take_more_photo_button_label;
}
}
String getAddPhotoButtonText(final AppLocalizations appLocalizations) =>
switch (this) {
ImageField.FRONT => appLocalizations.front_packaging_photo_button_label,
ImageField.INGREDIENTS =>
appLocalizations.ingredients_photo_button_label,
ImageField.NUTRITION =>
appLocalizations.nutritional_facts_photo_button_label,
ImageField.PACKAGING => appLocalizations.recycling_photo_button_label,
ImageField.OTHER => appLocalizations.take_more_photo_button_label,
};

Widget getPhotoButton(
final BuildContext context,
Expand Down
4 changes: 3 additions & 1 deletion packages/smooth_app/lib/helpers/product_cards_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,9 @@ List<ProductImageData> getProductMainImagesData(
final OpenFoodFactsLanguage language,
) {
final List<ProductImageData> result = <ProductImageData>[];
for (final ImageField imageField in ImageFieldSmoothieExtension.orderedMain) {
for (final ImageField imageField
in ImageFieldSmoothieExtension.getOrderedMainImageFields(
product.productType)) {
result.add(getProductImageData(product, imageField, language));
}
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,14 @@ class KnowledgePanelsBuilder {
if (panel == null) {
// happened in https://github.com/openfoodfacts/smooth-app/issues/2682
// due to some inconsistencies in the data sent by the server
Logs.w(
'unknown panel "$panelId" for barcode "${product.barcode}"',
);
if (panelId == 'ecoscore' &&
(product.productType ?? ProductType.food) != ProductType.food) {
// just ignore
} else {
Logs.w(
'unknown panel "$panelId" for barcode "${product.barcode}"',
);
}
return null;
}
return KnowledgePanelCard(
Expand Down
85 changes: 58 additions & 27 deletions packages/smooth_app/lib/pages/product/add_new_product_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,20 @@ class _AddNewProductPageState extends State<AddNewProductPage>
with TraceableClientMixin, UpToDateMixin {
/// Count of "other" pictures uploaded.
int _otherCount = 0;
int _totalPages = 0;
double _progress = 0.0;
bool _isLastPage = false;

/// The behavior is different for FOOD. And we don't know about it at first.
bool get _probablyFood =>
(_inputProductType ?? ProductType.food) == ProductType.food;

/// Total number of pages: depends on product type.
int get _totalPages =>
(_probablyFood ? 3 : 1) +
(widget.displayProductType ? 1 : 0) +
(_probablyFood && widget.displayMisc ? 1 : 0) +
(widget.displayPictures ? 1 : 0);

double get _progress => (_pageNumber + 1) / _totalPages;
bool get _isLastPage => (_pageNumber + 1) == _totalPages;
ProductType? _inputProductType;
late ColorScheme _colorScheme;

Expand Down Expand Up @@ -112,7 +123,8 @@ class _AddNewProductPageState extends State<AddNewProductPage>

bool _ecoscoreExpanded = false;

int get _pageNumber => _pageController.page!.round();
int get _pageNumber =>
_pageController.hasClients ? _pageController.page!.round() : 0;

@override
String get actionName => 'Opened add_new_product_page';
Expand Down Expand Up @@ -159,18 +171,7 @@ class _AddNewProductPageState extends State<AddNewProductPage>
widget.events[EditProductAction.openPage]!,
barcode: barcode,
);
_totalPages = 3 +
(widget.displayProductType ? 1 : 0) +
(widget.displayMisc ? 1 : 0) +
(widget.displayPictures ? 1 : 0);
_progress = 1 / _totalPages;

_pageController.addListener(() {
setState(() {
_progress = (_pageNumber + 1) / _totalPages;
_isLastPage = (_pageNumber + 1) == _totalPages;
});
});
_pageController.addListener(() => setState(() {}));
}

Future<bool> _onWillPop() async {
Expand Down Expand Up @@ -262,10 +263,12 @@ class _AddNewProductPageState extends State<AddNewProductPage>
_buildCard(_getProductTypes(context)),
if (widget.displayPictures)
_buildCard(_getImageRows(context)),
_buildCard(_getNutriscoreRows(context)),
_buildCard(_getEcoscoreRows(context)),
_buildCard(_getNovaRows(context)),
if (widget.displayMisc) _buildCard(_getMiscRows(context)),
if (_probablyFood) _buildCard(_getNutriscoreRows(context)),
if (_probablyFood) _buildCard(_getEcoscoreRows(context)),
if (_probablyFood) _buildCard(_getNovaRows(context)),
if (!_probablyFood) _buildCard(_getOxFRows(context)),
if (_probablyFood && widget.displayMisc)
_buildCard(_getMiscRows(context)),
],
),
),
Expand Down Expand Up @@ -387,7 +390,7 @@ class _AddNewProductPageState extends State<AddNewProductPage>
);
},
child: Text(
(_pageController.hasClients ? _pageNumber : 0) >= 1
_pageNumber >= 1
? appLocalizations.previous_label
: appLocalizations.cancel,
style: const TextStyle(
Expand Down Expand Up @@ -623,6 +626,31 @@ class _AddNewProductPageState extends State<AddNewProductPage>
return rows;
}

/// More compact, for non-FOOD only.
List<Widget> _getOxFRows(final BuildContext context) {
return <Widget>[
AddNewProductTitle(AppLocalizations.of(context).new_product_title_misc),
AddNewProductEditorButton(
upToDateProduct,
_categoryEditor,
isLoggedInMandatory: widget.isLoggedInMandatory,
),
if (_inputProductType != ProductType.product)
AddNewProductEditorButton(
upToDateProduct,
_ingredientsEditor,
isLoggedInMandatory: widget.isLoggedInMandatory,
),
if (_inputProductType == ProductType.petFood)
AddNewProductEditorButton(
upToDateProduct,
_nutritionEditor,
isLoggedInMandatory: widget.isLoggedInMandatory,
),
_buildDetailsButton(context),
];
}

List<Widget> _getImageRows(final BuildContext context) {
final AppLocalizations appLocalizations = AppLocalizations.of(context);
final List<Widget> rows = <Widget>[];
Expand All @@ -635,7 +663,7 @@ class _AddNewProductPageState extends State<AddNewProductPage>
appLocalizations.new_product_title_pictures_details),
);

// Main 4 images first.
// Main images first.
final List<ProductImageData> productImagesData = getProductMainImagesData(
upToDateProduct,
ProductQuery.getLanguage(),
Expand Down Expand Up @@ -726,13 +754,16 @@ class _AddNewProductPageState extends State<AddNewProductPage>
AddNewProductTitle(
AppLocalizations.of(context).new_product_title_misc,
),
AddNewProductEditorButton(
upToDateProduct,
_detailsEditor,
isLoggedInMandatory: widget.isLoggedInMandatory,
),
_buildDetailsButton(context),
];

Widget _buildDetailsButton(final BuildContext context) =>
AddNewProductEditorButton(
upToDateProduct,
_detailsEditor,
isLoggedInMandatory: widget.isLoggedInMandatory,
);

Widget _buildIngredientsButton(
final BuildContext context, {
final IconData? forceIconData,
Expand Down
18 changes: 10 additions & 8 deletions packages/smooth_app/lib/pages/product/edit_product_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,17 @@ class _EditProductPageState extends State<EditProductPage> with UpToDateMixin {
SimpleInputPageCategoryHelper(),
],
),
_ListTitleItem(
leading: const SvgIcon('assets/cacheTintable/ingredients.svg'),
title:
appLocalizations.edit_product_form_item_ingredients_title,
onTap: () async => ProductFieldOcrIngredientEditor().edit(
context: context,
product: upToDateProduct,
if (upToDateProduct.productType != ProductType.product)
_ListTitleItem(
leading:
const SvgIcon('assets/cacheTintable/ingredients.svg'),
title:
appLocalizations.edit_product_form_item_ingredients_title,
onTap: () async => ProductFieldOcrIngredientEditor().edit(
context: context,
product: upToDateProduct,
),
),
),
if (upToDateProduct.productType == null ||
upToDateProduct.productType == ProductType.food)
_getSimpleListTileItem(SimpleInputPageCategoryHelper())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,17 @@ class ProductImageGalleryView extends StatefulWidget {
class _ProductImageGalleryViewState extends State<ProductImageGalleryView>
with UpToDateMixin {
late OpenFoodFactsLanguage _language;
late final List<ImageField> _mainImageFields;
bool _clickedOtherPictureButton = false;

@override
void initState() {
super.initState();
initUpToDate(widget.product, context.read<LocalDatabase>());
_language = ProductQuery.getLanguage();
_mainImageFields = ImageFieldSmoothieExtension.getOrderedMainImageFields(
widget.product.productType,
);
}

@override
Expand Down Expand Up @@ -113,11 +117,12 @@ class _ProductImageGalleryViewState extends State<ProductImageGalleryView>
(BuildContext context, int index) {
return _PhotoRow(
position: index,
imageField: _mainImageFields[index],
product: upToDateProduct,
language: _language,
);
},
childCount: 4,
childCount: _mainImageFields.length,
),
),
SliverPadding(
Expand Down Expand Up @@ -187,15 +192,16 @@ class _PhotoRow extends StatelessWidget {
required this.position,
required this.product,
required this.language,
required this.imageField,
});

final int position;
final Product product;
final OpenFoodFactsLanguage language;
final ImageField imageField;

@override
Widget build(BuildContext context) {
final ImageField imageField = _getImageField(position);
final TransientFile transientFile = _getTransientFile(imageField);

final bool expired = transientFile.expired;
Expand Down Expand Up @@ -293,7 +299,4 @@ class _PhotoRow extends StatelessWidget {
imageField,
language,
);

ImageField _getImageField(final int index) =>
ImageFieldSmoothieExtension.orderedMain[index];
}
Loading

0 comments on commit 2becf35

Please sign in to comment.