From 6cfdb78cfd0c3b5802fb0529cc963c47be504f9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 19:51:35 +0100 Subject: [PATCH 1/7] chore(deps): bump crowdin/github-action from 2.2.0 to 2.3.0 (#5762) Bumps [crowdin/github-action](https://github.com/crowdin/github-action) from 2.2.0 to 2.3.0. - [Release notes](https://github.com/crowdin/github-action/releases) - [Commits](https://github.com/crowdin/github-action/compare/v2.2.0...v2.3.0) --- updated-dependencies: - dependency-name: crowdin/github-action 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/crowdin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 27d112d9972..ff93389aafb 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v4 - name: crowdin action - uses: crowdin/github-action@v2.2.0 + uses: crowdin/github-action@v2.3.0 continue-on-error: true with: # Upload sources to Crowdin From 493ac30242c4a15df68542e7ac35d71b22f7d4f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 20:02:46 +0100 Subject: [PATCH 2/7] chore(deps): bump rexml in /packages/smooth_app/ios in the bundler group (#5765) Bumps the bundler group in /packages/smooth_app/ios with 1 update: [rexml](https://github.com/ruby/rexml). Updates `rexml` from 3.3.8 to 3.3.9 - [Release notes](https://github.com/ruby/rexml/releases) - [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md) - [Commits](https://github.com/ruby/rexml/compare/v3.3.8...v3.3.9) --- updated-dependencies: - dependency-name: rexml dependency-type: indirect dependency-group: bundler ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/ios/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/smooth_app/ios/Gemfile.lock b/packages/smooth_app/ios/Gemfile.lock index b47a9626f5f..651cd238a45 100644 --- a/packages/smooth_app/ios/Gemfile.lock +++ b/packages/smooth_app/ios/Gemfile.lock @@ -183,7 +183,7 @@ GEM trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.3.8) + rexml (3.3.9) rouge (2.0.7) ruby2_keywords (0.0.5) rubyzip (2.3.2) From 688ddc214f15fbba95954835d9c0e26a876aef68 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Mon, 28 Oct 2024 21:57:31 +0100 Subject: [PATCH 3/7] feat: Improvements for the product page (Part 2) (#5764) * Improvements for the product page * Fix Android issues * Remove unused variable --- .../lib/helpers/product_cards_helper.dart | 117 ++++++++++--- .../knowledge_panel_group_card.dart | 14 +- .../knowledge_panel_product_cards.dart | 42 +---- .../lib/pages/prices/prices_card.dart | 154 ++++++++++-------- .../product_page/new_product_footer.dart | 40 ++--- .../product_page/new_product_page.dart | 2 - .../lib/pages/product/website_card.dart | 90 +++++----- 7 files changed, 272 insertions(+), 187 deletions(-) diff --git a/packages/smooth_app/lib/helpers/product_cards_helper.dart b/packages/smooth_app/lib/helpers/product_cards_helper.dart index 4f387736d44..64bf8acd5f3 100644 --- a/packages/smooth_app/lib/helpers/product_cards_helper.dart +++ b/packages/smooth_app/lib/helpers/product_cards_helper.dart @@ -10,6 +10,8 @@ import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/helpers/image_field_extension.dart'; import 'package:smooth_app/helpers/ui_helpers.dart'; import 'package:smooth_app/query/product_query.dart'; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; +import 'package:smooth_app/themes/theme_provider.dart'; import 'package:smooth_app/widgets/smooth_app_bar.dart'; SmoothAppBar buildEditProductAppBar({ @@ -88,26 +90,99 @@ const EdgeInsets SMOOTH_CARD_PADDING = EdgeInsets.symmetric( /// A SmoothCard on Product cards using default margin and padding. Widget buildProductSmoothCard({ Widget? header, + Widget? title, + EdgeInsetsGeometry? titlePadding, required Widget body, - EdgeInsets? padding = EdgeInsets.zero, - EdgeInsets? margin = const EdgeInsets.symmetric( + EdgeInsetsGeometry? padding = EdgeInsets.zero, + EdgeInsetsGeometry? margin = const EdgeInsets.symmetric( horizontal: SMALL_SPACE, ), -}) => - SmoothCard( - margin: margin, - padding: padding, - child: switch (header) { - Object _ => Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (header != null) header, - body, - ], +}) { + assert( + (header != null && title == null) || header == null, + "You can't pass a header and a title at the same time", + ); + + Widget child; + + if (title != null) { + child = Column( + mainAxisSize: MainAxisSize.min, + children: [ + _ProductSmoothCardTitle( + title: title, + padding: titlePadding, + ), + body, + ], + ); + } else if (header != null) { + child = Column( + mainAxisSize: MainAxisSize.min, + children: [ + header, + body, + ], + ); + } else { + child = body; + } + + return SmoothCard( + margin: margin, + padding: padding, + child: child, + ); +} + +class _ProductSmoothCardTitle extends StatelessWidget { + const _ProductSmoothCardTitle({ + required this.title, + this.padding, + }); + + final Widget title; + final EdgeInsetsGeometry? padding; + + @override + Widget build(BuildContext context) { + final SmoothColorsThemeExtension colors = + Theme.of(context).extension()!; + final EdgeInsetsGeometry effectivePadding = padding ?? + const EdgeInsetsDirectional.symmetric( + vertical: MEDIUM_SPACE, + ); + final TextStyle titleStyle = + Theme.of(context).textTheme.displaySmall ?? const TextStyle(); + final double fontSize = titleStyle.fontSize ?? 15.0; + + return Container( + constraints: BoxConstraints( + minHeight: + MEDIUM_SPACE * 2 + MediaQuery.textScalerOf(context).scale(fontSize), + ), + decoration: BoxDecoration( + color: context.lightTheme() + ? colors.primaryMedium + : colors.primarySemiDark, + borderRadius: const BorderRadius.vertical( + top: ROUNDED_RADIUS, + ), + ), + padding: effectivePadding, + child: Center( + child: DefaultTextStyle( + style: titleStyle, + textAlign: TextAlign.center, + child: SizedBox( + width: double.infinity, + child: title, ), - _ => body - }, + ), + ), ); + } +} // used to be in now defunct `AttributeListExpandable` List getPopulatedAttributes( @@ -170,7 +245,7 @@ List getSortedAttributes( } final Map> mandatoryAttributesByGroup = >{}; - // collecting all the mandatory attributes, by group +// collecting all the mandatory attributes, by group for (final AttributeGroup attributeGroup in product.attributeGroups!) { mandatoryAttributesByGroup[attributeGroup.id!] = getFilteredAttributes( attributeGroup, @@ -181,7 +256,7 @@ List getSortedAttributes( ); } - // now ordering by attribute group order +// now ordering by attribute group order for (final String attributeGroupId in attributeGroupOrder) { final List? attributes = mandatoryAttributesByGroup[attributeGroupId]; @@ -266,7 +341,7 @@ ProductImageData getProductImageData( language, ); if (productImage != null) { - // we found a localized version for this image +// we found a localized version for this image return ProductImageData( imageId: productImage.imgid, imageField: imageField, @@ -344,7 +419,7 @@ List getRawProductImages( for (final ProductImage productImage in rawImages) { final int? imageId = int.tryParse(productImage.imgid!); if (imageId == null) { - // highly unlikely +// highly unlikely continue; } final ProductImage? previous = map[imageId]; @@ -354,12 +429,12 @@ List getRawProductImages( } final ImageSize? currentImageSize = productImage.size; if (currentImageSize == null) { - // highly unlikely +// highly unlikely continue; } final ImageSize? previousImageSize = previous.size; if (previousImageSize == imageSize) { - // we already have the best +// we already have the best continue; } map[imageId] = productImage; diff --git a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_group_card.dart b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_group_card.dart index 6c9ef63db4f..4b6d177491c 100644 --- a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_group_card.dart +++ b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_group_card.dart @@ -4,6 +4,8 @@ import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/knowledge_panel/knowledge_panels/knowledge_panel_card.dart'; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; +import 'package:smooth_app/themes/theme_provider.dart'; class KnowledgePanelGroupCard extends StatelessWidget { const KnowledgePanelGroupCard({ @@ -19,6 +21,9 @@ class KnowledgePanelGroupCard extends StatelessWidget { @override Widget build(BuildContext context) { final ThemeData themeData = Theme.of(context); + final SmoothColorsThemeExtension themeExtension = + themeData.extension()!; + return Provider( lazy: true, create: (_) => groupElement, @@ -32,8 +37,13 @@ class KnowledgePanelGroupCard extends StatelessWidget { explicitChildNodes: true, child: Text( groupElement.title!, - style: - themeData.textTheme.titleSmall!.apply(color: Colors.grey), + style: themeData.textTheme.titleSmall!.copyWith( + fontSize: 15.5, + fontWeight: FontWeight.w700, + color: context.lightTheme() + ? themeExtension.primaryUltraBlack + : themeExtension.primaryLight, + ), ), ), ), diff --git a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_product_cards.dart b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_product_cards.dart index 9cd29efdf45..e64e5c7f955 100644 --- a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_product_cards.dart +++ b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_product_cards.dart @@ -3,8 +3,6 @@ import 'package:flutter/material.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; import 'package:smooth_app/knowledge_panel/knowledge_panels_builder.dart'; -import 'package:smooth_app/themes/smooth_theme_colors.dart'; -import 'package:smooth_app/themes/theme_provider.dart'; class KnowledgePanelProductCards extends StatelessWidget { const KnowledgePanelProductCards(this.knowledgePanelWidgets); @@ -13,9 +11,6 @@ class KnowledgePanelProductCards extends StatelessWidget { @override Widget build(BuildContext context) { - final SmoothColorsThemeExtension colors = - Theme.of(context).extension()!; - final List widgetsWrappedInSmoothCards = knowledgePanelWidgets.map((Widget widget) { /// When we have a panel with a title (e.g. "Health"), we change @@ -26,31 +21,12 @@ class KnowledgePanelProductCards extends StatelessWidget { if (hasTitle) { content = buildProductSmoothCard( - body: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - decoration: BoxDecoration( - color: context.lightTheme() - ? colors.primaryMedium - : colors.primarySemiDark, - borderRadius: const BorderRadius.vertical( - top: ROUNDED_RADIUS, - ), - ), - width: double.infinity, - padding: const EdgeInsetsDirectional.symmetric( - vertical: SMALL_SPACE, - ), - child: Center(child: widget.children.first), - ), - Padding( - padding: SMOOTH_CARD_PADDING, - child: Column( - children: widget.children.sublist(1), - ), - ), - ], + title: Text((widget.children.first as KnowledgePanelTitle).title), + body: Padding( + padding: SMOOTH_CARD_PADDING, + child: Column( + children: widget.children.sublist(1), + ), ), padding: EdgeInsets.zero, margin: EdgeInsets.zero, @@ -71,10 +47,8 @@ class KnowledgePanelProductCards extends StatelessWidget { return Center( child: Padding( - padding: const EdgeInsetsDirectional.only( - bottom: SMALL_SPACE, - start: SMALL_SPACE, - end: SMALL_SPACE, + padding: const EdgeInsetsDirectional.symmetric( + horizontal: SMALL_SPACE, ), child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/packages/smooth_app/lib/pages/prices/prices_card.dart b/packages/smooth_app/lib/pages/prices/prices_card.dart index 1337706f7c5..cdbb73a386e 100644 --- a/packages/smooth_app/lib/pages/prices/prices_card.dart +++ b/packages/smooth_app/lib/pages/prices/prices_card.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -9,8 +11,9 @@ import 'package:smooth_app/pages/prices/get_prices_model.dart'; import 'package:smooth_app/pages/prices/price_meta_product.dart'; import 'package:smooth_app/pages/prices/prices_page.dart'; import 'package:smooth_app/pages/prices/product_price_add_page.dart'; -import 'package:smooth_app/resources/app_icons.dart'; +import 'package:smooth_app/resources/app_icons.dart' as icons; import 'package:smooth_app/themes/smooth_theme_colors.dart'; +import 'package:smooth_app/themes/theme_provider.dart'; /// Card that displays buttons related to prices. class PricesCard extends StatelessWidget { @@ -21,88 +24,109 @@ class PricesCard extends StatelessWidget { @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); - final SmoothColorsThemeExtension? themeExtension = - Theme.of(context).extension(); + final SmoothColorsThemeExtension themeExtension = + Theme.of(context).extension()!; return buildProductSmoothCard( + title: Stack( + children: [ + Positioned.directional( + textDirection: Directionality.of(context), + start: LARGE_SPACE, + child: Container( + decoration: BoxDecoration( + color: themeExtension.orange, + shape: BoxShape.circle, + ), + padding: const EdgeInsetsDirectional.only( + top: 5.0, + start: 6.0, + end: 6.0, + bottom: 7.0, + ), + child: const icons.Lab( + size: 10.0, + color: Colors.white, + ), + ), + ), + const SizedBox(width: SMALL_SPACE), + Center(child: Text(appLocalizations.prices_generic_title)), + ], + ), body: Container( width: double.infinity, padding: const EdgeInsetsDirectional.all(LARGE_SPACE), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, + child: Stack( children: [ - Row( - mainAxisSize: MainAxisSize.min, + Positioned.directional( + textDirection: Directionality.of(context), + bottom: 0.0, + end: 0.0, + child: const _PricesCardTitleIcon(), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context).prices_generic_title, - style: Theme.of(context).textTheme.displaySmall, - ), - const SizedBox(width: SMALL_SPACE), - Container( - decoration: BoxDecoration( - color: themeExtension!.secondaryNormal, - borderRadius: CIRCULAR_BORDER_RADIUS, - ), - margin: const EdgeInsets.only(top: 0.5), - padding: const EdgeInsets.symmetric( - horizontal: MEDIUM_SPACE, - vertical: VERY_SMALL_SPACE, - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - appLocalizations.preview_badge, - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, + Padding( + padding: const EdgeInsets.symmetric(horizontal: SMALL_SPACE), + child: SmoothLargeButtonWithIcon( + text: appLocalizations.prices_view_prices, + icon: CupertinoIcons.tag_fill, + onPressed: () async => Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => PricesPage( + GetPricesModel.product( + product: PriceMetaProduct.product(product), + context: context, + ), ), ), - const SizedBox(width: SMALL_SPACE), - const Lab( - color: Colors.white, - size: 13.0, - ), - ], + ), ), ), - ], - ), - const SizedBox(height: SMALL_SPACE), - Padding( - padding: const EdgeInsets.all(SMALL_SPACE), - child: SmoothLargeButtonWithIcon( - text: appLocalizations.prices_view_prices, - icon: CupertinoIcons.tag_fill, - onPressed: () async => Navigator.of(context).push( - MaterialPageRoute( - builder: (BuildContext context) => PricesPage( - GetPricesModel.product( - product: PriceMetaProduct.product(product), - context: context, - ), + Padding( + padding: const EdgeInsets.all(SMALL_SPACE), + child: SmoothLargeButtonWithIcon( + text: appLocalizations.prices_add_a_price, + icon: Icons.add, + onPressed: () async => ProductPriceAddPage.showProductPage( + context: context, + product: PriceMetaProduct.product(product), + proofType: ProofType.priceTag, ), ), ), - ), - ), - Padding( - padding: const EdgeInsets.all(SMALL_SPACE), - child: SmoothLargeButtonWithIcon( - text: appLocalizations.prices_add_a_price, - icon: Icons.add, - onPressed: () async => ProductPriceAddPage.showProductPage( - context: context, - product: PriceMetaProduct.product(product), - proofType: ProofType.priceTag, - ), - ), + ], ), ], ), ), + margin: const EdgeInsetsDirectional.only( + start: SMALL_SPACE, + end: SMALL_SPACE, + top: VERY_LARGE_SPACE, + ), + ); + } +} + +class _PricesCardTitleIcon extends StatelessWidget { + const _PricesCardTitleIcon(); + + @override + Widget build(BuildContext context) { + final SmoothColorsThemeExtension? themeExtension = + Theme.of(context).extension(); + + return Transform.rotate( + angle: -pi / 6, + child: icons.Lab( + size: 100.0, + color: themeExtension?.orange + .withOpacity(context.lightTheme() ? 0.15 : 0.4), + ), ); } } diff --git a/packages/smooth_app/lib/pages/product/product_page/new_product_footer.dart b/packages/smooth_app/lib/pages/product/product_page/new_product_footer.dart index 520f8fbfafb..bfc44778cf6 100644 --- a/packages/smooth_app/lib/pages/product/product_page/new_product_footer.dart +++ b/packages/smooth_app/lib/pages/product/product_page/new_product_footer.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; @@ -25,33 +27,23 @@ import 'package:smooth_app/themes/theme_provider.dart'; class ProductFooter extends StatelessWidget { const ProductFooter({super.key}); - static const double kHeight = 46.0; + static const double kHeight = 48.0; @override Widget build(BuildContext context) { - double bottomPadding = MediaQuery.viewPaddingOf(context).bottom; - // Add an extra padding (for Android) - if (bottomPadding == 0.0) { - bottomPadding = 16.0; - } - return DecoratedBox( decoration: BoxDecoration( color: Theme.of(context).scaffoldBackgroundColor, boxShadow: [ BoxShadow( - color: Theme.of(context).shadowColor.withOpacity(0.1), + color: Theme.of(context) + .shadowColor + .withOpacity(context.lightTheme() ? 0.25 : 0.6), blurRadius: 10.0, ), ], ), - child: Padding( - padding: EdgeInsetsDirectional.only( - top: 16.0, - bottom: bottomPadding, - ), - child: const _ProductFooterButtonsBar(), - ), + child: const _ProductFooterButtonsBar(), ); } } @@ -64,8 +56,14 @@ class _ProductFooterButtonsBar extends StatelessWidget { final SmoothColorsThemeExtension themeExtension = Theme.of(context).extension()!; + double bottomPadding = MediaQuery.viewPaddingOf(context).bottom; + // Add an extra padding (for Android) + if (Platform.isAndroid) { + bottomPadding += MEDIUM_SPACE; + } + return SizedBox( - height: ProductFooter.kHeight, + height: ProductFooter.kHeight + LARGE_SPACE + bottomPadding, child: OutlinedButtonTheme( data: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( @@ -75,13 +73,16 @@ class _ProductFooterButtonsBar extends StatelessWidget { side: BorderSide(color: themeExtension.greyLight), padding: const EdgeInsetsDirectional.symmetric( horizontal: 19.0, - vertical: 14.0, ), ), ), child: ListView( - padding: - const EdgeInsetsDirectional.symmetric(horizontal: SMALL_SPACE), + padding: EdgeInsetsDirectional.only( + start: SMALL_SPACE, + end: SMALL_SPACE, + top: LARGE_SPACE, + bottom: bottomPadding, + ), scrollDirection: Axis.horizontal, children: const [ SizedBox(width: 10.0), @@ -383,6 +384,7 @@ class _ProductFooterFilledButton extends StatelessWidget { side: BorderSide.none, ), child: Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ IconTheme( data: const IconThemeData( diff --git a/packages/smooth_app/lib/pages/product/product_page/new_product_page.dart b/packages/smooth_app/lib/pages/product/product_page/new_product_page.dart index 837922549db..2747e07c2f3 100644 --- a/packages/smooth_app/lib/pages/product/product_page/new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/product_page/new_product_page.dart @@ -258,8 +258,6 @@ class ProductPageState extends State if (questionsLayout == ProductQuestionsLayout.banner) // assuming it's tall enough in order to go above the banner const SizedBox(height: 4 * VERY_LARGE_SPACE), - // Space for the navigation bar - SizedBox(height: MediaQuery.paddingOf(context).bottom), ], ), ); diff --git a/packages/smooth_app/lib/pages/product/website_card.dart b/packages/smooth_app/lib/pages/product/website_card.dart index 28f3d400db0..df800cc25db 100644 --- a/packages/smooth_app/lib/pages/product/website_card.dart +++ b/packages/smooth_app/lib/pages/product/website_card.dart @@ -3,6 +3,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/helpers/launch_url_helper.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; +import 'package:smooth_app/resources/app_icons.dart' as icons; /// Card that displays a website link. class WebsiteCard extends StatelessWidget { @@ -15,58 +16,59 @@ class WebsiteCard extends StatelessWidget { final AppLocalizations localizations = AppLocalizations.of(context); final String website = _getWebsite(); - return buildProductSmoothCard( - body: Semantics( - label: localizations.product_field_website_title, - value: Uri.parse(website).host, - link: true, - excludeSemantics: true, + return Semantics( + label: localizations.product_field_website_title, + value: Uri.parse(website).host, + link: true, + excludeSemantics: true, + child: Padding( + padding: const EdgeInsetsDirectional.only( + top: VERY_LARGE_SPACE, + start: SMALL_SPACE, + end: SMALL_SPACE, + ), child: InkWell( onTap: () async => LaunchUrlHelper.launchURL(website), borderRadius: ROUNDED_BORDER_RADIUS, - child: Container( - width: double.infinity, - padding: const EdgeInsetsDirectional.only( - start: LARGE_SPACE, - top: LARGE_SPACE, - bottom: LARGE_SPACE, - // To be perfectly aligned with arrows - end: 21.0, - ), - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - localizations.product_field_website_title, - style: Theme.of(context).textTheme.displaySmall, - ), - const SizedBox(height: SMALL_SPACE), - Text( - website, - overflow: TextOverflow.ellipsis, - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith(color: Colors.blue), - ), - ], + child: buildProductSmoothCard( + title: Text(localizations.product_field_website_title), + body: Container( + width: double.infinity, + padding: const EdgeInsetsDirectional.only( + start: LARGE_SPACE, + top: LARGE_SPACE, + bottom: LARGE_SPACE, + // To be perfectly aligned with arrows + end: 21.0, + ), + child: Row( + children: [ + Expanded( + child: Text( + website, + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.blue), + ), ), - ), - const Icon(Icons.open_in_new), - ], + const Padding( + padding: EdgeInsetsDirectional.only( + start: 5.0, + end: 3.0, + ), + child: icons.ExternalLink( + size: 20.0, + ), + ), + ], + ), ), + margin: EdgeInsets.zero, ), ), ), - margin: const EdgeInsets.only( - left: SMALL_SPACE, - right: SMALL_SPACE, - bottom: MEDIUM_SPACE, - ), ); } From e4d68a2d659d463b7066ae0c3812af2e4c891928 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 07:00:53 +0100 Subject: [PATCH 4/7] chore(deps): bump share_plus in /packages/smooth_app (#5761) Bumps [share_plus](https://github.com/fluttercommunity/plus_plugins/tree/main/packages/share_plus) from 10.0.0 to 10.1.1. - [Release notes](https://github.com/fluttercommunity/plus_plugins/releases) - [Commits](https://github.com/fluttercommunity/plus_plugins/commits/share_plus-v10.1.1/packages/share_plus) --- updated-dependencies: - dependency-name: share_plus 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> --- packages/smooth_app/pubspec.lock | 16 ++++++++-------- packages/smooth_app/pubspec.yaml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index 90fa2c08bda..9a1087c5122 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -1370,18 +1370,18 @@ packages: dependency: "direct main" description: name: share_plus - sha256: "59dfd53f497340a0c3a81909b220cfdb9b8973a91055c4e5ab9b9b9ad7c513c0" + sha256: "3af2cda1752e5c24f2fc04b6083b40f013ffe84fb90472f30c6499a9213d5442" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.1.1" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface - sha256: "6ababf341050edff57da8b6990f11f4e99eaba837865e2e6defe16d039619db5" + sha256: c57c0bbfec7142e3a0f55633be504b796af72e60e3c791b44d5a017b985f7a48 url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.0.1" shared_preferences: dependency: "direct main" description: @@ -1687,10 +1687,10 @@ packages: dependency: transitive description: name: url_launcher_windows - sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.3" uuid: dependency: "direct main" description: @@ -1759,10 +1759,10 @@ packages: dependency: transitive description: name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "1.1.0" webdriver: dependency: transitive description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index 2ae7057e37c..603e8538125 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -57,7 +57,7 @@ dependencies: collection: 1.18.0 path: 1.9.0 path_provider: 2.1.4 - share_plus: 10.0.0 + share_plus: 10.1.1 fimber: 0.7.0 shimmer: ^3.0.0 rive: 0.13.15 From 1ce92df2c2d25cf8a33820422b5f848d6d280eb8 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 29 Oct 2024 07:15:31 +0100 Subject: [PATCH 5/7] feat: JDK 21 for Android (#5763) * Support JDK 21 (Android) * Use JDK 21 for GitHub Actions --- ...d-release-to-org-openfoodfacts-scanner.yml | 2 +- ...s-release-to-org-openfoodfacts-scanner.yml | 2 +- .github/workflows/postsubmit.yml | 2 +- .github/workflows/waldo_sessions.yml | 2 +- packages/smooth_app/android/app/build.gradle | 38 ++++++------------- .../android/app/src/main/AndroidManifest.xml | 1 - packages/smooth_app/android/build.gradle | 21 ++++++++++ packages/smooth_app/android/gradle.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 3 +- packages/smooth_app/android/settings.gradle | 7 ++-- 10 files changed, 44 insertions(+), 36 deletions(-) diff --git a/.github/workflows/android-release-to-org-openfoodfacts-scanner.yml b/.github/workflows/android-release-to-org-openfoodfacts-scanner.yml index 5bef5c55971..e0d33166834 100644 --- a/.github/workflows/android-release-to-org-openfoodfacts-scanner.yml +++ b/.github/workflows/android-release-to-org-openfoodfacts-scanner.yml @@ -50,7 +50,7 @@ on: required: true env: - JAVA_VERSION: 17 + JAVA_VERSION: 21 RUBY_VERSION: 3.2.0 jobs: diff --git a/.github/workflows/ios-release-to-org-openfoodfacts-scanner.yml b/.github/workflows/ios-release-to-org-openfoodfacts-scanner.yml index 566dd1869a4..3324cd2d9cf 100644 --- a/.github/workflows/ios-release-to-org-openfoodfacts-scanner.yml +++ b/.github/workflows/ios-release-to-org-openfoodfacts-scanner.yml @@ -34,7 +34,7 @@ on: required: true env: - JAVA_VERSION: 17 + JAVA_VERSION: 21 RUBY_VERSION: 3.2.0 jobs: diff --git a/.github/workflows/postsubmit.yml b/.github/workflows/postsubmit.yml index fed9ccddf9b..6351b6c0ac4 100644 --- a/.github/workflows/postsubmit.yml +++ b/.github/workflows/postsubmit.yml @@ -19,7 +19,7 @@ jobs: uses: actions/setup-java@v4.5.0 with: distribution: 'zulu' - java-version: 17 + java-version: 21 # Get the flutter version from ./flutter-version.txt - run: echo "FLUTTER_VERSION=$(cat flutter-version.txt)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/waldo_sessions.yml b/.github/workflows/waldo_sessions.yml index 81eb0d98e1d..07e4627272b 100644 --- a/.github/workflows/waldo_sessions.yml +++ b/.github/workflows/waldo_sessions.yml @@ -30,7 +30,7 @@ jobs: uses: actions/setup-java@v4.5.0 with: distribution: 'zulu' - java-version: 17 + java-version: 21 # Get the flutter version from ./flutter-version.txt - run: echo "FLUTTER_VERSION=$(cat flutter-version.txt)" >> $GITHUB_OUTPUT diff --git a/packages/smooth_app/android/app/build.gradle b/packages/smooth_app/android/app/build.gradle index 4d1eddb3c90..5ae28a77167 100644 --- a/packages/smooth_app/android/app/build.gradle +++ b/packages/smooth_app/android/app/build.gradle @@ -4,35 +4,20 @@ plugins { id "dev.flutter.flutter-gradle-plugin" } -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} android { - compileSdkVersion 34 - ndkVersion "25.1.8937393" + namespace = "org.openfoodfacts.app" + compileSdk = flutter.compileSdkVersion + ndkVersion = "27.0.12077973" compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + coreLibraryDesugaringEnabled true } kotlinOptions { - jvmTarget = '1.8' + jvmTarget = JavaVersion.VERSION_17 } sourceSets { @@ -41,10 +26,10 @@ android { defaultConfig { applicationId "org.openfoodfacts.scanner" - minSdkVersion 21 - targetSdkVersion 34 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName multiDexEnabled true } @@ -73,4 +58,5 @@ flutter { dependencies { implementation 'androidx.multidex:multidex:2.0.1' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2' } \ No newline at end of file diff --git a/packages/smooth_app/android/app/src/main/AndroidManifest.xml b/packages/smooth_app/android/app/src/main/AndroidManifest.xml index 212f5f042f2..013cabbe812 100644 --- a/packages/smooth_app/android/app/src/main/AndroidManifest.xml +++ b/packages/smooth_app/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ diff --git a/packages/smooth_app/android/build.gradle b/packages/smooth_app/android/build.gradle index bc157bd1a12..3b8a5cf6f1b 100644 --- a/packages/smooth_app/android/build.gradle +++ b/packages/smooth_app/android/build.gradle @@ -3,6 +3,27 @@ allprojects { google() mavenCentral() } + + subprojects { + afterEvaluate { + if (it.hasProperty('android')) { + it.android.compileSdkVersion = 35 + it.android.defaultConfig.targetSdkVersion = 35 + it.android.compileOptions.sourceCompatibility = JavaVersion.VERSION_21 + it.android.compileOptions.targetCompatibility = JavaVersion.VERSION_21 + tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + kotlinOptions.jvmTarget = JavaVersion.VERSION_21 + } + if (it.android.namespace == null) { + def manifest = new XmlSlurper().parse(file(it.android.sourceSets.main.manifest.srcFile)) + def packageName = manifest.@package.text() + android.namespace = packageName + println("Updating namespace ${packageName}") + } + } + } + project.buildDir = "${rootProject.buildDir}/${project.name}" + } } rootProject.buildDir = '../build' diff --git a/packages/smooth_app/android/gradle.properties b/packages/smooth_app/android/gradle.properties index 94adc3a3f97..25971708216 100644 --- a/packages/smooth_app/android/gradle.properties +++ b/packages/smooth_app/android/gradle.properties @@ -1,3 +1,3 @@ -org.gradle.jvmargs=-Xmx1536M +org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true android.enableJetifier=true diff --git a/packages/smooth_app/android/gradle/wrapper/gradle-wrapper.properties b/packages/smooth_app/android/gradle/wrapper/gradle-wrapper.properties index 3c472b99c6f..82e606a573c 100644 --- a/packages/smooth_app/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/smooth_app/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip + diff --git a/packages/smooth_app/android/settings.gradle b/packages/smooth_app/android/settings.gradle index 05e070bc760..2c926c94841 100644 --- a/packages/smooth_app/android/settings.gradle +++ b/packages/smooth_app/android/settings.gradle @@ -17,9 +17,10 @@ pluginManagement { } plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.3.0" apply false - id "org.jetbrains.kotlin.android" version "1.8.0" apply false + id "com.android.application" version "8.7.1" apply false + id "org.jetbrains.kotlin.android" version "2.0.20" apply false } -include ":app" \ No newline at end of file +include ":app" From 668ddbaa46571759aec5ff72a49a2136b31c46c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 08:42:36 +0100 Subject: [PATCH 6/7] chore(deps): bump rexml (#5766) Bumps the bundler group in /packages/smooth_app/android with 1 update: [rexml](https://github.com/ruby/rexml). Updates `rexml` from 3.3.8 to 3.3.9 - [Release notes](https://github.com/ruby/rexml/releases) - [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md) - [Commits](https://github.com/ruby/rexml/compare/v3.3.8...v3.3.9) --- updated-dependencies: - dependency-name: rexml dependency-type: indirect dependency-group: bundler ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/android/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/smooth_app/android/Gemfile.lock b/packages/smooth_app/android/Gemfile.lock index 444c18b1c6e..c0be1e563af 100644 --- a/packages/smooth_app/android/Gemfile.lock +++ b/packages/smooth_app/android/Gemfile.lock @@ -182,7 +182,7 @@ GEM trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.3.8) + rexml (3.3.9) rouge (2.0.7) ruby2_keywords (0.0.5) rubyzip (2.3.2) From db544a6ec802f4d928b7866e15d08b37e8b04a39 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:01:32 +0100 Subject: [PATCH 7/7] Update assets (#5434) Co-authored-by: teolemon --- .../onboarding/sample_product_data.json | 512 ++++++++++-------- 1 file changed, 285 insertions(+), 227 deletions(-) diff --git a/packages/smooth_app/assets/onboarding/sample_product_data.json b/packages/smooth_app/assets/onboarding/sample_product_data.json index 8da40ee7319..c364b4013e5 100644 --- a/packages/smooth_app/assets/onboarding/sample_product_data.json +++ b/packages/smooth_app/assets/onboarding/sample_product_data.json @@ -1,5 +1,5 @@ { - "code" : "093270067481501", + "code" : "93270067481501", "product" : { "additives_tags" : [], "attribute_groups" : [ @@ -278,13 +278,13 @@ "description" : "", "description_short" : "Very low environmental impact", "grade" : "a", - "icon_url" : "https://static.openfoodfacts.org/images/attributes/dist/ecoscore-a.svg", + "icon_url" : "https://static.openfoodfacts.org/images/attributes/dist/ecoscore-a-plus.svg", "id" : "ecoscore", "match" : 100, "name" : "Eco-Score", "panel_id" : "ecoscore", "status" : "known", - "title" : "Eco-Score A" + "title" : "Eco-Score A+" }, { "description" : "", @@ -351,8 +351,8 @@ "transportation_score" : 0 } ], - "epi_score" : 93, - "epi_value" : 4, + "epi_score" : 0, + "epi_value" : 0, "origins_from_categories" : [ "en:unknown" ], @@ -491,71 +491,71 @@ "world" : 0, "xk" : 4 }, - "value" : 4, + "value" : 0, "values" : { - "ad" : 13, - "al" : 4, - "at" : 10, - "ax" : 14, - "ba" : 6, - "be" : 17, - "bg" : 7, - "ch" : 14, - "cy" : 10, - "cz" : 11, - "de" : 13, - "dk" : 10, - "dz" : 11, - "ee" : 15, - "eg" : 9, - "es" : 10, - "fi" : 14, - "fo" : 13, - "fr" : 19, - "gg" : 16, - "gi" : 5, - "gr" : 11, - "hr" : 9, - "hu" : 8, - "ie" : 11, - "il" : 9, - "im" : 12, - "is" : 12, - "it" : 11, - "je" : 15, - "lb" : 10, - "li" : 14, - "lt" : 13, - "lu" : 16, - "lv" : 15, - "ly" : 12, - "ma" : 13, - "mc" : 12, - "md" : 8, - "me" : 10, - "mk" : 8, - "mt" : 13, - "nl" : 16, - "no" : 7, - "pl" : 8, - "ps" : 10, - "pt" : 6, - "ro" : 9, - "rs" : 5, - "se" : 6, - "si" : 10, - "sj" : 12, - "sk" : 8, - "sm" : 10, - "sy" : 8, - "tn" : 5, - "tr" : 5, - "ua" : 10, - "uk" : 14, - "us" : 4, - "va" : 8, - "world" : 4, - "xk" : 8 + "ad" : 9, + "al" : 0, + "at" : 6, + "ax" : 10, + "ba" : 2, + "be" : 13, + "bg" : 3, + "ch" : 10, + "cy" : 6, + "cz" : 7, + "de" : 9, + "dk" : 6, + "dz" : 7, + "ee" : 11, + "eg" : 5, + "es" : 6, + "fi" : 10, + "fo" : 9, + "fr" : 15, + "gg" : 12, + "gi" : 1, + "gr" : 7, + "hr" : 5, + "hu" : 4, + "ie" : 7, + "il" : 5, + "im" : 8, + "is" : 8, + "it" : 7, + "je" : 11, + "lb" : 6, + "li" : 10, + "lt" : 9, + "lu" : 12, + "lv" : 11, + "ly" : 8, + "ma" : 9, + "mc" : 8, + "md" : 4, + "me" : 6, + "mk" : 4, + "mt" : 9, + "nl" : 12, + "no" : 3, + "pl" : 4, + "ps" : 6, + "pt" : 2, + "ro" : 5, + "rs" : 1, + "se" : 2, + "si" : 6, + "sj" : 8, + "sk" : 4, + "sm" : 6, + "sy" : 4, + "tn" : 1, + "tr" : 1, + "ua" : 6, + "uk" : 10, + "us" : 0, + "va" : 4, + "world" : 0, + "xk" : 4 } }, "packaging" : { @@ -611,71 +611,71 @@ "score" : 98, "version" : "3.1.1" }, - "grade" : "a", + "grade" : "a-plus", "grades" : { - "ad" : "a", - "al" : "a", - "at" : "a", - "ax" : "a", - "ba" : "a", - "be" : "a", - "bg" : "a", - "ch" : "a", - "cy" : "a", - "cz" : "a", - "de" : "a", - "dk" : "a", - "dz" : "a", - "ee" : "a", - "eg" : "a", - "es" : "a", - "fi" : "a", - "fo" : "a", - "fr" : "a", - "gg" : "a", - "gi" : "a", - "gr" : "a", - "hr" : "a", - "hu" : "a", - "ie" : "a", - "il" : "a", - "im" : "a", - "is" : "a", - "it" : "a", - "je" : "a", - "lb" : "a", - "li" : "a", - "lt" : "a", - "lu" : "a", - "lv" : "a", - "ly" : "a", - "ma" : "a", - "mc" : "a", - "md" : "a", - "me" : "a", - "mk" : "a", - "mt" : "a", - "nl" : "a", - "no" : "a", - "pl" : "a", - "ps" : "a", - "pt" : "a", - "ro" : "a", - "rs" : "a", - "se" : "a", - "si" : "a", - "sj" : "a", - "sk" : "a", - "sm" : "a", - "sy" : "a", - "tn" : "a", - "tr" : "a", - "ua" : "a", - "uk" : "a", - "us" : "a", - "va" : "a", - "world" : "a", - "xk" : "a" + "ad" : "a-plus", + "al" : "a-plus", + "at" : "a-plus", + "ax" : "a-plus", + "ba" : "a-plus", + "be" : "a-plus", + "bg" : "a-plus", + "ch" : "a-plus", + "cy" : "a-plus", + "cz" : "a-plus", + "de" : "a-plus", + "dk" : "a-plus", + "dz" : "a-plus", + "ee" : "a-plus", + "eg" : "a-plus", + "es" : "a-plus", + "fi" : "a-plus", + "fo" : "a-plus", + "fr" : "a-plus", + "gg" : "a-plus", + "gi" : "a-plus", + "gr" : "a-plus", + "hr" : "a-plus", + "hu" : "a-plus", + "ie" : "a-plus", + "il" : "a-plus", + "im" : "a-plus", + "is" : "a-plus", + "it" : "a-plus", + "je" : "a-plus", + "lb" : "a-plus", + "li" : "a-plus", + "lt" : "a-plus", + "lu" : "a-plus", + "lv" : "a-plus", + "ly" : "a-plus", + "ma" : "a-plus", + "mc" : "a-plus", + "md" : "a-plus", + "me" : "a-plus", + "mk" : "a-plus", + "mt" : "a-plus", + "nl" : "a-plus", + "no" : "a-plus", + "pl" : "a-plus", + "ps" : "a-plus", + "pt" : "a-plus", + "ro" : "a-plus", + "rs" : "a-plus", + "se" : "a-plus", + "si" : "a-plus", + "sj" : "a-plus", + "sk" : "a-plus", + "sm" : "a-plus", + "sy" : "a-plus", + "tn" : "a-plus", + "tr" : "a-plus", + "ua" : "a-plus", + "uk" : "a-plus", + "us" : "a-plus", + "va" : "a-plus", + "world" : "a-plus", + "xk" : "a-plus" }, "previous_data" : { "agribalyse" : { @@ -704,76 +704,76 @@ "grade" : "a", "score" : 122 }, - "score" : 115, + "score" : 111, "scores" : { - "ad" : 123, - "al" : 115, - "at" : 121, - "ax" : 123, - "ba" : 117, + "ad" : 120, + "al" : 111, + "at" : 117, + "ax" : 121, + "ba" : 113, "be" : 123, - "bg" : 118, - "ch" : 123, - "cy" : 121, - "cz" : 122, - "de" : 123, - "dk" : 121, - "dz" : 122, - "ee" : 123, - "eg" : 120, - "es" : 121, - "fi" : 123, - "fo" : 123, + "bg" : 114, + "ch" : 121, + "cy" : 117, + "cz" : 118, + "de" : 120, + "dk" : 117, + "dz" : 118, + "ee" : 122, + "eg" : 116, + "es" : 117, + "fi" : 121, + "fo" : 120, "fr" : 123, "gg" : 123, - "gi" : 116, - "gr" : 122, - "hr" : 120, - "hu" : 119, - "ie" : 122, - "il" : 120, - "im" : 123, - "is" : 123, - "it" : 122, - "je" : 123, - "lb" : 121, - "li" : 123, - "lt" : 123, + "gi" : 112, + "gr" : 118, + "hr" : 116, + "hu" : 115, + "ie" : 118, + "il" : 116, + "im" : 119, + "is" : 119, + "it" : 118, + "je" : 122, + "lb" : 117, + "li" : 121, + "lt" : 120, "lu" : 123, - "lv" : 123, - "ly" : 123, - "ma" : 123, - "mc" : 123, - "md" : 119, - "me" : 121, - "mk" : 119, - "mt" : 123, + "lv" : 122, + "ly" : 119, + "ma" : 120, + "mc" : 119, + "md" : 115, + "me" : 117, + "mk" : 115, + "mt" : 120, "nl" : 123, - "no" : 118, - "pl" : 119, - "ps" : 121, - "pt" : 117, - "ro" : 120, - "rs" : 116, - "se" : 117, - "si" : 121, - "sj" : 123, - "sk" : 119, - "sm" : 121, - "sy" : 119, - "tn" : 116, - "tr" : 116, - "ua" : 121, - "uk" : 123, - "us" : 115, - "va" : 119, - "world" : 115, - "xk" : 119 + "no" : 114, + "pl" : 115, + "ps" : 117, + "pt" : 113, + "ro" : 116, + "rs" : 112, + "se" : 113, + "si" : 117, + "sj" : 119, + "sk" : 115, + "sm" : 117, + "sy" : 115, + "tn" : 112, + "tr" : 112, + "ua" : 117, + "uk" : 121, + "us" : 111, + "va" : 115, + "world" : 111, + "xk" : 115 }, "status" : "known" }, - "ecoscore_grade" : "a", - "ecoscore_score" : 115, + "ecoscore_grade" : "a-plus", + "ecoscore_score" : 111, "environment_impact_level_tags" : [], "ingredients_analysis_tags" : [ "en:palm-oil-free", @@ -895,7 +895,7 @@ "title_element" : { "icon_color_from_evaluation" : true, "icon_url" : "https://static.openfoodfacts.org/images/icons/dist/car.svg", - "subtitle" : "51 g CO² per 100g of product", + "subtitle" : "51 g CO₂e per 100g of product", "title" : "Equal to driving 0.3 km in a petrol car" }, "topics" : [ @@ -956,9 +956,10 @@ ], "level" : "info", "title_element" : { - "grade" : "a", - "icon_url" : "https://static.openfoodfacts.org/images/attributes/dist/ecoscore-a.svg", - "title" : "Eco-Score A - Very low environmental impact", + "grade" : "a_plus", + "icon_url" : "https://static.openfoodfacts.org/images/attributes/dist/ecoscore-a-plus.svg", + "name" : "Eco-Score", + "title" : "Eco-Score A-PLUS - Very low environmental impact", "type" : "grade" }, "topics" : [ @@ -1075,12 +1076,12 @@ ], "level" : "info", "title_element" : { - "grade" : "a", + "grade" : "a_plus", "icon_color_from_evaluation" : true, "icon_size" : "small", "icon_url" : "https://static.openfoodfacts.org/images/icons/dist/lca.svg", "subtitle" : "Category: Soup, mixed vegetables, prepacked, to be reheated", - "title" : "Average impact of products of the same category: A (Score: 98/100)", + "title" : "Average impact of products of the same category: A+ (Score: 98/100)", "type" : "grade" }, "topics" : [ @@ -1092,7 +1093,7 @@ { "element_type" : "text", "text_element" : { - "html" : "\n Environmental policy: +4
\n Transportation: 0
\n ", + "html" : "\n Environmental policy: 0
\n Transportation: 0
\n ", "type" : "default" } }, @@ -1136,14 +1137,14 @@ } } ], - "evaluation" : "average", + "evaluation" : "bad", "level" : "info", "title_element" : { "icon_color_from_evaluation" : true, "icon_size" : "small", "icon_url" : "https://static.openfoodfacts.org/images/icons/dist/public.svg", - "subtitle" : "Bonus: +4", - "title" : "Origins of ingredients with a medium impact" + "subtitle" : "Malus: 0", + "title" : "Origins of ingredients with a high impact" }, "topics" : [ "environment" @@ -1268,17 +1269,17 @@ { "element_type" : "text", "text_element" : { - "html" : "\n Life cycle analysis score: 98
\n Sum of bonuses and maluses:\n \n +17\n

\n Final score: 115/100\n \n ", + "html" : "\n Life cycle analysis score: 98
\n Sum of bonuses and maluses:\n \n +13\n

\n Final score: 100/100\n \n ", "type" : "summary" } } ], "level" : "info", "title_element" : { - "grade" : "a", - "icon_url" : "https://static.openfoodfacts.org/images/attributes/dist/ecoscore-a.svg", + "grade" : "a_plus", + "icon_url" : "https://static.openfoodfacts.org/images/attributes/dist/ecoscore-a-plus.svg", "subtitle" : "Product: A good product for you - Open Food Facts - 200 g", - "title" : "Impact for this product: A (Score: 115/100)", + "title" : "Impact for this product: A+ (Score: 100/100)", "type" : "grade" }, "topics" : [ @@ -1692,13 +1693,17 @@ } } ], - "evaluation" : "", + "evaluation" : "good", + "half_width_on_mobile" : true, "level" : "info", "size" : "small", "title_element" : { "icon_size" : "small", "icon_url" : "https://static.openfoodfacts.org/images/misc/low.svg", - "title" : "Fat in low quantity (0.5%)" + "name" : "Fat", + "title" : "Fat in low quantity (0.5%)", + "type" : "percentage", + "value" : 0.5 }, "topics" : [ "health" @@ -1734,13 +1739,17 @@ } } ], - "evaluation" : "", + "evaluation" : "average", + "half_width_on_mobile" : true, "level" : "info", "size" : "small", "title_element" : { "icon_size" : "small", "icon_url" : "https://static.openfoodfacts.org/images/misc/moderate.svg", - "title" : "Salt in moderate quantity (0.4%)" + "name" : "Salt", + "title" : "Salt in moderate quantity (0.4%)", + "type" : "percentage", + "value" : 0.4 }, "topics" : [ "health" @@ -1766,13 +1775,17 @@ } } ], - "evaluation" : "", + "evaluation" : "good", + "half_width_on_mobile" : true, "level" : "info", "size" : "small", "title_element" : { "icon_size" : "small", "icon_url" : "https://static.openfoodfacts.org/images/misc/low.svg", - "title" : "Saturated fat in low quantity (0.2%)" + "name" : "Saturated fat", + "title" : "Saturated fat in low quantity (0.2%)", + "type" : "percentage", + "value" : 0.2 }, "topics" : [ "health" @@ -1798,13 +1811,17 @@ } } ], - "evaluation" : "", + "evaluation" : "good", + "half_width_on_mobile" : true, "level" : "info", "size" : "small", "title_element" : { "icon_size" : "small", "icon_url" : "https://static.openfoodfacts.org/images/misc/low.svg", - "title" : "Sugars in low quantity (0.5%)" + "name" : "Sugars", + "title" : "Sugars in low quantity (0.5%)", + "type" : "percentage", + "value" : 0.5 }, "topics" : [ "health" @@ -1840,6 +1857,13 @@ }, "nutriscore_2023" : { "elements" : [ + { + "element_type" : "text", + "text_element" : { + "html" : "Warning: the amount of fruits, vegetables and nuts is not specified on the label, it was estimated from the list of ingredients: 65\n ", + "type" : "warning" + } + }, { "element_type" : "panel", "panel_element" : { @@ -2101,6 +2125,13 @@ "text" : "Nutrition facts", "type" : "text" }, + { + "column_group_id" : "product", + "shown_by_default" : true, + "text" : "As sold
for 100 g / 100 ml", + "text_for_small_screens" : "100g", + "type" : "text" + }, { "column_group_id" : "comparisons", "shown_by_default" : true, @@ -2117,6 +2148,9 @@ "style" : "max-width:15rem", "text" : "Energy" }, + { + "text" : "120 kj
(29 kcal)" + }, { "evaluation" : "good", "text" : "-54%" @@ -2130,6 +2164,9 @@ "style" : "max-width:15rem", "text" : "Fat" }, + { + "text" : "0.5 g" + }, { "evaluation" : "good", "text" : "-68%" @@ -2143,9 +2180,12 @@ "style" : "max-width:15rem", "text" : "Saturated fat" }, + { + "text" : "0.2 g" + }, { "evaluation" : "good", - "text" : "-42%" + "text" : "-41%" } ] }, @@ -2156,9 +2196,12 @@ "style" : "max-width:15rem", "text" : "Salt" }, + { + "text" : "0.4 g" + }, { "evaluation" : "good", - "text" : "-40%" + "text" : "-39%" } ] }, @@ -2170,7 +2213,10 @@ "text" : "Carbohydrates" }, { - "text" : "-63%" + "text" : "4 g" + }, + { + "text" : "-62%" } ] }, @@ -2181,9 +2227,12 @@ "style" : "max-width:15rem", "text" : "Fiber" }, + { + "text" : "3 g" + }, { "evaluation" : "good", - "text" : "+96%" + "text" : "+95%" } ] }, @@ -2194,9 +2243,12 @@ "style" : "max-width:15rem", "text" : "Sugars" }, + { + "text" : "0.5 g" + }, { "evaluation" : "good", - "text" : "-83%" + "text" : "-82%" } ] }, @@ -2207,6 +2259,9 @@ "style" : "max-width:15rem", "text" : "Proteins" }, + { + "text" : "1 g" + }, { "evaluation" : "bad", "text" : "-56%" @@ -2220,6 +2275,9 @@ "style" : "max-width:15rem", "text" : "Fruits‚ vegetables‚ nuts and rapeseed‚ walnut and olive oils (estimate from ingredients list analysis)" }, + { + "text" : "65 %" + }, { "text" : "" } @@ -2286,13 +2344,13 @@ } } ], - "evaluation" : "average", + "evaluation" : "bad", "expanded" : false, "level" : "info", "title_element" : { "icon_color_from_evaluation" : true, "icon_url" : "https://static.openfoodfacts.org/images/icons/dist/public.svg", - "subtitle" : "Origins of ingredients with a medium impact", + "subtitle" : "Origins of ingredients with a high impact", "title" : "Origins of ingredients" }, "topics" : [ @@ -2481,14 +2539,14 @@ } }, "labels_tags" : [ + "en:fair-trade", "en:organic", - "en:eu-organic", - "en:fair-trade" + "en:eu-organic" ], "labels_tags_fr" : [ + "Commerce équitable", "Bio", - "Bio européen", - "Commerce équitable" + "Bio européen" ], "lang" : "en", "nutrient_levels" : {