From c70683939db4324f3299f0c91e103e3eb7368584 Mon Sep 17 00:00:00 2001 From: VaiTon Date: Sun, 4 Sep 2022 19:33:29 +0200 Subject: [PATCH 01/16] feat: Add a gallery of the images selected and uploaded for a product (#2801) * feat: image list gallery * feat: display every image in gallery view * feat: shimmering effect in `smooth_list_view.dart` * docs: add documentation to `product_image_gallery_view.dart` * refactor: extract SmoothBackButton Co-authored-by: monsieurtanuki --- .../cards/data_cards/image_upload_card.dart | 15 +- .../product_cards/product_image_carousel.dart | 2 +- .../smooth_product_card_found.dart | 2 +- .../smooth_product_card_template.dart | 6 +- .../lib/generic_lib/loading_sliver.dart | 21 + .../widgets/images/smooth_image.dart | 65 +++ .../images/smooth_images_sliver_grid.dart | 103 ++++ .../images/smooth_images_sliver_list.dart | 44 ++ .../widgets/images/smooth_images_view.dart | 15 + .../widgets/picture_not_found.dart | 15 + .../widgets/smooth_back_button.dart | 19 + .../widgets/smooth_list_tile_card.dart | 107 +++++ .../widgets/smooth_product_image.dart | 62 +-- .../smooth_product_image_container.dart | 25 - .../lib/helpers/collections_helper.dart | 11 - .../lib/helpers/database_helper.dart | 21 + .../lib/helpers/product_cards_helper.dart | 72 +-- packages/smooth_app/lib/l10n/app_en.arb | 4 +- .../product/common/product_query_page.dart | 20 +- .../product/common/product_refresher.dart | 6 +- .../lib/pages/product/edit_product_page.dart | 70 +-- .../product/product_image_gallery_view.dart | 448 +++++++----------- .../pages/product/product_image_viewer.dart | 142 ++++++ packages/smooth_app/pubspec.lock | 7 + packages/smooth_app/pubspec.yaml | 1 + 25 files changed, 818 insertions(+), 485 deletions(-) create mode 100644 packages/smooth_app/lib/generic_lib/loading_sliver.dart create mode 100644 packages/smooth_app/lib/generic_lib/widgets/images/smooth_image.dart create mode 100644 packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_sliver_grid.dart create mode 100644 packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_sliver_list.dart create mode 100644 packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_view.dart create mode 100644 packages/smooth_app/lib/generic_lib/widgets/picture_not_found.dart create mode 100644 packages/smooth_app/lib/generic_lib/widgets/smooth_back_button.dart create mode 100644 packages/smooth_app/lib/generic_lib/widgets/smooth_list_tile_card.dart delete mode 100644 packages/smooth_app/lib/generic_lib/widgets/smooth_product_image_container.dart create mode 100644 packages/smooth_app/lib/helpers/database_helper.dart create mode 100644 packages/smooth_app/lib/pages/product/product_image_viewer.dart diff --git a/packages/smooth_app/lib/cards/data_cards/image_upload_card.dart b/packages/smooth_app/lib/cards/data_cards/image_upload_card.dart index 0bc11c59b46..6ae3246a6a0 100644 --- a/packages/smooth_app/lib/cards/data_cards/image_upload_card.dart +++ b/packages/smooth_app/lib/cards/data_cards/image_upload_card.dart @@ -25,9 +25,11 @@ class ImageUploadCard extends StatefulWidget { } class _ImageUploadCardState extends State { - ImageProvider? _imageProvider; // Normal size image to display in carousel - ImageProvider? - _imageFullProvider; // Full resolution image to display in image page + /// Normal size image to display in carousel + ImageProvider? _imageProvider; + + /// Full resolution image to display in image page + ImageProvider? _imageFullProvider; Future _getImage() async { final File? croppedImageFile = @@ -47,8 +49,7 @@ class _ImageUploadCardState extends State { } await uploadCapturedPicture( context, - barcode: widget.product - .barcode!, //Probably throws an error, but this is not a big problem when we got a product without a barcode + barcode: widget.product.barcode!, imageField: widget.productImageData.imageField, imageUri: croppedImageFile.uri, ); @@ -113,9 +114,7 @@ class _ImageUploadCardState extends State { context, MaterialPageRoute( builder: (BuildContext context) => ProductImageGalleryView( - productImageData: widget.productImageData, - allProductImagesData: widget.allProductImagesData, - title: widget.productImageData.title, + imagesData: widget.allProductImagesData, barcode: widget.product.barcode, ), ), diff --git a/packages/smooth_app/lib/cards/product_cards/product_image_carousel.dart b/packages/smooth_app/lib/cards/product_cards/product_image_carousel.dart index 924f9c347da..4e1ddd750d6 100644 --- a/packages/smooth_app/lib/cards/product_cards/product_image_carousel.dart +++ b/packages/smooth_app/lib/cards/product_cards/product_image_carousel.dart @@ -20,7 +20,7 @@ class ProductImageCarousel extends StatelessWidget { Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); final List allProductImagesData = - getAllProductImagesData(product, appLocalizations); + getProductMainImagesData(product, appLocalizations); return SizedBox( height: height, 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 1019e77675c..cf26810b395 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 @@ -86,7 +86,7 @@ class SmoothProductCardFound extends StatelessWidget { padding: const EdgeInsets.all(VERY_SMALL_SPACE), child: Row( children: [ - SmoothProductImage( + SmoothMainProductImage( product: product, width: screenSize.width * 0.20, height: screenSize.width * 0.20, diff --git a/packages/smooth_app/lib/cards/product_cards/smooth_product_card_template.dart b/packages/smooth_app/lib/cards/product_cards/smooth_product_card_template.dart index 3a7c03d8626..58d584d3873 100644 --- a/packages/smooth_app/lib/cards/product_cards/smooth_product_card_template.dart +++ b/packages/smooth_app/lib/cards/product_cards/smooth_product_card_template.dart @@ -2,8 +2,8 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:smooth_app/cards/product_cards/smooth_product_card_found.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; -import 'package:smooth_app/generic_lib/widgets/smooth_product_image_container.dart'; import 'package:smooth_app/helpers/ui_helpers.dart'; /// Empty template for a product card display. @@ -51,10 +51,10 @@ class SmoothProductCardTemplate extends StatelessWidget { padding: const EdgeInsets.all(VERY_SMALL_SPACE), child: Row( children: [ - SmoothProductImageContainer( + SmoothImage( width: screenSize.width * 0.20, height: screenSize.width * 0.20, - child: Container(color: itemColor), + color: itemColor, ), const Padding(padding: EdgeInsets.only(left: VERY_SMALL_SPACE)), Expanded( diff --git a/packages/smooth_app/lib/generic_lib/loading_sliver.dart b/packages/smooth_app/lib/generic_lib/loading_sliver.dart new file mode 100644 index 00000000000..a7a274b5d98 --- /dev/null +++ b/packages/smooth_app/lib/generic_lib/loading_sliver.dart @@ -0,0 +1,21 @@ +import 'package:flutter/widgets.dart'; + +/// A [SliverChildBuilderDelegate] that can show progress by displaying +/// [loadingWidget]s. +/// +/// When [loading] is `true`, [loadingCount] of [loadingWidget] will be +/// displayed. +class LoadingSliverChildBuilderDelegate extends SliverChildBuilderDelegate { + LoadingSliverChildBuilderDelegate({ + required IndexedWidgetBuilder childBuilder, + required int childCount, + Widget? loadingWidget, + int loadingCount = 4, + bool loading = false, + }) : assert(loading == false || loadingWidget != null), + super( + (BuildContext context, int index) => + loading ? loadingWidget : childBuilder(context, index), + childCount: loading ? loadingCount : childCount, + ); +} diff --git a/packages/smooth_app/lib/generic_lib/widgets/images/smooth_image.dart b/packages/smooth_app/lib/generic_lib/widgets/images/smooth_image.dart new file mode 100644 index 00000000000..b0e7730e81a --- /dev/null +++ b/packages/smooth_app/lib/generic_lib/widgets/images/smooth_image.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/widgets/picture_not_found.dart'; + +/// Container to display a product image on a product card. +/// +/// If [imageProvider] is null, [PictureNotFound] is displayed. +class SmoothImage extends StatelessWidget { + const SmoothImage({ + this.imageProvider, + this.height, + this.width, + this.color, + this.decoration, + this.fit, + }); + + final ImageProvider? imageProvider; + final double? height; + final double? width; + final Color? color; + final Decoration? decoration; + final BoxFit? fit; + + @override + Widget build(BuildContext context) => ClipRRect( + borderRadius: ROUNDED_BORDER_RADIUS, + child: Container( + decoration: decoration, + width: width, + height: height, + color: color, + child: imageProvider == null + ? const PictureNotFound() + : Image( + image: imageProvider!, + fit: fit ?? BoxFit.cover, + loadingBuilder: _loadingBuilder, + ), + ), + ); + + Widget _loadingBuilder( + BuildContext _, + Widget child, + ImageChunkEvent? progress, + ) { + if (progress == null) { + return child; + } + + final double progressValue = + progress.cumulativeBytesLoaded / progress.expectedTotalBytes!; + + return Center( + child: CircularProgressIndicator( + strokeWidth: 2.5, + valueColor: const AlwaysStoppedAnimation( + Colors.white, + ), + value: progressValue, + ), + ); + } +} diff --git a/packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_sliver_grid.dart b/packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_sliver_grid.dart new file mode 100644 index 00000000000..0af5c620188 --- /dev/null +++ b/packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_sliver_grid.dart @@ -0,0 +1,103 @@ +import 'package:flutter/material.dart'; +import 'package:shimmer/shimmer.dart'; +import 'package:smooth_app/data_models/product_image_data.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/loading_sliver.dart'; +import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart'; +import 'package:smooth_app/generic_lib/widgets/images/smooth_images_view.dart'; +import 'package:smooth_app/generic_lib/widgets/picture_not_found.dart'; + +/// Displays a [SliverGrid] with tiles showing the images passed +/// via [imagesData] +class SmoothImagesSliverGrid extends SmoothImagesView { + const SmoothImagesSliverGrid({ + required super.imagesData, + super.onTap, + super.loading = false, + this.loadingCount = 6, + this.maxTileWidth = VERY_LARGE_SPACE * 7, + this.childAspectRatio = 1.5, + }); + + /// The number of shimmering tiles to display while [loading] is true + final int loadingCount; + + /// The maximum width of a tile + final double maxTileWidth; + + final double childAspectRatio; + + @override + Widget build(BuildContext context) { + final List> imageList = + imagesData.entries.toList(); + + return SliverPadding( + padding: const EdgeInsets.all(MEDIUM_SPACE), + sliver: SliverGrid( + delegate: LoadingSliverChildBuilderDelegate( + loading: loading, + childCount: imageList.length, + loadingWidget: _buildShimmer(), + loadingCount: loadingCount, + childBuilder: (BuildContext context, int index) { + final MapEntry?> entry = + imageList[index]; + final ImageProvider? imageProvider = entry.value; + + return imageProvider == null + ? const PictureNotFound() + : Hero( + tag: entry.key.imageUrl!, + child: _ImageTile( + image: imageProvider, + onTap: onTap == null + ? null + : () => onTap!(entry.key, entry.value), + ), + ); + }), + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: maxTileWidth, + childAspectRatio: childAspectRatio, + mainAxisSpacing: MEDIUM_SPACE, + crossAxisSpacing: MEDIUM_SPACE, + ), + ), + ); + } + + Widget _buildShimmer() => Shimmer.fromColors( + baseColor: WHITE_COLOR, + highlightColor: GREY_COLOR, + child: const SmoothImage( + width: VERY_LARGE_SPACE * 5, + height: MEDIUM_SPACE * 5, + color: WHITE_COLOR, + ), + ); +} + +class _ImageTile extends StatelessWidget { + const _ImageTile({ + required this.image, + this.onTap, + }); + + final ImageProvider image; + final void Function()? onTap; + + @override + Widget build(BuildContext context) => Ink( + decoration: BoxDecoration( + borderRadius: ROUNDED_BORDER_RADIUS, + image: DecorationImage( + image: image, + fit: BoxFit.cover, + )), + child: InkWell( + borderRadius: ROUNDED_BORDER_RADIUS, + onTap: onTap, + ), + ); +} diff --git a/packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_sliver_list.dart b/packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_sliver_list.dart new file mode 100644 index 00000000000..3a421d18dc3 --- /dev/null +++ b/packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_sliver_list.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:smooth_app/data_models/product_image_data.dart'; +import 'package:smooth_app/generic_lib/loading_sliver.dart'; +import 'package:smooth_app/generic_lib/widgets/images/smooth_images_view.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_list_tile_card.dart'; + +/// Displays a [SliverList] by using [SmoothListTileCard] for showing images +/// passed via [imagesData]. +/// +/// If [loading] is set to `true`, the list shows instead +/// loading [SmoothListTileCard]s. +class SmoothImagesSliverList extends SmoothImagesView { + const SmoothImagesSliverList({ + required super.imagesData, + super.onTap, + super.loading = false, + }); + + @override + Widget build(BuildContext context) { + final ThemeData themeData = Theme.of(context); + final List> imageList = + imagesData.entries.toList(); + final int count = imageList.length; + + return SliverList( + delegate: LoadingSliverChildBuilderDelegate( + loading: loading, + childCount: count, + loadingWidget: SmoothListTileCard.loading(), + childBuilder: (_, int index) => SmoothListTileCard.image( + imageProvider: imageList[index].value, + title: Text( + imageList[index].key.title, + style: themeData.textTheme.headline4, + ), + onTap: onTap == null + ? null + : () => onTap!(imageList[index].key, imageList[index].value), + ), + ), + ); + } +} diff --git a/packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_view.dart b/packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_view.dart new file mode 100644 index 00000000000..9b5f88cf5b6 --- /dev/null +++ b/packages/smooth_app/lib/generic_lib/widgets/images/smooth_images_view.dart @@ -0,0 +1,15 @@ +import 'package:flutter/widgets.dart'; +import 'package:smooth_app/data_models/product_image_data.dart'; + +/// Base class for classes that display a collection of images. +abstract class SmoothImagesView extends StatelessWidget { + const SmoothImagesView({ + required this.imagesData, + this.onTap, + this.loading = false, + }); + + final Map imagesData; + final void Function(ProductImageData, ImageProvider?)? onTap; + final bool loading; +} diff --git a/packages/smooth_app/lib/generic_lib/widgets/picture_not_found.dart b/packages/smooth_app/lib/generic_lib/widgets/picture_not_found.dart new file mode 100644 index 00000000000..a336c3acf1e --- /dev/null +++ b/packages/smooth_app/lib/generic_lib/widgets/picture_not_found.dart @@ -0,0 +1,15 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_svg/svg.dart'; + +/// Displays a default asset as a _picture not found_ image. +class PictureNotFound extends StatelessWidget { + const PictureNotFound(); + + static const String NOT_FOUND_ASSET = 'assets/product/product_not_found.svg'; + + @override + Widget build(BuildContext context) => SvgPicture.asset( + NOT_FOUND_ASSET, + fit: BoxFit.cover, + ); +} diff --git a/packages/smooth_app/lib/generic_lib/widgets/smooth_back_button.dart b/packages/smooth_app/lib/generic_lib/widgets/smooth_back_button.dart new file mode 100644 index 00000000000..ab59a642485 --- /dev/null +++ b/packages/smooth_app/lib/generic_lib/widgets/smooth_back_button.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:smooth_app/themes/constant_icons.dart'; + +/// Displays an [IconButton] containing the platform-specific default +/// back button icon. +class SmoothBackButton extends StatelessWidget { + const SmoothBackButton({ + this.onPressed, + }); + + final void Function()? onPressed; + + @override + Widget build(BuildContext context) => IconButton( + icon: Icon(ConstantIcons.instance.getBackIcon()), + tooltip: MaterialLocalizations.of(context).backButtonTooltip, + onPressed: onPressed ?? () => Navigator.maybePop(context), + ); +} diff --git a/packages/smooth_app/lib/generic_lib/widgets/smooth_list_tile_card.dart b/packages/smooth_app/lib/generic_lib/widgets/smooth_list_tile_card.dart new file mode 100644 index 00000000000..e5cd89e908d --- /dev/null +++ b/packages/smooth_app/lib/generic_lib/widgets/smooth_list_tile_card.dart @@ -0,0 +1,107 @@ +import 'package:flutter/material.dart'; +import 'package:shimmer/shimmer.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; +import 'package:smooth_app/themes/constant_icons.dart'; + +/// Displays a [ListTile] in a [SmoothCard] wrapped with an [InkWell]. +class SmoothListTileCard extends StatelessWidget { + const SmoothListTileCard({ + required this.title, + this.subtitle, + this.onTap, + this.leading, + Key? key, + }) : super(key: key); + + /// Displays a [ListTile] inside a [SmoothCard] with a leading [Column] + /// containing the specified [imageProvider] + SmoothListTileCard.image({ + required ImageProvider? imageProvider, + Widget? title, + GestureTapCallback? onTap, + }) : this( + title: title, + onTap: onTap, + leading: SmoothImage( + width: VERY_LARGE_SPACE * 5, + height: MEDIUM_SPACE * 5, + imageProvider: imageProvider, + ), + ); + + /// Displays a [ListTile] inside a [SmoothCard] with a leading [Column] + /// containing the specified [icon] + SmoothListTileCard.icon({ + Widget? icon, + Widget? title, + Widget? subtitle, + GestureTapCallback? onTap, + Key? key, + }) : this( + title: title, + subtitle: subtitle, + key: key, + onTap: onTap, + // we use a Column to have the icon centered vertically + leading: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [icon ?? const Icon(Icons.edit)], + ), + ); + + /// Displays a loading card with a shimmering effect + SmoothListTileCard.loading() + : this( + title: Shimmer.fromColors( + baseColor: GREY_COLOR, + highlightColor: WHITE_COLOR, + child: Row( + children: [ + Expanded( + child: Container( + decoration: const BoxDecoration( + color: GREY_COLOR, + borderRadius: CIRCULAR_BORDER_RADIUS, + ), + ), + ), + ], + ), + ), + leading: Shimmer.fromColors( + baseColor: GREY_COLOR, + highlightColor: WHITE_COLOR, + child: const SmoothImage( + width: VERY_LARGE_SPACE * 5, + height: MEDIUM_SPACE * 5, + color: GREY_COLOR, + ), + ), + ); + + final Widget? title; + final Widget? subtitle; + final Widget? leading; + final GestureTapCallback? onTap; + + @override + Widget build(BuildContext context) => SmoothCard( + padding: EdgeInsets.zero, + child: InkWell( + borderRadius: ROUNDED_BORDER_RADIUS, + onTap: onTap, + child: Padding( + padding: const EdgeInsets.all(VERY_SMALL_SPACE), + child: ListTile( + onTap: onTap, + title: title, + subtitle: subtitle, + leading: leading, + trailing: Icon(ConstantIcons.instance.getForwardIcon()), + ), + ), + ), + ); +} diff --git a/packages/smooth_app/lib/generic_lib/widgets/smooth_product_image.dart b/packages/smooth_app/lib/generic_lib/widgets/smooth_product_image.dart index 6371c0734f7..b6a7fe3e88e 100644 --- a/packages/smooth_app/lib/generic_lib/widgets/smooth_product_image.dart +++ b/packages/smooth_app/lib/generic_lib/widgets/smooth_product_image.dart @@ -1,11 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; import 'package:openfoodfacts/model/Product.dart'; -import 'package:smooth_app/generic_lib/widgets/smooth_product_image_container.dart'; +import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart'; /// Main product image on a product card. -class SmoothProductImage extends StatelessWidget { - const SmoothProductImage({ +class SmoothMainProductImage extends StatelessWidget { + const SmoothMainProductImage({ required this.product, required this.height, required this.width, @@ -17,57 +16,16 @@ class SmoothProductImage extends StatelessWidget { @override Widget build(BuildContext context) { - Widget? result; - result = _buildFromUrl(product.imageFrontSmallUrl); - if (result != null) { - return result; - } - result = _buildFromUrl(product.imageFrontUrl); - if (result != null) { - return result; - } - return SmoothProductImageContainer( + final NetworkImage? child = _buildFromUrl(product.imageFrontSmallUrl) ?? + _buildFromUrl(product.imageFrontUrl); + + return SmoothImage( width: width, height: height, - child: Center( - child: SvgPicture.asset( - 'assets/product/product_not_found.svg', - fit: BoxFit.cover, - ), - ), + imageProvider: child, ); } - Widget? _buildFromUrl(final String? url) => url == null || url.isEmpty - ? null - : SmoothProductImageContainer( - width: width, - height: height, - child: Image.network( - url, - fit: BoxFit.contain, - loadingBuilder: (BuildContext context, Widget child, - ImageChunkEvent? progress) => - progress == null - ? child - : Center( - child: CircularProgressIndicator.adaptive( - strokeWidth: 2.5, - valueColor: const AlwaysStoppedAnimation( - Colors.white, - ), - value: progress.cumulativeBytesLoaded / - progress.expectedTotalBytes!, - ), - ), - errorBuilder: - (BuildContext context, Object error, StackTrace? stackTrace) => - Center( - child: SvgPicture.asset( - 'assets/product/product_not_found.svg', - fit: BoxFit.cover, - ), - ), - ), - ); + NetworkImage? _buildFromUrl(final String? url) => + url == null || url.isEmpty ? null : NetworkImage(url); } diff --git a/packages/smooth_app/lib/generic_lib/widgets/smooth_product_image_container.dart b/packages/smooth_app/lib/generic_lib/widgets/smooth_product_image_container.dart deleted file mode 100644 index a7c451fed27..00000000000 --- a/packages/smooth_app/lib/generic_lib/widgets/smooth_product_image_container.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:smooth_app/generic_lib/design_constants.dart'; - -/// Container to display the main product image on a product card. -class SmoothProductImageContainer extends StatelessWidget { - const SmoothProductImageContainer({ - required this.height, - required this.width, - required this.child, - }); - - final double height; - final double width; - final Widget child; - - @override - Widget build(BuildContext context) => ClipRRect( - borderRadius: ROUNDED_BORDER_RADIUS, - child: SizedBox( - width: width, - height: height, - child: child, - ), - ); -} diff --git a/packages/smooth_app/lib/helpers/collections_helper.dart b/packages/smooth_app/lib/helpers/collections_helper.dart index 2aaa320eb2d..748abc95e83 100644 --- a/packages/smooth_app/lib/helpers/collections_helper.dart +++ b/packages/smooth_app/lib/helpers/collections_helper.dart @@ -91,17 +91,6 @@ extension SetExtensions on Set { } } -extension IterableExtensions on Iterable { - T? firstWhereOrNull(bool Function(T element) test) { - for (final T element in this) { - if (test(element)) { - return element; - } - } - return null; - } -} - extension MapStringKeyExtensions on Map { String? keyStartingWith(String key, {bool ignoreCase = false}) { final String searchKey; diff --git a/packages/smooth_app/lib/helpers/database_helper.dart b/packages/smooth_app/lib/helpers/database_helper.dart new file mode 100644 index 00000000000..5b35bab4de5 --- /dev/null +++ b/packages/smooth_app/lib/helpers/database_helper.dart @@ -0,0 +1,21 @@ +import 'package:smooth_app/database/dao_int.dart'; + +/// Returns a progressive number each time it is invoked for a given [key]. +/// This is useful to generate a unique id for a given [key]. +/// +/// The [key] is a string that is used to identify the sequence. +/// +/// The progressive number is saved in the database, so that it is persistent. +Future getNextSequenceNumber( + final DaoInt daoInt, + final String key, +) async { + int? result = daoInt.get(key); + if (result == null) { + result = 1; + } else { + result++; + } + await daoInt.put(key, result); + return result; +} diff --git a/packages/smooth_app/lib/helpers/product_cards_helper.dart b/packages/smooth_app/lib/helpers/product_cards_helper.dart index ad244d713d5..52dca216172 100644 --- a/packages/smooth_app/lib/helpers/product_cards_helper.dart +++ b/packages/smooth_app/lib/helpers/product_cards_helper.dart @@ -89,39 +89,39 @@ Widget addPanelButton( ), ); -List getAllProductImagesData( - Product product, AppLocalizations appLocalizations) { - final List allProductImagesData = [ - ProductImageData( - imageField: ImageField.FRONT, - imageUrl: product.imageFrontUrl, - title: appLocalizations.product, - buttonText: appLocalizations.front_photo, - ), - ProductImageData( - imageField: ImageField.INGREDIENTS, - imageUrl: product.imageIngredientsUrl, - title: appLocalizations.ingredients, - buttonText: appLocalizations.ingredients_photo, - ), - ProductImageData( - imageField: ImageField.NUTRITION, - imageUrl: product.imageNutritionUrl, - title: appLocalizations.nutrition, - buttonText: appLocalizations.nutrition_facts_photo, - ), - ProductImageData( - imageField: ImageField.PACKAGING, - imageUrl: product.imagePackagingUrl, - title: appLocalizations.packaging_information, - buttonText: appLocalizations.packaging_information_photo, - ), - ProductImageData( - imageField: ImageField.OTHER, - imageUrl: null, - title: appLocalizations.more_photos, - buttonText: appLocalizations.more_photos, - ), - ]; - return allProductImagesData; -} +List getProductMainImagesData( + Product product, + AppLocalizations appLocalizations, +) => + [ + ProductImageData( + imageField: ImageField.FRONT, + imageUrl: product.imageFrontUrl, + title: appLocalizations.product, + buttonText: appLocalizations.front_photo, + ), + ProductImageData( + imageField: ImageField.INGREDIENTS, + imageUrl: product.imageIngredientsUrl, + title: appLocalizations.ingredients, + buttonText: appLocalizations.ingredients_photo, + ), + ProductImageData( + imageField: ImageField.NUTRITION, + imageUrl: product.imageNutritionUrl, + title: appLocalizations.nutrition, + buttonText: appLocalizations.nutrition_facts_photo, + ), + ProductImageData( + imageField: ImageField.PACKAGING, + imageUrl: product.imagePackagingUrl, + title: appLocalizations.packaging_information, + buttonText: appLocalizations.packaging_information_photo, + ), + ProductImageData( + imageField: ImageField.OTHER, + imageUrl: null, + title: appLocalizations.more_photos, + buttonText: appLocalizations.more_photos, + ), + ]; diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 4cb954b7585..fee90d546b8 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images" : "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/pages/product/common/product_query_page.dart b/packages/smooth_app/lib/pages/product/common/product_query_page.dart index e599bbd21ef..07cd70da911 100644 --- a/packages/smooth_app/lib/pages/product/common/product_query_page.dart +++ b/packages/smooth_app/lib/pages/product/common/product_query_page.dart @@ -16,6 +16,7 @@ import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dar import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/duration_constants.dart'; import 'package:smooth_app/generic_lib/loading_dialog.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_error_card.dart'; import 'package:smooth_app/helpers/analytics_helper.dart'; @@ -23,7 +24,6 @@ import 'package:smooth_app/pages/personalized_ranking_page.dart'; import 'package:smooth_app/pages/product/common/product_list_item_simple.dart'; import 'package:smooth_app/pages/product/common/product_query_page_helper.dart'; import 'package:smooth_app/query/paged_product_query.dart'; -import 'package:smooth_app/themes/constant_icons.dart'; import 'package:smooth_app/widgets/ranking_floating_action_button.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; @@ -140,7 +140,7 @@ class _ProductQueryPageState extends State SmoothScaffold( appBar: AppBar( backgroundColor: themeData.scaffoldBackgroundColor, - leading: const _BackButton(), + leading: const SmoothBackButton(), title: _getAppBarTitle(), actions: actions, ), @@ -205,7 +205,7 @@ class _ProductQueryPageState extends State backgroundColor: themeData.scaffoldBackgroundColor, elevation: 0, automaticallyImplyLeading: false, - leading: const _BackButton(), + leading: const SmoothBackButton(), title: _getAppBarTitle(), actions: _getAppBarButtons(), ), @@ -470,20 +470,6 @@ class _ProductQueryPageState extends State } } -// TODO(monsieurtanki): put it in a specific Widget class -class _BackButton extends StatelessWidget { - const _BackButton(); - - @override - Widget build(BuildContext context) => IconButton( - icon: Icon(ConstantIcons.instance.getBackIcon()), - tooltip: MaterialLocalizations.of(context).backButtonTooltip, - onPressed: () { - Navigator.maybePop(context); - }, - ); -} - // TODO(monsieurtanki): put it in a specific reusable class class _Action { _Action({ 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 2c09c9cfeab..ece4c6a72d7 100644 --- a/packages/smooth_app/lib/pages/product/common/product_refresher.dart +++ b/packages/smooth_app/lib/pages/product/common/product_refresher.dart @@ -81,8 +81,8 @@ class ProductRefresher { await showDialog( context: context, builder: (BuildContext context) => SmoothAlertDialog( - body: Text(appLocalizations - .nutrition_page_update_done), // TODO(monsieurtanuki): title as method parameter + body: Text(appLocalizations.nutrition_page_update_done), + // TODO(monsieurtanuki): title as method parameter positiveAction: SmoothActionButton( text: appLocalizations.okay, onPressed: () => Navigator.of(context).pop(), @@ -129,6 +129,7 @@ class ProductRefresher { return const _MetaProductRefresher.error(null); } + /// Returns `true` if the fetch is successful. Future fetchAndRefresh({ required final BuildContext context, required final LocalDatabase localDatabase, @@ -178,6 +179,7 @@ class ProductRefresher { class _MetaProductRefresher { const _MetaProductRefresher.error(this.error) : product = null; + const _MetaProductRefresher.product(this.product) : error = null; final String? error; 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 ebe402b56de..45124bf3954 100644 --- a/packages/smooth_app/lib/pages/product/edit_product_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_product_page.dart @@ -11,7 +11,7 @@ import 'package:smooth_app/data_models/up_to_date_product_provider.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/duration_constants.dart'; -import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_list_tile_card.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; import 'package:smooth_app/pages/product/add_basic_details_page.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; @@ -23,7 +23,6 @@ import 'package:smooth_app/pages/product/ordered_nutrients_cache.dart'; import 'package:smooth_app/pages/product/product_image_gallery_view.dart'; import 'package:smooth_app/pages/product/simple_input_page.dart'; import 'package:smooth_app/pages/product/simple_input_page_helpers.dart'; -import 'package:smooth_app/themes/constant_icons.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; /// Page where we can indirectly edit all data about a product. @@ -162,16 +161,14 @@ class _EditProductPageState extends State { return; } final List allProductImagesData = - getAllProductImagesData(_product, appLocalizations); + getProductMainImagesData(_product, appLocalizations); // TODO(monsieurtanuki): careful, waiting for pop'ed value final bool? refreshed = await Navigator.push( context, MaterialPageRoute( builder: (BuildContext context) => ProductImageGalleryView( - productImageData: allProductImagesData.first, - allProductImagesData: allProductImagesData, - title: allProductImagesData.first.title, + imagesData: allProductImagesData, barcode: _product.barcode, ), fullscreenDialog: true, @@ -295,6 +292,7 @@ class _EditProductPageState extends State { Widget _getSimpleListTileItem(final AbstractSimpleInputPageHelper helper) { final AppLocalizations appLocalizations = AppLocalizations.of(context); + return _ListTitleItem( leading: helper.getIcon(), title: helper.getTitle(appLocalizations), @@ -319,12 +317,12 @@ class _EditProductPageState extends State { Future _refreshProduct(BuildContext context) async { final LocalDatabase localDatabase = context.read(); - final bool result = await ProductRefresher().fetchAndRefresh( + final bool success = await ProductRefresher().fetchAndRefresh( context: context, localDatabase: localDatabase, barcode: _product.barcode!, ); - if (mounted && result) { + if (mounted && success) { final AppLocalizations appLocalizations = AppLocalizations.of(context); ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -333,7 +331,7 @@ class _EditProductPageState extends State { ), ); } - return result; + return success; } Widget _getMultipleListTileItem( @@ -347,7 +345,6 @@ class _EditProductPageState extends State { return _ListTitleItem( leading: const Icon(Icons.interests), title: titles.join(', '), - subtitle: null, onTap: () async { if (!await ProductRefresher().checkIfLoggedIn(context)) { return; @@ -384,44 +381,25 @@ class _EditProductPageState extends State { } } -class _ListTitleItem extends StatelessWidget { - const _ListTitleItem({ - required this.title, - this.subtitle, - this.onTap, - this.leading, +class _ListTitleItem extends SmoothListTileCard { + _ListTitleItem({ + Widget? leading, + String? title, + String? subtitle, + void Function()? onTap, Key? key, - }) : super(key: key); - - final String title; - final String? subtitle; - final VoidCallback? onTap; - final Widget? leading; - - @override - Widget build(BuildContext context) => SmoothCard( - padding: EdgeInsets.zero, - child: InkWell( - borderRadius: ROUNDED_BORDER_RADIUS, + }) : super.icon( + title: title == null + ? null + : Text( + title, + style: const TextStyle(fontWeight: FontWeight.bold), + ), onTap: onTap, - child: Padding( - padding: const EdgeInsets.all(5.0), - child: ListTile( - title: Text( - title, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - subtitle: subtitle == null ? null : Text(subtitle!), - // we use a Column to have the icon centered vertically - leading: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [leading ?? const Icon(Icons.edit)], - ), - trailing: Icon(ConstantIcons.instance.getForwardIcon()), - ), - ), - ), - ); + key: key, + icon: leading, + subtitle: subtitle == null ? null : Text(subtitle), + ); } /// SVG that looks like a ListTile icon. diff --git a/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart b/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart index ba62cdbac0e..310f9072555 100644 --- a/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart +++ b/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart @@ -1,36 +1,33 @@ -// ignore_for_file: cast_nullable_to_non_nullable - import 'dart:io'; +import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:http/http.dart' as http; -import 'package:path_provider/path_provider.dart'; -import 'package:photo_view/photo_view.dart'; -import 'package:photo_view/photo_view_gallery.dart'; +import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/data_models/product_image_data.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; -import 'package:smooth_app/generic_lib/duration_constants.dart'; -import 'package:smooth_app/generic_lib/loading_dialog.dart'; -import 'package:smooth_app/generic_lib/widgets/smooth_gauge.dart'; +import 'package:smooth_app/generic_lib/widgets/images/smooth_images_sliver_grid.dart'; +import 'package:smooth_app/generic_lib/widgets/images/smooth_images_sliver_list.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; import 'package:smooth_app/helpers/picture_capture_helper.dart'; import 'package:smooth_app/pages/image_crop_page.dart'; -import 'package:smooth_app/pages/product/confirm_and_upload_picture.dart'; -import 'package:smooth_app/themes/constant_icons.dart'; +import 'package:smooth_app/pages/product/product_image_viewer.dart'; +import 'package:smooth_app/query/product_query.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; +/// ProductImageGalleryView is a page that displays a list of product images. +/// +/// It allows the user to add a new image and edit an existing image +/// by clicking on it. +/// class ProductImageGalleryView extends StatefulWidget { const ProductImageGalleryView({ + required this.imagesData, this.barcode, - required this.title, - required this.productImageData, - required this.allProductImagesData, }); final String? barcode; - final String title; - final ProductImageData productImageData; - final List allProductImagesData; + final List imagesData; @override State createState() => @@ -38,50 +35,52 @@ class ProductImageGalleryView extends StatefulWidget { } class _ProductImageGalleryViewState extends State { - late final PageController _controller; - late final List images = []; - final List allProductImageProviders = []; - late String title; - bool _hasPhoto = true; - late ProductImageData _productImageDataCurrent; - int _currentIndex = 0; + late final Map selectedImages; + + final Map unselectedImages = + {}; + + bool _isRefreshed = false; + bool _isLoadingMore = true; @override void initState() { - title = widget.title; + selectedImages = Map.fromIterables( + widget.imagesData, + widget.imagesData.map(_provideImage), + ); - for (final ProductImageData element in widget.allProductImagesData) { - images.add(element); - if (element.imageUrl != null) { - allProductImageProviders.add(NetworkImage(element.imageUrl!)); - } else { - allProductImageProviders.add(null); + _getProductImages(widget.barcode!) + .then((Iterable? loadedData) { + if (loadedData == null) { + return; } - } - _controller = PageController( - initialPage: widget.allProductImagesData.indexOf( - images.firstWhere((ProductImageData element) => - element.imageUrl == widget.productImageData.imageUrl), - ), - ); - _currentIndex = _controller.initialPage; - _productImageDataCurrent = widget.productImageData; + final Map?> newMap = + Map.fromIterables( + loadedData, + loadedData.map(_provideImage), + ); + + setState(() { + unselectedImages.addAll(newMap); + _isLoadingMore = false; + }); + }); + super.initState(); } - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } + ImageProvider? _provideImage(ProductImageData imageData) => + imageData.imageUrl == null ? null : NetworkImage(imageData.imageUrl!); @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); + final ThemeData theme = Theme.of(context); - //When all are empty there shouldn't be a way to access this page - if (images.isEmpty) { + // When there is no data there should be no way to get to this page. + if (selectedImages.isEmpty) { return SmoothScaffold( body: Center( child: Text(appLocalizations.error), @@ -89,255 +88,140 @@ class _ProductImageGalleryViewState extends State { ); } return SmoothScaffold( - extendBodyBehindAppBar: true, appBar: AppBar( - backgroundColor: Colors.transparent, - foregroundColor: WHITE_COLOR, - elevation: 0, - title: Text(title), - leading: IconButton( - icon: Icon(ConstantIcons.instance.getBackIcon()), - onPressed: () { - Navigator.maybePop(context); - }, - )), - backgroundColor: Colors.black, - floatingActionButton: _hasPhoto - ? _buildEditFloatingActionButton( - appLocalizations.edit_photo_button_label) - : _buildAddFloatingActionButton( - appLocalizations.add_photo_button_label), - body: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ConstrainedBox( - constraints: BoxConstraints.tight( - Size(double.infinity, MediaQuery.of(context).size.height / 2), - ), - child: PhotoViewGallery.builder( - pageController: _controller, - scrollPhysics: const BouncingScrollPhysics(), - builder: (BuildContext context, int index) { - if (allProductImageProviders[index] == null) { - if (images[index].imageUrl != null) { - allProductImageProviders[index] = - NetworkImage(images[index].imageUrl!); - } else { - return PhotoViewGalleryPageOptions.customChild( - child: InkWell( - onTap: () async { - final int? currentIndex = _controller.page?.toInt(); - if (currentIndex != null) { - final File? croppedImageFile = - await startImageCropping(context, - showOptionDialog: true); - if (croppedImageFile != null) { - setState(() { - allProductImageProviders[currentIndex] = - FileImage(croppedImageFile); - }); - if (!mounted) { - return; - } - await uploadCapturedPicture( - context, - barcode: widget.barcode!, - imageField: _productImageDataCurrent.imageField, - imageUri: croppedImageFile.uri, - ); - if (!mounted) { - return; - } - } - } - }, - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - Icons.add_a_photo, - size: 100, - color: WHITE_COLOR, - ), - Text( - appLocalizations.add_photo_button_label, - style: const TextStyle( - color: WHITE_COLOR, - ), - ), - ], - ), - ), - ), - ); - } - } - return PhotoViewGalleryPageOptions( - imageProvider: allProductImageProviders[index], - initialScale: PhotoViewComputedScale.contained * 0.8, - minScale: PhotoViewComputedScale.contained * 0.8, - maxScale: PhotoViewComputedScale.covered * 1.1, - heroAttributes: PhotoViewHeroAttributes( - tag: images[index].imageUrl ?? ''), - ); - }, - itemCount: images.length, - loadingBuilder: - (final BuildContext context, final ImageChunkEvent? event) { - return Center( - child: SmoothGauge( - color: Theme.of(context).colorScheme.onBackground, - value: event == null || - event.expectedTotalBytes == null || - event.expectedTotalBytes == 0 - ? 0 - : event.cumulativeBytesLoaded / - event.expectedTotalBytes!, - ), - ); - }, - backgroundDecoration: const BoxDecoration( - color: Colors.black, - ), - onPageChanged: (int index) { - setState( - () { - title = images[index].title; - _hasPhoto = images[index].imageUrl != null; - _productImageDataCurrent = images[index]; - _currentIndex = index; - }, - ); - }, + title: Text(appLocalizations.edit_product_form_item_photos_title), + leading: SmoothBackButton( + onPressed: () => Navigator.maybePop(context, _isRefreshed), + ), + ), + body: Scrollbar( + child: CustomScrollView( + slivers: [ + _buildTitle(appLocalizations.selected_images, theme: theme), + SmoothImagesSliverList( + imagesData: selectedImages, + onTap: (ProductImageData data, _) => + data.imageUrl != null ? _openImage(data) : _newImage(data), ), - ), - SizedBox( - height: 15, - child: ListView.builder( - shrinkWrap: true, - scrollDirection: Axis.horizontal, - itemBuilder: (BuildContext context, int index) { - return Container( - margin: const EdgeInsets.all(3), - width: 15, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: - index == _currentIndex ? WHITE_COLOR : FAIR_GREY_COLOR, - ), - ); - }, - itemCount: images.length, + _buildTitle(appLocalizations.all_images, theme: theme), + SmoothImagesSliverGrid( + imagesData: unselectedImages, + loading: _isLoadingMore, + onTap: (ProductImageData data, _) => _openImage(data), ), - ), - ], + ], + ), ), ); } - Future _getCurrentImageFile(String url) async { - final http.Response response = await http.get(Uri.parse(url)); - final Directory tempDirectory = await getTemporaryDirectory(); - final File imageFile = await File('${tempDirectory.path}/editing_image') - .writeAsBytes(response.bodyBytes); - return imageFile; - } - - FloatingActionButton _buildAddFloatingActionButton(String labelText) { - return FloatingActionButton.extended( - backgroundColor: Theme.of(context).colorScheme.primary, - onPressed: () async { - final int? currentIndex = _controller.page?.toInt(); - if (currentIndex != null) { - final File? croppedImageFile = await startImageCropping(context); - if (croppedImageFile != null) { - setState(() { - allProductImageProviders[currentIndex] = - FileImage(croppedImageFile); - }); - if (!mounted) { - return; - } - await uploadCapturedPicture( - context, - barcode: widget.barcode!, - imageField: _productImageDataCurrent.imageField, - imageUri: croppedImageFile.uri, - ); + SliverPadding _buildTitle(String title, {required ThemeData theme}) => + SliverPadding( + padding: const EdgeInsets.all(LARGE_SPACE), + sliver: SliverToBoxAdapter( + child: Text( + title, + style: theme.textTheme.headline2, + ), + ), + ); - if (!mounted) { - return; - } - final AppLocalizations appLocalizations = - AppLocalizations.of(context); - final String message = appLocalizations.image_upload_queued; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(message), - duration: SnackBarDuration.medium, - ), - ); - Navigator.pop( - context, - ); - } - } - }, - icon: const Icon(Icons.add_a_photo), - label: Text(labelText)); - } + Future _openImage(ProductImageData imageData) async => + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => ProductImageViewer( + barcode: widget.barcode!, + imageData: imageData, + ), + )); - FloatingActionButton _buildEditFloatingActionButton(String labelText) { - return FloatingActionButton.extended( - backgroundColor: Theme.of(context).colorScheme.primary, - onPressed: () async { - final int? currentIndex = _controller.page?.toInt(); - if (currentIndex == null && currentIndex! >= images.length) { - return; - } + Future _newImage(ProductImageData data) async { + final File? croppedImageFile = await startImageCropping(context); + if (croppedImageFile == null) { + return; + } + setState(() { + final FileImage fileImage = FileImage(croppedImageFile); + if (selectedImages.containsKey(data)) { + selectedImages[data] = fileImage; + } else if (unselectedImages.containsKey(data)) { + unselectedImages[data] = fileImage; + } else { + throw ArgumentError('Could not find the type of $data'); + } + }); + if (!mounted) { + return; + } + final bool isUploaded = await uploadCapturedPicture( + context, + barcode: widget.barcode!, + imageField: data.imageField, + imageUri: croppedImageFile.uri, + ); - final ProductImageData currentImage = images[currentIndex]; - if (currentImage.imageUrl == null) { - return; - } + if (isUploaded) { + _isRefreshed = true; + if (!mounted) { + return; + } + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final String message = getImageUploadedMessage( + data.imageField, + appLocalizations, + ); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(message), + duration: const Duration(seconds: 3), + ), + ); + } + } - final File? imageFile = await LoadingDialog.run( - context: context, - future: _getCurrentImageFile(currentImage.imageUrl!)); + Future?> _getProductImages(String barcode) async { + final ProductQueryConfiguration configuration = ProductQueryConfiguration( + barcode, + fields: [ProductField.IMAGES], + language: ProductQuery.getLanguage(), + country: ProductQuery.getCountry(), + ); - if (imageFile == null) { - return; - } + final ProductResult result; + try { + result = await OpenFoodAPIClient.getProduct(configuration); + } catch (e) { + return null; + } - if (!mounted) { - return; - } + if (result.status != 1) { + return null; + } - // TODO(monsieurtanuki): careful, waiting for pop'ed value - // ignore: use_build_context_synchronously - final File? photoUploaded = await Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => ConfirmAndUploadPicture( - barcode: widget.barcode!, - imageType: currentImage.imageField, - initialPhoto: imageFile, - ), - ), - ); - if (photoUploaded != null) { - if (!mounted) { - return; - } + final Product? product = result.product; + if (product == null || product.images == null) { + return null; + } - setState(() { - allProductImageProviders[currentIndex] = FileImage(photoUploaded); - }); - } - }, - label: Text(labelText), - icon: const Icon(Icons.edit), - ); + return _deduplicateImages(product.images!).map(_getProductImageData); } + + /// Groups the list of [ProductImage] by [ProductImage.imgid] + /// and returns the first of every group + Iterable _deduplicateImages(Iterable images) => + images + .groupListsBy((ProductImage element) => element.imgid) + .values + .map((List sameIdImages) => sameIdImages.firstOrNull) + .whereNotNull(); + + /// Created a [ProductImageData] from a [ProductImage] + ProductImageData _getProductImageData(ProductImage image) => ProductImageData( + imageField: image.field, + // TODO(VaiTon): i18n + title: image.imgid ?? '', + buttonText: image.imgid ?? '', + imageUrl: ImageHelper.buildUrl(widget.barcode, image), + ); } diff --git a/packages/smooth_app/lib/pages/product/product_image_viewer.dart b/packages/smooth_app/lib/pages/product/product_image_viewer.dart new file mode 100644 index 00000000000..b219fc9cf68 --- /dev/null +++ b/packages/smooth_app/lib/pages/product/product_image_viewer.dart @@ -0,0 +1,142 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:http/http.dart' as http; +import 'package:path_provider/path_provider.dart'; +import 'package:photo_view/photo_view.dart'; +import 'package:provider/provider.dart'; +import 'package:smooth_app/data_models/product_image_data.dart'; +import 'package:smooth_app/database/dao_int.dart'; +import 'package:smooth_app/database/local_database.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/loading_dialog.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; +import 'package:smooth_app/helpers/database_helper.dart'; +import 'package:smooth_app/pages/product/confirm_and_upload_picture.dart'; +import 'package:smooth_app/widgets/smooth_scaffold.dart'; + +/// Displays a full-screen image with an edit floating button +class ProductImageViewer extends StatefulWidget { + const ProductImageViewer({ + required this.barcode, + required this.imageData, + }); + + final String barcode; + final ProductImageData imageData; + + @override + State createState() => _ProductImageViewerState(); +} + +class _ProductImageViewerState extends State { + late final ProductImageData imageData; + + /// When the image is edited, this is the new image + late ImageProvider imageProvider; + bool _isEdited = false; + + @override + void initState() { + imageData = widget.imageData; + imageProvider = NetworkImage(imageData.imageUrl!); + + super.initState(); + } + + @override + Widget build(BuildContext context) => SmoothScaffold( + extendBodyBehindAppBar: true, + backgroundColor: Colors.black, + floatingActionButton: FloatingActionButton.extended( + label: Text(AppLocalizations.of(context).edit_photo_button_label), + icon: const Icon(Icons.edit), + backgroundColor: Theme.of(context).colorScheme.primary, + onPressed: () { + final DaoInt daoInt = DaoInt(context.read()); + _editImage(daoInt); + }, + ), + appBar: AppBar( + backgroundColor: Colors.black, + foregroundColor: WHITE_COLOR, + elevation: 0, + title: Text(imageData.title), + leading: SmoothBackButton( + onPressed: () => Navigator.maybePop(context, _isEdited), + ), + ), + body: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ConstrainedBox( + constraints: BoxConstraints.tight( + Size(double.infinity, MediaQuery.of(context).size.height / 2), + ), + child: PhotoView( + minScale: 0.2, + imageProvider: imageProvider, + heroAttributes: PhotoViewHeroAttributes( + tag: imageProvider, + ), + backgroundDecoration: const BoxDecoration( + color: Colors.black, + ), + ), + ), + ], + ), + ); + + Future _editImage(final DaoInt daoInt) async { + final File? imageFile = await LoadingDialog.run( + context: context, + future: _downloadImageFile(daoInt, imageData.imageUrl!), + ); + + if (imageFile == null) { + return; + } + + if (!mounted) { + return; + } + + final File? photoUploaded = await Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => ConfirmAndUploadPicture( + barcode: widget.barcode, + imageType: imageData.imageField, + initialPhoto: imageFile, + ), + ), + ); + if (photoUploaded != null) { + _isEdited = true; + if (!mounted) { + return; + } + + setState(() { + imageProvider = FileImage(photoUploaded); + }); + } + } + + static const String _CROP_IMAGE_SEQUENCE_KEY = 'crop_image_sequence'; + + Future _downloadImageFile(DaoInt daoInt, String url) async { + final http.Response response = await http.get(Uri.parse(url)); + final Directory tempDirectory = await getTemporaryDirectory(); + + final int sequenceNumber = + await getNextSequenceNumber(daoInt, _CROP_IMAGE_SEQUENCE_KEY); + + final File file = + File('${tempDirectory.path}/editing_image_$sequenceNumber'); + + return file.writeAsBytes(response.bodyBytes); + } +} diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index 5206d094681..a7dd7b82f48 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -1199,6 +1199,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.1" + shimmer: + dependency: "direct main" + description: + name: shimmer + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" sky_engine: dependency: transitive description: flutter diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index b2ac7f3ea01..d43788b4c66 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -80,6 +80,7 @@ dependencies: path: ../data_importer share_plus: ^4.0.10 fimber: ^0.6.6 + shimmer: ^2.0.0 dev_dependencies: integration_test: From d9c35d721202cdd3bed3620a501cdca193fb4346 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 4 Sep 2022 19:59:38 +0200 Subject: [PATCH 02/16] chore(develop): release 3.11.0 (#2913) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 13 +++++++++++++ version.txt | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 204ead9050a..f20e6e071eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [3.11.0](https://github.com/openfoodfacts/smooth-app/compare/v3.10.3...v3.11.0) (2022-09-04) + + +### Features + +* Add a gallery of the images selected and uploaded for a product ([#2801](https://github.com/openfoodfacts/smooth-app/issues/2801)) ([c706839](https://github.com/openfoodfacts/smooth-app/commit/c70683939db4324f3299f0c91e103e3eb7368584)) + + +### Miscellaneous + +* **deps:** bump flutter_launcher_icons in /packages/smooth_app ([#2873](https://github.com/openfoodfacts/smooth-app/issues/2873)) ([242ec9d](https://github.com/openfoodfacts/smooth-app/commit/242ec9d91868a1c0e46f2991f58b1c2ce6366951)) +* New Crowdin translations ([#2914](https://github.com/openfoodfacts/smooth-app/issues/2914)) ([d1b9020](https://github.com/openfoodfacts/smooth-app/commit/d1b902084b538407575e616169d5bd66d1770982)) + ## [3.10.3](https://github.com/openfoodfacts/smooth-app/compare/v3.10.2...v3.10.3) (2022-09-03) diff --git a/version.txt b/version.txt index 7d4ef04f654..afad818663d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.10.3 +3.11.0 From 91aa45782793d9e1f78c5201053c599d08314260 Mon Sep 17 00:00:00 2001 From: Abu Ghalib <33085535+abughalib@users.noreply.github.com> Date: Mon, 5 Sep 2022 19:27:24 +0530 Subject: [PATCH 03/16] fix: #2846 horizontal layout buttons (#2899) * fix: #2846 * fix: #2846 * padding fix * small padding --- .../pages/product/edit_ingredients_page.dart | 1 + .../pages/product/nutrition_page_loaded.dart | 1 + .../lib/pages/product/simple_input_page.dart | 24 +++++++++++-------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart b/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart index cf5c3fa046e..895a8fb841a 100644 --- a/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart @@ -369,6 +369,7 @@ class _OcrWidget extends StatelessWidget { ), const SizedBox(height: MEDIUM_SPACE), SmoothActionButtonsBar( + axis: Axis.horizontal, negativeAction: SmoothActionButton( text: appLocalizations.cancel, onPressed: () => Navigator.pop(context), diff --git a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart index 3e6051f8539..a939798d496 100644 --- a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart +++ b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart @@ -145,6 +145,7 @@ class _NutritionPageLoadedState extends State { ), ), SmoothActionButtonsBar( + axis: Axis.horizontal, positiveAction: SmoothActionButton( text: appLocalizations.save, onPressed: () async => _exitPage( 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 405d4e65b0f..94a5413e724 100644 --- a/packages/smooth_app/lib/pages/product/simple_input_page.dart +++ b/packages/smooth_app/lib/pages/product/simple_input_page.dart @@ -111,17 +111,21 @@ class _SimpleInputPageState extends State { child: ListView(children: simpleInputs), ), ), - SmoothActionButtonsBar( - positiveAction: SmoothActionButton( - text: appLocalizations.save, - onPressed: () async => _exitPage( - await _mayExitPage(saving: true), + 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), + negativeAction: SmoothActionButton( + text: appLocalizations.cancel, + onPressed: () async => _exitPage( + await _mayExitPage(saving: false), + ), ), ), ), From a5f53430a5164ba198b6269867a20d1a1db8fdd2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 09:46:16 +0200 Subject: [PATCH 04/16] chore: New Crowdin translations (#2920) Co-authored-by: Crowdin Bot --- packages/smooth_app/lib/l10n/app_aa.arb | 4 +++- packages/smooth_app/lib/l10n/app_af.arb | 4 +++- packages/smooth_app/lib/l10n/app_ak.arb | 4 +++- packages/smooth_app/lib/l10n/app_am.arb | 4 +++- packages/smooth_app/lib/l10n/app_ar.arb | 4 +++- packages/smooth_app/lib/l10n/app_as.arb | 4 +++- packages/smooth_app/lib/l10n/app_az.arb | 4 +++- packages/smooth_app/lib/l10n/app_be.arb | 4 +++- packages/smooth_app/lib/l10n/app_bg.arb | 4 +++- packages/smooth_app/lib/l10n/app_bm.arb | 4 +++- packages/smooth_app/lib/l10n/app_bn.arb | 4 +++- packages/smooth_app/lib/l10n/app_bo.arb | 4 +++- packages/smooth_app/lib/l10n/app_br.arb | 4 +++- packages/smooth_app/lib/l10n/app_bs.arb | 4 +++- packages/smooth_app/lib/l10n/app_ca.arb | 4 +++- packages/smooth_app/lib/l10n/app_ce.arb | 4 +++- packages/smooth_app/lib/l10n/app_co.arb | 4 +++- packages/smooth_app/lib/l10n/app_cs.arb | 4 +++- packages/smooth_app/lib/l10n/app_cv.arb | 4 +++- packages/smooth_app/lib/l10n/app_cy.arb | 4 +++- packages/smooth_app/lib/l10n/app_da.arb | 4 +++- packages/smooth_app/lib/l10n/app_de.arb | 4 +++- packages/smooth_app/lib/l10n/app_el.arb | 4 +++- packages/smooth_app/lib/l10n/app_en.arb | 2 +- packages/smooth_app/lib/l10n/app_eo.arb | 4 +++- packages/smooth_app/lib/l10n/app_es.arb | 4 +++- packages/smooth_app/lib/l10n/app_et.arb | 4 +++- packages/smooth_app/lib/l10n/app_eu.arb | 4 +++- packages/smooth_app/lib/l10n/app_fa.arb | 4 +++- packages/smooth_app/lib/l10n/app_fi.arb | 4 +++- packages/smooth_app/lib/l10n/app_fil.arb | 4 +++- packages/smooth_app/lib/l10n/app_fo.arb | 4 +++- packages/smooth_app/lib/l10n/app_fr.arb | 4 +++- packages/smooth_app/lib/l10n/app_ga.arb | 4 +++- packages/smooth_app/lib/l10n/app_gd.arb | 4 +++- packages/smooth_app/lib/l10n/app_gl.arb | 4 +++- packages/smooth_app/lib/l10n/app_gu.arb | 4 +++- packages/smooth_app/lib/l10n/app_ha.arb | 4 +++- packages/smooth_app/lib/l10n/app_he.arb | 12 ++++++---- packages/smooth_app/lib/l10n/app_hi.arb | 4 +++- packages/smooth_app/lib/l10n/app_hr.arb | 4 +++- packages/smooth_app/lib/l10n/app_ht.arb | 4 +++- packages/smooth_app/lib/l10n/app_hu.arb | 4 +++- packages/smooth_app/lib/l10n/app_hy.arb | 4 +++- packages/smooth_app/lib/l10n/app_id.arb | 4 +++- packages/smooth_app/lib/l10n/app_ii.arb | 4 +++- packages/smooth_app/lib/l10n/app_is.arb | 4 +++- packages/smooth_app/lib/l10n/app_it.arb | 4 +++- packages/smooth_app/lib/l10n/app_iu.arb | 4 +++- packages/smooth_app/lib/l10n/app_ja.arb | 4 +++- packages/smooth_app/lib/l10n/app_jv.arb | 4 +++- packages/smooth_app/lib/l10n/app_ka.arb | 4 +++- packages/smooth_app/lib/l10n/app_kk.arb | 4 +++- packages/smooth_app/lib/l10n/app_km.arb | 4 +++- packages/smooth_app/lib/l10n/app_kn.arb | 4 +++- packages/smooth_app/lib/l10n/app_ko.arb | 4 +++- packages/smooth_app/lib/l10n/app_ku.arb | 4 +++- packages/smooth_app/lib/l10n/app_kw.arb | 4 +++- packages/smooth_app/lib/l10n/app_ky.arb | 4 +++- packages/smooth_app/lib/l10n/app_la.arb | 4 +++- packages/smooth_app/lib/l10n/app_lb.arb | 4 +++- packages/smooth_app/lib/l10n/app_lo.arb | 4 +++- packages/smooth_app/lib/l10n/app_lt.arb | 4 +++- packages/smooth_app/lib/l10n/app_lv.arb | 4 +++- packages/smooth_app/lib/l10n/app_mg.arb | 4 +++- packages/smooth_app/lib/l10n/app_mi.arb | 4 +++- packages/smooth_app/lib/l10n/app_ml.arb | 4 +++- packages/smooth_app/lib/l10n/app_mn.arb | 4 +++- packages/smooth_app/lib/l10n/app_mr.arb | 4 +++- packages/smooth_app/lib/l10n/app_ms.arb | 4 +++- packages/smooth_app/lib/l10n/app_mt.arb | 4 +++- packages/smooth_app/lib/l10n/app_my.arb | 4 +++- packages/smooth_app/lib/l10n/app_nb.arb | 4 +++- packages/smooth_app/lib/l10n/app_ne.arb | 4 +++- packages/smooth_app/lib/l10n/app_nl.arb | 4 +++- packages/smooth_app/lib/l10n/app_nn.arb | 4 +++- packages/smooth_app/lib/l10n/app_no.arb | 4 +++- packages/smooth_app/lib/l10n/app_nr.arb | 4 +++- packages/smooth_app/lib/l10n/app_oc.arb | 4 +++- packages/smooth_app/lib/l10n/app_pa.arb | 4 +++- packages/smooth_app/lib/l10n/app_pl.arb | 4 +++- packages/smooth_app/lib/l10n/app_pt.arb | 4 +++- packages/smooth_app/lib/l10n/app_qu.arb | 4 +++- packages/smooth_app/lib/l10n/app_rm.arb | 4 +++- packages/smooth_app/lib/l10n/app_ro.arb | 4 +++- packages/smooth_app/lib/l10n/app_ru.arb | 4 +++- packages/smooth_app/lib/l10n/app_sa.arb | 4 +++- packages/smooth_app/lib/l10n/app_sc.arb | 4 +++- packages/smooth_app/lib/l10n/app_sd.arb | 4 +++- packages/smooth_app/lib/l10n/app_sg.arb | 4 +++- packages/smooth_app/lib/l10n/app_si.arb | 4 +++- packages/smooth_app/lib/l10n/app_sk.arb | 4 +++- packages/smooth_app/lib/l10n/app_sl.arb | 4 +++- packages/smooth_app/lib/l10n/app_sn.arb | 4 +++- packages/smooth_app/lib/l10n/app_so.arb | 4 +++- packages/smooth_app/lib/l10n/app_sq.arb | 4 +++- packages/smooth_app/lib/l10n/app_sr.arb | 4 +++- packages/smooth_app/lib/l10n/app_ss.arb | 4 +++- packages/smooth_app/lib/l10n/app_st.arb | 4 +++- packages/smooth_app/lib/l10n/app_sv.arb | 4 +++- packages/smooth_app/lib/l10n/app_sw.arb | 4 +++- packages/smooth_app/lib/l10n/app_ta.arb | 4 +++- packages/smooth_app/lib/l10n/app_te.arb | 4 +++- packages/smooth_app/lib/l10n/app_tg.arb | 4 +++- packages/smooth_app/lib/l10n/app_th.arb | 4 +++- packages/smooth_app/lib/l10n/app_ti.arb | 4 +++- packages/smooth_app/lib/l10n/app_tl.arb | 4 +++- packages/smooth_app/lib/l10n/app_tn.arb | 4 +++- packages/smooth_app/lib/l10n/app_tr.arb | 30 +++++++++++++----------- packages/smooth_app/lib/l10n/app_ts.arb | 4 +++- packages/smooth_app/lib/l10n/app_tt.arb | 4 +++- packages/smooth_app/lib/l10n/app_tw.arb | 4 +++- packages/smooth_app/lib/l10n/app_ty.arb | 4 +++- packages/smooth_app/lib/l10n/app_ug.arb | 4 +++- packages/smooth_app/lib/l10n/app_uk.arb | 4 +++- packages/smooth_app/lib/l10n/app_ur.arb | 4 +++- packages/smooth_app/lib/l10n/app_uz.arb | 4 +++- packages/smooth_app/lib/l10n/app_ve.arb | 4 +++- packages/smooth_app/lib/l10n/app_vi.arb | 4 +++- packages/smooth_app/lib/l10n/app_wa.arb | 4 +++- packages/smooth_app/lib/l10n/app_wo.arb | 4 +++- packages/smooth_app/lib/l10n/app_xh.arb | 4 +++- packages/smooth_app/lib/l10n/app_yi.arb | 4 +++- packages/smooth_app/lib/l10n/app_yo.arb | 4 +++- packages/smooth_app/lib/l10n/app_zh.arb | 4 +++- packages/smooth_app/lib/l10n/app_zu.arb | 4 +++- 126 files changed, 393 insertions(+), 143 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_aa.arb b/packages/smooth_app/lib/l10n/app_aa.arb index c54581634a2..bc31944c65f 100644 --- a/packages/smooth_app/lib/l10n/app_aa.arb +++ b/packages/smooth_app/lib/l10n/app_aa.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_af.arb b/packages/smooth_app/lib/l10n/app_af.arb index d969898ddc5..124f5691536 100644 --- a/packages/smooth_app/lib/l10n/app_af.arb +++ b/packages/smooth_app/lib/l10n/app_af.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ak.arb b/packages/smooth_app/lib/l10n/app_ak.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_ak.arb +++ b/packages/smooth_app/lib/l10n/app_ak.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_am.arb b/packages/smooth_app/lib/l10n/app_am.arb index f5f52e40d84..7acb3cb740b 100644 --- a/packages/smooth_app/lib/l10n/app_am.arb +++ b/packages/smooth_app/lib/l10n/app_am.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ar.arb b/packages/smooth_app/lib/l10n/app_ar.arb index 288e5cd3bf0..856963a4ce0 100644 --- a/packages/smooth_app/lib/l10n/app_ar.arb +++ b/packages/smooth_app/lib/l10n/app_ar.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "يرجى إرسال بريد إلكتروني إلينا يدويًا إلى contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_as.arb b/packages/smooth_app/lib/l10n/app_as.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_as.arb +++ b/packages/smooth_app/lib/l10n/app_as.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_az.arb b/packages/smooth_app/lib/l10n/app_az.arb index 4bfbe5b6362..9c83cb8f9bf 100644 --- a/packages/smooth_app/lib/l10n/app_az.arb +++ b/packages/smooth_app/lib/l10n/app_az.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_be.arb b/packages/smooth_app/lib/l10n/app_be.arb index 7ab07f4226c..2618e12f635 100644 --- a/packages/smooth_app/lib/l10n/app_be.arb +++ b/packages/smooth_app/lib/l10n/app_be.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bg.arb b/packages/smooth_app/lib/l10n/app_bg.arb index 25b5ba9d746..88e3bd4634e 100644 --- a/packages/smooth_app/lib/l10n/app_bg.arb +++ b/packages/smooth_app/lib/l10n/app_bg.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Моля, изпрати ни ръчно имейл до contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bm.arb b/packages/smooth_app/lib/l10n/app_bm.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_bm.arb +++ b/packages/smooth_app/lib/l10n/app_bm.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bn.arb b/packages/smooth_app/lib/l10n/app_bn.arb index 4002783c20e..dff6cf68c32 100644 --- a/packages/smooth_app/lib/l10n/app_bn.arb +++ b/packages/smooth_app/lib/l10n/app_bn.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bo.arb b/packages/smooth_app/lib/l10n/app_bo.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_bo.arb +++ b/packages/smooth_app/lib/l10n/app_bo.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_br.arb b/packages/smooth_app/lib/l10n/app_br.arb index b2b493375e5..98eb9ff2382 100644 --- a/packages/smooth_app/lib/l10n/app_br.arb +++ b/packages/smooth_app/lib/l10n/app_br.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bs.arb b/packages/smooth_app/lib/l10n/app_bs.arb index 641faa99755..13d5fd43dcd 100644 --- a/packages/smooth_app/lib/l10n/app_bs.arb +++ b/packages/smooth_app/lib/l10n/app_bs.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ca.arb b/packages/smooth_app/lib/l10n/app_ca.arb index b9d10e2d8d5..e2486074caa 100644 --- a/packages/smooth_app/lib/l10n/app_ca.arb +++ b/packages/smooth_app/lib/l10n/app_ca.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ce.arb b/packages/smooth_app/lib/l10n/app_ce.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_ce.arb +++ b/packages/smooth_app/lib/l10n/app_ce.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_co.arb b/packages/smooth_app/lib/l10n/app_co.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_co.arb +++ b/packages/smooth_app/lib/l10n/app_co.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cs.arb b/packages/smooth_app/lib/l10n/app_cs.arb index d24cdfab41d..78a0181cd2a 100644 --- a/packages/smooth_app/lib/l10n/app_cs.arb +++ b/packages/smooth_app/lib/l10n/app_cs.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Pošlete nám prosím ručně e-mail na adresu contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cv.arb b/packages/smooth_app/lib/l10n/app_cv.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_cv.arb +++ b/packages/smooth_app/lib/l10n/app_cv.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cy.arb b/packages/smooth_app/lib/l10n/app_cy.arb index c173646041a..a30561b3d5a 100644 --- a/packages/smooth_app/lib/l10n/app_cy.arb +++ b/packages/smooth_app/lib/l10n/app_cy.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_da.arb b/packages/smooth_app/lib/l10n/app_da.arb index 430a4eb0219..58a63d0abcf 100644 --- a/packages/smooth_app/lib/l10n/app_da.arb +++ b/packages/smooth_app/lib/l10n/app_da.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Send manuelt en e-mail til contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "Alle fotos", + "selected_images": "Valgte fotos" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_de.arb b/packages/smooth_app/lib/l10n/app_de.arb index f4105d7c358..3d7c374f829 100644 --- a/packages/smooth_app/lib/l10n/app_de.arb +++ b/packages/smooth_app/lib/l10n/app_de.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Bitte senden Sie uns manuell eine E-Mail an contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "Alle Fotos", + "selected_images": "Ausgewählte Fotos" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_el.arb b/packages/smooth_app/lib/l10n/app_el.arb index 6e2fe832871..c9ff11e512d 100644 --- a/packages/smooth_app/lib/l10n/app_el.arb +++ b/packages/smooth_app/lib/l10n/app_el.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index fee90d546b8..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1630,6 +1630,6 @@ "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" }, - "all_images" : "All Images", + "all_images": "All Images", "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_eo.arb b/packages/smooth_app/lib/l10n/app_eo.arb index 1b742b5139a..e49ef252cb8 100644 --- a/packages/smooth_app/lib/l10n/app_eo.arb +++ b/packages/smooth_app/lib/l10n/app_eo.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_es.arb b/packages/smooth_app/lib/l10n/app_es.arb index d4b12e7d069..6cb443b36c1 100644 --- a/packages/smooth_app/lib/l10n/app_es.arb +++ b/packages/smooth_app/lib/l10n/app_es.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Envíanos manualmente un correo electrónico a contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "Todas las imágenes", + "selected_images": "Imágenes seleccionadas" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_et.arb b/packages/smooth_app/lib/l10n/app_et.arb index 5fba7f87b4b..6bb494c29ff 100644 --- a/packages/smooth_app/lib/l10n/app_et.arb +++ b/packages/smooth_app/lib/l10n/app_et.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_eu.arb b/packages/smooth_app/lib/l10n/app_eu.arb index 849e0b208eb..c22d4cf264f 100644 --- a/packages/smooth_app/lib/l10n/app_eu.arb +++ b/packages/smooth_app/lib/l10n/app_eu.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fa.arb b/packages/smooth_app/lib/l10n/app_fa.arb index 7536b53fe72..055c5b06900 100644 --- a/packages/smooth_app/lib/l10n/app_fa.arb +++ b/packages/smooth_app/lib/l10n/app_fa.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fi.arb b/packages/smooth_app/lib/l10n/app_fi.arb index 5c297fb7763..7063619f681 100644 --- a/packages/smooth_app/lib/l10n/app_fi.arb +++ b/packages/smooth_app/lib/l10n/app_fi.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fil.arb b/packages/smooth_app/lib/l10n/app_fil.arb index e001bddc4e7..5413a4fa50a 100644 --- a/packages/smooth_app/lib/l10n/app_fil.arb +++ b/packages/smooth_app/lib/l10n/app_fil.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fo.arb b/packages/smooth_app/lib/l10n/app_fo.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_fo.arb +++ b/packages/smooth_app/lib/l10n/app_fo.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fr.arb b/packages/smooth_app/lib/l10n/app_fr.arb index 04b073189da..9d485665114 100644 --- a/packages/smooth_app/lib/l10n/app_fr.arb +++ b/packages/smooth_app/lib/l10n/app_fr.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ga.arb b/packages/smooth_app/lib/l10n/app_ga.arb index 6cf65f1d9ac..6f12eec738f 100644 --- a/packages/smooth_app/lib/l10n/app_ga.arb +++ b/packages/smooth_app/lib/l10n/app_ga.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gd.arb b/packages/smooth_app/lib/l10n/app_gd.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_gd.arb +++ b/packages/smooth_app/lib/l10n/app_gd.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gl.arb b/packages/smooth_app/lib/l10n/app_gl.arb index d46cebdf56f..e8aa176a30a 100644 --- a/packages/smooth_app/lib/l10n/app_gl.arb +++ b/packages/smooth_app/lib/l10n/app_gl.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gu.arb b/packages/smooth_app/lib/l10n/app_gu.arb index 268a02ae982..0b21fc26566 100644 --- a/packages/smooth_app/lib/l10n/app_gu.arb +++ b/packages/smooth_app/lib/l10n/app_gu.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ha.arb b/packages/smooth_app/lib/l10n/app_ha.arb index b6994ffff1f..312f1334fe9 100644 --- a/packages/smooth_app/lib/l10n/app_ha.arb +++ b/packages/smooth_app/lib/l10n/app_ha.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_he.arb b/packages/smooth_app/lib/l10n/app_he.arb index e4c33d581c3..92ea7ee24c8 100644 --- a/packages/smooth_app/lib/l10n/app_he.arb +++ b/packages/smooth_app/lib/l10n/app_he.arb @@ -1573,7 +1573,7 @@ "@choose_from_gallery": { "description": "Button label for choosing a photo from gallery" }, - "image_upload_queued": "The image will be uploaded in the background as soon as possible.", + "image_upload_queued": "התמונה תישלח ברקע בהקדם האפשרי.", "@image_upload_queued": { "description": "Message when a photo is queued for upload" }, @@ -1618,16 +1618,18 @@ "@help_with_openfoodfacts": { "description": "Label for the email title" }, - "product_task_background_schedule": "The product will be updated in the background as soon as possible.", + "product_task_background_schedule": "המוצר יעודכן ברקע בהקדם האפשרי.", "@product_task_background_schedule": { "description": "Message when a product is scheduled for background update" }, - "no_email_client_available_dialog_title": "No email application!", + "no_email_client_available_dialog_title": "אין יישומון דוא״ל!", "@no_email_client_available_dialog_title": { "description": "Title for the dialog when no email client is installed on the device" }, - "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", + "no_email_client_available_dialog_content": "נא לשלוח אלינו הודעה ידנית אל contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "כל התמונות", + "selected_images": "תמונות נבחרות" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hi.arb b/packages/smooth_app/lib/l10n/app_hi.arb index 826a2a216ea..699801d1c48 100644 --- a/packages/smooth_app/lib/l10n/app_hi.arb +++ b/packages/smooth_app/lib/l10n/app_hi.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hr.arb b/packages/smooth_app/lib/l10n/app_hr.arb index b5819fbe30b..11a1fd6c3e5 100644 --- a/packages/smooth_app/lib/l10n/app_hr.arb +++ b/packages/smooth_app/lib/l10n/app_hr.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ht.arb b/packages/smooth_app/lib/l10n/app_ht.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_ht.arb +++ b/packages/smooth_app/lib/l10n/app_ht.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hu.arb b/packages/smooth_app/lib/l10n/app_hu.arb index c1963d1b845..c57ec635b2a 100644 --- a/packages/smooth_app/lib/l10n/app_hu.arb +++ b/packages/smooth_app/lib/l10n/app_hu.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hy.arb b/packages/smooth_app/lib/l10n/app_hy.arb index b07dda7bc8f..5248d37c9d2 100644 --- a/packages/smooth_app/lib/l10n/app_hy.arb +++ b/packages/smooth_app/lib/l10n/app_hy.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_id.arb b/packages/smooth_app/lib/l10n/app_id.arb index 9ff2fc4ad89..437e4e9c9a1 100644 --- a/packages/smooth_app/lib/l10n/app_id.arb +++ b/packages/smooth_app/lib/l10n/app_id.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ii.arb b/packages/smooth_app/lib/l10n/app_ii.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_ii.arb +++ b/packages/smooth_app/lib/l10n/app_ii.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_is.arb b/packages/smooth_app/lib/l10n/app_is.arb index 1e69472397e..73e56c86d62 100644 --- a/packages/smooth_app/lib/l10n/app_is.arb +++ b/packages/smooth_app/lib/l10n/app_is.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_it.arb b/packages/smooth_app/lib/l10n/app_it.arb index 147cd44fffe..8aff73eb1d8 100644 --- a/packages/smooth_app/lib/l10n/app_it.arb +++ b/packages/smooth_app/lib/l10n/app_it.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Sei pregato di inviarci manualmente un'email a contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_iu.arb b/packages/smooth_app/lib/l10n/app_iu.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_iu.arb +++ b/packages/smooth_app/lib/l10n/app_iu.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ja.arb b/packages/smooth_app/lib/l10n/app_ja.arb index 858ef7f6b6e..831fa0d8af5 100644 --- a/packages/smooth_app/lib/l10n/app_ja.arb +++ b/packages/smooth_app/lib/l10n/app_ja.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "すべての画像", + "selected_images": "選択した画像" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_jv.arb b/packages/smooth_app/lib/l10n/app_jv.arb index 8aea30c97b3..3f3b6b5e46a 100644 --- a/packages/smooth_app/lib/l10n/app_jv.arb +++ b/packages/smooth_app/lib/l10n/app_jv.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ka.arb b/packages/smooth_app/lib/l10n/app_ka.arb index 32d7f37ba84..664f8a989c9 100644 --- a/packages/smooth_app/lib/l10n/app_ka.arb +++ b/packages/smooth_app/lib/l10n/app_ka.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kk.arb b/packages/smooth_app/lib/l10n/app_kk.arb index 7c7625b6386..9c1d4cd92f5 100644 --- a/packages/smooth_app/lib/l10n/app_kk.arb +++ b/packages/smooth_app/lib/l10n/app_kk.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_km.arb b/packages/smooth_app/lib/l10n/app_km.arb index 944c3454226..510302ab77b 100644 --- a/packages/smooth_app/lib/l10n/app_km.arb +++ b/packages/smooth_app/lib/l10n/app_km.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kn.arb b/packages/smooth_app/lib/l10n/app_kn.arb index 7be2e1fba18..c287f08fd50 100644 --- a/packages/smooth_app/lib/l10n/app_kn.arb +++ b/packages/smooth_app/lib/l10n/app_kn.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ko.arb b/packages/smooth_app/lib/l10n/app_ko.arb index 3ed88f31d1a..fbb4d2c5514 100644 --- a/packages/smooth_app/lib/l10n/app_ko.arb +++ b/packages/smooth_app/lib/l10n/app_ko.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ku.arb b/packages/smooth_app/lib/l10n/app_ku.arb index 5ebad7c4a25..bbea31c4b82 100644 --- a/packages/smooth_app/lib/l10n/app_ku.arb +++ b/packages/smooth_app/lib/l10n/app_ku.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kw.arb b/packages/smooth_app/lib/l10n/app_kw.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_kw.arb +++ b/packages/smooth_app/lib/l10n/app_kw.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ky.arb b/packages/smooth_app/lib/l10n/app_ky.arb index 86f55a4c43a..927e98d4859 100644 --- a/packages/smooth_app/lib/l10n/app_ky.arb +++ b/packages/smooth_app/lib/l10n/app_ky.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_la.arb b/packages/smooth_app/lib/l10n/app_la.arb index bce7c1d2199..9b0fe1fc870 100644 --- a/packages/smooth_app/lib/l10n/app_la.arb +++ b/packages/smooth_app/lib/l10n/app_la.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lb.arb b/packages/smooth_app/lib/l10n/app_lb.arb index 92cc5913469..ecc0e22e284 100644 --- a/packages/smooth_app/lib/l10n/app_lb.arb +++ b/packages/smooth_app/lib/l10n/app_lb.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lo.arb b/packages/smooth_app/lib/l10n/app_lo.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_lo.arb +++ b/packages/smooth_app/lib/l10n/app_lo.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lt.arb b/packages/smooth_app/lib/l10n/app_lt.arb index 701897bd57e..038c20f65f1 100644 --- a/packages/smooth_app/lib/l10n/app_lt.arb +++ b/packages/smooth_app/lib/l10n/app_lt.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lv.arb b/packages/smooth_app/lib/l10n/app_lv.arb index 852614059f1..74712515c76 100644 --- a/packages/smooth_app/lib/l10n/app_lv.arb +++ b/packages/smooth_app/lib/l10n/app_lv.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mg.arb b/packages/smooth_app/lib/l10n/app_mg.arb index 26fac8fd6fd..da7139865cd 100644 --- a/packages/smooth_app/lib/l10n/app_mg.arb +++ b/packages/smooth_app/lib/l10n/app_mg.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mi.arb b/packages/smooth_app/lib/l10n/app_mi.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_mi.arb +++ b/packages/smooth_app/lib/l10n/app_mi.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ml.arb b/packages/smooth_app/lib/l10n/app_ml.arb index e36b7ba0cc0..f32d85774bb 100644 --- a/packages/smooth_app/lib/l10n/app_ml.arb +++ b/packages/smooth_app/lib/l10n/app_ml.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mn.arb b/packages/smooth_app/lib/l10n/app_mn.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_mn.arb +++ b/packages/smooth_app/lib/l10n/app_mn.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mr.arb b/packages/smooth_app/lib/l10n/app_mr.arb index fa5a47e928b..6291e75bfe4 100644 --- a/packages/smooth_app/lib/l10n/app_mr.arb +++ b/packages/smooth_app/lib/l10n/app_mr.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ms.arb b/packages/smooth_app/lib/l10n/app_ms.arb index e084af3fb7f..1e9bf6029bf 100644 --- a/packages/smooth_app/lib/l10n/app_ms.arb +++ b/packages/smooth_app/lib/l10n/app_ms.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mt.arb b/packages/smooth_app/lib/l10n/app_mt.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_mt.arb +++ b/packages/smooth_app/lib/l10n/app_mt.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_my.arb b/packages/smooth_app/lib/l10n/app_my.arb index 3ac00c3bfbd..0249d0a5870 100644 --- a/packages/smooth_app/lib/l10n/app_my.arb +++ b/packages/smooth_app/lib/l10n/app_my.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nb.arb b/packages/smooth_app/lib/l10n/app_nb.arb index ac6551969c5..d4735aa9b1f 100644 --- a/packages/smooth_app/lib/l10n/app_nb.arb +++ b/packages/smooth_app/lib/l10n/app_nb.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ne.arb b/packages/smooth_app/lib/l10n/app_ne.arb index a7db71f19ea..46dad364c39 100644 --- a/packages/smooth_app/lib/l10n/app_ne.arb +++ b/packages/smooth_app/lib/l10n/app_ne.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nl.arb b/packages/smooth_app/lib/l10n/app_nl.arb index 19b12349da9..523b1f11593 100644 --- a/packages/smooth_app/lib/l10n/app_nl.arb +++ b/packages/smooth_app/lib/l10n/app_nl.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Stuur ons alstublieft handmatig een e-mail naar contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nn.arb b/packages/smooth_app/lib/l10n/app_nn.arb index 502fb999097..745ccf3e96c 100644 --- a/packages/smooth_app/lib/l10n/app_nn.arb +++ b/packages/smooth_app/lib/l10n/app_nn.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_no.arb b/packages/smooth_app/lib/l10n/app_no.arb index 502fb999097..745ccf3e96c 100644 --- a/packages/smooth_app/lib/l10n/app_no.arb +++ b/packages/smooth_app/lib/l10n/app_no.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nr.arb b/packages/smooth_app/lib/l10n/app_nr.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_nr.arb +++ b/packages/smooth_app/lib/l10n/app_nr.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_oc.arb b/packages/smooth_app/lib/l10n/app_oc.arb index 1cb67bf75f3..9f0b2a0f300 100644 --- a/packages/smooth_app/lib/l10n/app_oc.arb +++ b/packages/smooth_app/lib/l10n/app_oc.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pa.arb b/packages/smooth_app/lib/l10n/app_pa.arb index 62462430641..c9d6899e9e5 100644 --- a/packages/smooth_app/lib/l10n/app_pa.arb +++ b/packages/smooth_app/lib/l10n/app_pa.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pl.arb b/packages/smooth_app/lib/l10n/app_pl.arb index 5dfdbcc2318..60af410d533 100644 --- a/packages/smooth_app/lib/l10n/app_pl.arb +++ b/packages/smooth_app/lib/l10n/app_pl.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Prześlij nam ręcznie e-mail na adres contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "Wszystkie obrazy", + "selected_images": "Wybrane obrazy" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pt.arb b/packages/smooth_app/lib/l10n/app_pt.arb index 81648b63301..e8d3a5a56c3 100644 --- a/packages/smooth_app/lib/l10n/app_pt.arb +++ b/packages/smooth_app/lib/l10n/app_pt.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Por favor, envie manualmente um e-mail para contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "Todas as imagens", + "selected_images": "Imagens seleccionadas" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_qu.arb b/packages/smooth_app/lib/l10n/app_qu.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_qu.arb +++ b/packages/smooth_app/lib/l10n/app_qu.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_rm.arb b/packages/smooth_app/lib/l10n/app_rm.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_rm.arb +++ b/packages/smooth_app/lib/l10n/app_rm.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ro.arb b/packages/smooth_app/lib/l10n/app_ro.arb index 3ee75f717e1..5994ab93a05 100644 --- a/packages/smooth_app/lib/l10n/app_ro.arb +++ b/packages/smooth_app/lib/l10n/app_ro.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Vă rugăm să ne trimiteți manual un e-mail la contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ru.arb b/packages/smooth_app/lib/l10n/app_ru.arb index d4e81efd69e..c38933c1eb2 100644 --- a/packages/smooth_app/lib/l10n/app_ru.arb +++ b/packages/smooth_app/lib/l10n/app_ru.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sa.arb b/packages/smooth_app/lib/l10n/app_sa.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_sa.arb +++ b/packages/smooth_app/lib/l10n/app_sa.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sc.arb b/packages/smooth_app/lib/l10n/app_sc.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_sc.arb +++ b/packages/smooth_app/lib/l10n/app_sc.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sd.arb b/packages/smooth_app/lib/l10n/app_sd.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_sd.arb +++ b/packages/smooth_app/lib/l10n/app_sd.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sg.arb b/packages/smooth_app/lib/l10n/app_sg.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_sg.arb +++ b/packages/smooth_app/lib/l10n/app_sg.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_si.arb b/packages/smooth_app/lib/l10n/app_si.arb index 02fca6996a3..1ff554adbaf 100644 --- a/packages/smooth_app/lib/l10n/app_si.arb +++ b/packages/smooth_app/lib/l10n/app_si.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sk.arb b/packages/smooth_app/lib/l10n/app_sk.arb index 2a79c45d038..1eadb41ac94 100644 --- a/packages/smooth_app/lib/l10n/app_sk.arb +++ b/packages/smooth_app/lib/l10n/app_sk.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sl.arb b/packages/smooth_app/lib/l10n/app_sl.arb index f5242c24c03..429ec3cb6e2 100644 --- a/packages/smooth_app/lib/l10n/app_sl.arb +++ b/packages/smooth_app/lib/l10n/app_sl.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sn.arb b/packages/smooth_app/lib/l10n/app_sn.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_sn.arb +++ b/packages/smooth_app/lib/l10n/app_sn.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_so.arb b/packages/smooth_app/lib/l10n/app_so.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_so.arb +++ b/packages/smooth_app/lib/l10n/app_so.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sq.arb b/packages/smooth_app/lib/l10n/app_sq.arb index f7ddad979ed..17e9456524a 100644 --- a/packages/smooth_app/lib/l10n/app_sq.arb +++ b/packages/smooth_app/lib/l10n/app_sq.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sr.arb b/packages/smooth_app/lib/l10n/app_sr.arb index 5b788ded630..9f3ea17bc3a 100644 --- a/packages/smooth_app/lib/l10n/app_sr.arb +++ b/packages/smooth_app/lib/l10n/app_sr.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ss.arb b/packages/smooth_app/lib/l10n/app_ss.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_ss.arb +++ b/packages/smooth_app/lib/l10n/app_ss.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_st.arb b/packages/smooth_app/lib/l10n/app_st.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_st.arb +++ b/packages/smooth_app/lib/l10n/app_st.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sv.arb b/packages/smooth_app/lib/l10n/app_sv.arb index eaaffd470a1..17b39dd0c74 100644 --- a/packages/smooth_app/lib/l10n/app_sv.arb +++ b/packages/smooth_app/lib/l10n/app_sv.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sw.arb b/packages/smooth_app/lib/l10n/app_sw.arb index f8d657a3154..200785245cb 100644 --- a/packages/smooth_app/lib/l10n/app_sw.arb +++ b/packages/smooth_app/lib/l10n/app_sw.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ta.arb b/packages/smooth_app/lib/l10n/app_ta.arb index 2fee0cd3176..34a988d6503 100644 --- a/packages/smooth_app/lib/l10n/app_ta.arb +++ b/packages/smooth_app/lib/l10n/app_ta.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_te.arb b/packages/smooth_app/lib/l10n/app_te.arb index 080c21962c8..1c1c3b73205 100644 --- a/packages/smooth_app/lib/l10n/app_te.arb +++ b/packages/smooth_app/lib/l10n/app_te.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tg.arb b/packages/smooth_app/lib/l10n/app_tg.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_tg.arb +++ b/packages/smooth_app/lib/l10n/app_tg.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_th.arb b/packages/smooth_app/lib/l10n/app_th.arb index edc5e80b4ee..e1d7ddaf9b6 100644 --- a/packages/smooth_app/lib/l10n/app_th.arb +++ b/packages/smooth_app/lib/l10n/app_th.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ti.arb b/packages/smooth_app/lib/l10n/app_ti.arb index 8d24749a48e..5b4a8edd639 100644 --- a/packages/smooth_app/lib/l10n/app_ti.arb +++ b/packages/smooth_app/lib/l10n/app_ti.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tl.arb b/packages/smooth_app/lib/l10n/app_tl.arb index 50c5ddf4116..5f36f12f7ee 100644 --- a/packages/smooth_app/lib/l10n/app_tl.arb +++ b/packages/smooth_app/lib/l10n/app_tl.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tn.arb b/packages/smooth_app/lib/l10n/app_tn.arb index 03cb27058b3..1f5fc116032 100644 --- a/packages/smooth_app/lib/l10n/app_tn.arb +++ b/packages/smooth_app/lib/l10n/app_tn.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tr.arb b/packages/smooth_app/lib/l10n/app_tr.arb index 795d8ada763..7d985d6a70a 100644 --- a/packages/smooth_app/lib/l10n/app_tr.arb +++ b/packages/smooth_app/lib/l10n/app_tr.arb @@ -363,7 +363,7 @@ "ranking_subtitle_match_yes": "Sizin için harika bir eşleşme", "ranking_subtitle_match_no": "Çok zayıf eşleşme", "ranking_subtitle_match_maybe": "Bilinmeyen eşleşme", - "refresh_with_new_preferences": "Refresh the list with your new preferences", + "refresh_with_new_preferences": "Listeyi yeni tercihlerinizle yenileyin", "@refresh_with_new_preferences": { "description": "Action button label: Refresh the list with your new preferences" }, @@ -696,7 +696,7 @@ "@consent_analytics_title": { "description": "Title for the consent analytics UI Page" }, - "consent_analytics_body1": "Help the Open Food Facts volunteers to improve the app. You decide whether to submit anonymous analytics.", + "consent_analytics_body1": "Uygulamayı geliştirmek için Open Food Facts gönüllülerine yardım edin. Anonim analizlerin gönderilip gönderilmeyeceğine siz karar verirsiniz.", "@conset_analytics_body1": { "description": "first paragraph for the consent analytics UI Page" }, @@ -867,7 +867,7 @@ } } }, - "user_profile_title_id_default": "Welcome {id}!", + "user_profile_title_id_default": "{id} hoş geldiniz!", "@user_profile_title_id_default": { "description": "User login (when it's an id)", "placeholders": { @@ -907,7 +907,7 @@ "@camera_focus_point_algorithm_title": { "description": "Title for the Camera focus mode (Android only)" }, - "camera_focus_point_algorithm_subtitle": "Current mode: {mode}\n{reason}", + "camera_focus_point_algorithm_subtitle": "Geçerli mod: {mode}\n{reason}", "@camera_focus_point_algorithm_subtitle": { "description": "SubTitle for the Camera focus mode (Android only)", "placeholders": { @@ -1079,7 +1079,7 @@ "@edit_product_form_item_categories_explainer_2": { "description": "Product edition - Categories - input explainer, part 2" }, - "edit_product_form_item_categories_explainer_3": "Examples: Sardines in olive oil, Orange juice from concentrate", + "edit_product_form_item_categories_explainer_3": "Örnekler: Zeytinyağında sardalya, Konsantreden portakal suyu", "@edit_product_form_item_categories_explainer_3": { "description": "Product edition - Categories - input explainer, part 3" }, @@ -1310,7 +1310,7 @@ "@dev_preferences_import_history_title": { "description": "User dev preferences - Import history - Title" }, - "dev_preferences_import_history_subtitle": "Will clear history and put 3 products in there", + "dev_preferences_import_history_subtitle": "Geçmişi temizleyecek ve oraya 3 ürün koyacak", "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, @@ -1343,11 +1343,11 @@ "@dev_mode_scan_camera_only": { "description": "Scan mode - Camera only" }, - "dev_mode_scan_preprocess_full_image": "Camera stream and full image preprocessing, no scanning", + "dev_mode_scan_preprocess_full_image": "Kamera akışı ve tam görüntü ön işleme, tarama yok", "@dev_mode_scan_preprocess_full_image": { "description": "Scan mode - Preprocess full image" }, - "dev_mode_scan_preprocess_half_image": "Camera stream and half image preprocessing, no scanning", + "dev_mode_scan_preprocess_half_image": "Kamera akışı ve yarım görüntü ön işleme, tarama yok", "@dev_mode_scan_preprocess_half_image": { "description": "Scan mode - Preprocess half image" }, @@ -1383,15 +1383,15 @@ } } }, - "user_search_contributor_title": "Products I added", + "user_search_contributor_title": "Eklediğim Ürünler", "@user_search_contributor_title": { "description": "User search (contributor): list tile title" }, - "user_search_informer_title": "Products I edited", + "user_search_informer_title": "Düzenlediğim ürünler", "@user_search_informer_title": { "description": "User search (informer): list tile title" }, - "user_search_photographer_title": "Products I photographed", + "user_search_photographer_title": "Fotoğrafını çektiğim ürünler", "@user_search_photographer_title": { "description": "User search (photographer): list tile title" }, @@ -1587,7 +1587,7 @@ "description": "Label for expanding nutrition facts table in application setting" }, "expand_ingredients_body": "Keep the ingredients panel expanded", - "no_internet_connection": "No internet connection", + "no_internet_connection": "İnternet bağlantısı yok", "@no_internet_connection": { "description": "Message when there is no internet connection" }, @@ -1595,7 +1595,7 @@ "@world_results_label": { "description": "Label describing the current source of the results: the entire world. Keep it short" }, - "world_results_action": "Extend your search to the world", + "world_results_action": "Aramanızı dünyaya genişletin", "@world_results_action": { "description": "Label for the action button that displays the results from the entire world" }, @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Lütfen bize manuel olarak contact@openfoodfacts.org adresine bir e-posta gönderin", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "Tüm Resimler", + "selected_images": "Seçilmiş Resimler" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ts.arb b/packages/smooth_app/lib/l10n/app_ts.arb index 03cb27058b3..1f5fc116032 100644 --- a/packages/smooth_app/lib/l10n/app_ts.arb +++ b/packages/smooth_app/lib/l10n/app_ts.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tt.arb b/packages/smooth_app/lib/l10n/app_tt.arb index 3e7ce729038..ac95cd5f43b 100644 --- a/packages/smooth_app/lib/l10n/app_tt.arb +++ b/packages/smooth_app/lib/l10n/app_tt.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tw.arb b/packages/smooth_app/lib/l10n/app_tw.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_tw.arb +++ b/packages/smooth_app/lib/l10n/app_tw.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ty.arb b/packages/smooth_app/lib/l10n/app_ty.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_ty.arb +++ b/packages/smooth_app/lib/l10n/app_ty.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ug.arb b/packages/smooth_app/lib/l10n/app_ug.arb index 741cfcc789c..2b55b689778 100644 --- a/packages/smooth_app/lib/l10n/app_ug.arb +++ b/packages/smooth_app/lib/l10n/app_ug.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_uk.arb b/packages/smooth_app/lib/l10n/app_uk.arb index 16a223e817e..3ce90d291d6 100644 --- a/packages/smooth_app/lib/l10n/app_uk.arb +++ b/packages/smooth_app/lib/l10n/app_uk.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ur.arb b/packages/smooth_app/lib/l10n/app_ur.arb index 60670d210d8..4e91893164d 100644 --- a/packages/smooth_app/lib/l10n/app_ur.arb +++ b/packages/smooth_app/lib/l10n/app_ur.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_uz.arb b/packages/smooth_app/lib/l10n/app_uz.arb index 3d0889c3e41..f24d7d7fa75 100644 --- a/packages/smooth_app/lib/l10n/app_uz.arb +++ b/packages/smooth_app/lib/l10n/app_uz.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ve.arb b/packages/smooth_app/lib/l10n/app_ve.arb index 03cb27058b3..1f5fc116032 100644 --- a/packages/smooth_app/lib/l10n/app_ve.arb +++ b/packages/smooth_app/lib/l10n/app_ve.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_vi.arb b/packages/smooth_app/lib/l10n/app_vi.arb index 55206a4df08..c8c3470eb62 100644 --- a/packages/smooth_app/lib/l10n/app_vi.arb +++ b/packages/smooth_app/lib/l10n/app_vi.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_wa.arb b/packages/smooth_app/lib/l10n/app_wa.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_wa.arb +++ b/packages/smooth_app/lib/l10n/app_wa.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_wo.arb b/packages/smooth_app/lib/l10n/app_wo.arb index 03cb27058b3..1f5fc116032 100644 --- a/packages/smooth_app/lib/l10n/app_wo.arb +++ b/packages/smooth_app/lib/l10n/app_wo.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_xh.arb b/packages/smooth_app/lib/l10n/app_xh.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_xh.arb +++ b/packages/smooth_app/lib/l10n/app_xh.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_yi.arb b/packages/smooth_app/lib/l10n/app_yi.arb index 4cb954b7585..f21d8eb53ed 100644 --- a/packages/smooth_app/lib/l10n/app_yi.arb +++ b/packages/smooth_app/lib/l10n/app_yi.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_yo.arb b/packages/smooth_app/lib/l10n/app_yo.arb index 9ed43e68436..149cad1719c 100644 --- a/packages/smooth_app/lib/l10n/app_yo.arb +++ b/packages/smooth_app/lib/l10n/app_yo.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_zh.arb b/packages/smooth_app/lib/l10n/app_zh.arb index c91353beb45..a1d4b6a28cb 100644 --- a/packages/smooth_app/lib/l10n/app_zh.arb +++ b/packages/smooth_app/lib/l10n/app_zh.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_zu.arb b/packages/smooth_app/lib/l10n/app_zu.arb index 012f48c8440..f720248d61b 100644 --- a/packages/smooth_app/lib/l10n/app_zu.arb +++ b/packages/smooth_app/lib/l10n/app_zu.arb @@ -1629,5 +1629,7 @@ "no_email_client_available_dialog_content": "Please send us manually an email to contact@openfoodfacts.org", "@no_email_client_available_dialog_content": { "description": "Content for the dialog when no email client is installed on the device" - } + }, + "all_images": "All Images", + "selected_images": "Selected Images" } \ No newline at end of file From 513af0e22df0939ba4a59994c1b26f84447af9e4 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Tue, 6 Sep 2022 09:46:54 +0200 Subject: [PATCH 05/16] fix: back to flutter 3.0.5 (#2923) * fix: back to flutter 3.0.5 * Fix CI * Update README.md Co-authored-by: Marvin M <39344769+M123-dev@users.noreply.github.com> --- ...d-release-to-org-openfoodfacts-scanner.yml | 4 +- ...s-release-to-org-openfoodfacts-scanner.yml | 4 +- .github/workflows/postsubmit.yml | 8 ++-- .github/workflows/presubmit.yml | 5 ++- README.md | 8 ++++ .../cache/files/file_cache_manager_impl.dart | 1 + .../onboarding/onboarding_bottom_bar.dart | 4 +- .../lib/pages/product/new_product_page.dart | 2 +- .../pages/scan/camera_image_full_getter.dart | 2 + packages/smooth_app/pubspec.lock | 43 +++++++++++-------- packages/smooth_app/pubspec.yaml | 4 +- .../smooth_app/test/tests_utils/goldens.dart | 1 + 12 files changed, 56 insertions(+), 30 deletions(-) diff --git a/.github/workflows/android-release-to-org-openfoodfacts-scanner.yml b/.github/workflows/android-release-to-org-openfoodfacts-scanner.yml index d5d07aab489..4506423a281 100644 --- a/.github/workflows/android-release-to-org-openfoodfacts-scanner.yml +++ b/.github/workflows/android-release-to-org-openfoodfacts-scanner.yml @@ -61,7 +61,9 @@ jobs: with: channel: stable cache: true - cache-key: ${{ inputs.FLUTTER-CACHE-KEY }} + flutter-version: '3.0.5' + #cache-key: ${{ inputs.FLUTTER-CACHE-KEY }} + cache-key: revert-3.0.5 - name: Flutter version run: flutter --version diff --git a/.github/workflows/ios-release-to-org-openfoodfacts-scanner.yml b/.github/workflows/ios-release-to-org-openfoodfacts-scanner.yml index 681104141b6..95c0f4abbff 100644 --- a/.github/workflows/ios-release-to-org-openfoodfacts-scanner.yml +++ b/.github/workflows/ios-release-to-org-openfoodfacts-scanner.yml @@ -65,7 +65,9 @@ jobs: with: channel: stable cache: true - cache-key: ${{ inputs.FLUTTER-CACHE-KEY }} + flutter-version: '3.0.5' + #cache-key: ${{ inputs.FLUTTER-CACHE-KEY }} + cache-key: revert-3.0.5 - name: Flutter version run: flutter --version diff --git a/.github/workflows/postsubmit.yml b/.github/workflows/postsubmit.yml index 371af1dba78..e88d988bf96 100644 --- a/.github/workflows/postsubmit.yml +++ b/.github/workflows/postsubmit.yml @@ -23,14 +23,16 @@ jobs: with: distribution: 'zulu' java-version: 11 - + - name: Setup Flutter uses: subosito/flutter-action@v2 with: channel: stable cache: true - cache-key: flutter-${{ env.FLUTTER_VERSION }}-${{ hashFiles('**/pubspec.lock')}} - + flutter-version: '3.0.5' + #cache-key: flutter-${{ env.FLUTTER_VERSION }}-${{ hashFiles('**/pubspec.lock')}} + cache-key: revert-3.0.5 + - run: flutter --version # Get dependencies. diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml index 8a62bdd8823..124883a00fe 100644 --- a/.github/workflows/presubmit.yml +++ b/.github/workflows/presubmit.yml @@ -26,9 +26,10 @@ jobs: uses: subosito/flutter-action@v2 with: channel: stable - flutter-version: ${{ env.FLUTTER_VERSION }} cache: true - cache-key: flutter-${{ env.FLUTTER_VERSION }}-${{ hashFiles('**/pubspec.lock')}} + flutter-version: '3.0.5' + #cache-key: flutter-${{ env.FLUTTER_VERSION }}-${{ hashFiles('**/pubspec.lock')}} + cache-key: revert-3.0.5 - run: flutter --version diff --git a/README.md b/README.md index 372d8e31b94..d635ef73668 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,14 @@ # New Open Food Facts mobile app for Android and iPhone - Codename: "Smooth App" [![SmoothApp Post-Submit Tests](https://github.com/openfoodfacts/smooth-app/actions/workflows/postsubmit.yml/badge.svg)](https://github.com/openfoodfacts/smooth-app/actions/workflows/postsubmit.yml) +## Alert! + +We are currently using Flutter 3.0.5 as the new 3.3.0 [has some bugs](https://github.com/openfoodfacts/smooth-app/issues/2919). + +Running `flutter downgrade 3.0.5` downgrades the version.- + +------ + Latest commit deployed to App Stores: (August 25th 2022 as Build 722) https://github.com/openfoodfacts/smooth-app/releases/tag/v3.8.1 A new Flutter application by [Open Food Facts](https://github.com/openfoodfacts). You can install it on [Android](https://play.google.com/store/apps/details?id=org.openfoodfacts.scanner) or [iPhone/iPad](https://apps.apple.com/app/open-food-facts/id588797948). Note that a internal development build ([Android](https://play.google.com/apps/internaltest/4699092342921529278) or [iPhone/iPad](https://testflight.apple.com/join/c2tiBHgd) )if you'd like to use the results of your PRs quicker. diff --git a/packages/smooth_app/lib/cache/files/file_cache_manager_impl.dart b/packages/smooth_app/lib/cache/files/file_cache_manager_impl.dart index eebe0ac1a2d..71150368c58 100644 --- a/packages/smooth_app/lib/cache/files/file_cache_manager_impl.dart +++ b/packages/smooth_app/lib/cache/files/file_cache_manager_impl.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'dart:typed_data'; import 'package:flutter/foundation.dart'; import 'package:path/path.dart'; diff --git a/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart b/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart index fc6cac54684..d0f51d88135 100644 --- a/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart +++ b/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart @@ -111,10 +111,10 @@ class OnboardingBottomIcon extends StatelessWidget { @override Widget build(BuildContext context) => ElevatedButton( style: ElevatedButton.styleFrom( - foregroundColor: foregroundColor, - backgroundColor: backgroundColor, shape: const CircleBorder(), padding: const EdgeInsets.all(MEDIUM_SPACE), + primary: backgroundColor, + onPrimary: foregroundColor, ), onPressed: onPressed, child: Icon(icon), diff --git a/packages/smooth_app/lib/pages/product/new_product_page.dart b/packages/smooth_app/lib/pages/product/new_product_page.dart index e459b34774e..efcd63c9b0a 100644 --- a/packages/smooth_app/lib/pages/product/new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/new_product_page.dart @@ -334,7 +334,7 @@ class _ProductPageState extends State with TraceableClientMixin { shape: const CircleBorder(), padding: const EdgeInsets.all( 18), // TODO(monsieurtanuki): cf. FloatingActionButton - backgroundColor: colorScheme.primary, + primary: colorScheme.primary, ), child: Icon(iconData, color: colorScheme.onPrimary), ), diff --git a/packages/smooth_app/lib/pages/scan/camera_image_full_getter.dart b/packages/smooth_app/lib/pages/scan/camera_image_full_getter.dart index 314e2436ad0..4d1231b9ce0 100644 --- a/packages/smooth_app/lib/pages/scan/camera_image_full_getter.dart +++ b/packages/smooth_app/lib/pages/scan/camera_image_full_getter.dart @@ -1,3 +1,5 @@ +import 'dart:typed_data'; + import 'package:camera/camera.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index a7dd7b82f48..a18f22835c7 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -21,7 +21,7 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.3.0" + version: "3.1.11" args: dependency: transitive description: @@ -35,7 +35,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.9.0" + version: "2.8.2" audioplayers: dependency: "direct main" description: @@ -174,7 +174,14 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.2.1" + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" checked_yaml: dependency: transitive description: @@ -195,7 +202,7 @@ packages: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.1" + version: "1.1.0" code_builder: dependency: transitive description: @@ -272,7 +279,7 @@ packages: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "3.0.2" + version: "3.0.1" csslib: dependency: transitive description: @@ -377,7 +384,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.3.1" + version: "1.3.0" ffi: dependency: transitive description: @@ -561,7 +568,7 @@ packages: name: fwfh_text_style url: "https://pub.dartlang.org" source: hosted - version: "2.22.08+1" + version: "2.22.08" glob: dependency: transitive description: @@ -755,14 +762,14 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.12" + version: "0.12.11" material_color_utilities: dependency: transitive description: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.5" + version: "0.1.4" matomo_tracker: dependency: "direct main" description: @@ -1224,7 +1231,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.9.0" + version: "1.8.2" sqflite: dependency: "direct main" description: @@ -1266,14 +1273,14 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.1" + version: "1.1.0" sync_http: dependency: transitive description: name: sync_http url: "https://pub.dartlang.org" source: hosted - version: "0.3.1" + version: "0.3.0" synchronized: dependency: transitive description: @@ -1296,14 +1303,14 @@ packages: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.1" + version: "1.2.0" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.12" + version: "0.4.9" tuple: dependency: transitive description: @@ -1317,7 +1324,7 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.1" + version: "1.3.0" unicode: dependency: transitive description: @@ -1422,7 +1429,7 @@ packages: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "9.0.0" + version: "8.2.2" watcher: dependency: transitive description: @@ -1480,5 +1487,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.18.0 <3.0.0" - flutter: ">=3.3.0" + dart: ">=2.17.6 <3.0.0" + flutter: ">=3.0.0" diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index d43788b4c66..4e22675bd59 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -4,8 +4,8 @@ version: 0.0.0+600 publish_to: "none" environment: - sdk: ">=2.18.0 <3.0.0" - flutter: ">=3.3.0" + sdk: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" dependencies: flutter: diff --git a/packages/smooth_app/test/tests_utils/goldens.dart b/packages/smooth_app/test/tests_utils/goldens.dart index 5b8f28ccab4..c29999f2155 100644 --- a/packages/smooth_app/test/tests_utils/goldens.dart +++ b/packages/smooth_app/test/tests_utils/goldens.dart @@ -1,4 +1,5 @@ import 'dart:developer'; +import 'dart:typed_data'; import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; From e8c97e479b408e745a7e8e26eb3cc38a9a637881 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 6 Sep 2022 09:53:40 +0200 Subject: [PATCH 06/16] fix: Dark status bar for onboarding (#2864) * Ensure all screens from the onboarding have a dark status bar (issue on iOS) * Also apply to KnowledgePanelPage * Ensure the "Authorize" button has a splash color * Format dart code * Useless print statement removed * Knowledge panel card: Only force the status bar brightness on the walkthrough * Revert to the initial implementation * Dart format --- .../knowledge_panel_card.dart | 17 +++++++--- .../onboarding/onboarding_flow_navigator.dart | 1 + .../pages/onboarding/reinvention_page.dart | 1 + .../onboarding/sample_health_card_page.dart | 20 ++++++----- .../lib/pages/onboarding/welcome_page.dart | 1 + .../lib/widgets/smooth_scaffold.dart | 33 +++++++++++++++++-- 6 files changed, 58 insertions(+), 15 deletions(-) diff --git a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_card.dart b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_card.dart index a82daf0b12a..8195614249d 100644 --- a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_card.dart +++ b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_card.dart @@ -10,6 +10,7 @@ import 'package:smooth_app/knowledge_panel/knowledge_panels/knowledge_panel_expa import 'package:smooth_app/knowledge_panel/knowledge_panels/knowledge_panel_group_card.dart'; import 'package:smooth_app/knowledge_panel/knowledge_panels/knowledge_panel_page.dart'; import 'package:smooth_app/knowledge_panel/knowledge_panels/knowledge_panel_summary_card.dart'; +import 'package:smooth_app/widgets/smooth_scaffold.dart'; class KnowledgePanelCard extends StatelessWidget { const KnowledgePanelCard({ @@ -54,14 +55,20 @@ class KnowledgePanelCard extends StatelessWidget { margin: EdgeInsets.zero, ), onTap: () { + final Brightness? brightness = + SmoothBrightnessOverride.of(context)?.brightness; + Navigator.push( context, MaterialPageRoute( - builder: (BuildContext context) => KnowledgePanelPage( - groupElement: group, - panel: panel, - allPanels: allPanels, - product: product, + builder: (BuildContext context) => SmoothBrightnessOverride( + brightness: brightness, + child: KnowledgePanelPage( + groupElement: group, + panel: panel, + allPanels: allPanels, + product: product, + ), ), ), ); diff --git a/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart b/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart index ca735438bd5..ec497cea7e4 100644 --- a/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart +++ b/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart @@ -192,6 +192,7 @@ class OnboardingFlowNavigator { child: Builder( builder: (BuildContext context) => SmoothScaffold( body: widget, + brightness: Brightness.dark, ), ), ); diff --git a/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart b/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart index 86ae51b205b..cdd6347be3a 100644 --- a/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart @@ -25,6 +25,7 @@ class ReinventionPage extends StatelessWidget { return SmoothScaffold( backgroundColor: backgroundColor, + brightness: Brightness.dark, body: SafeArea( child: Stack( children: [ diff --git a/packages/smooth_app/lib/pages/onboarding/sample_health_card_page.dart b/packages/smooth_app/lib/pages/onboarding/sample_health_card_page.dart index ce09f54d7df..4d84d6539a5 100644 --- a/packages/smooth_app/lib/pages/onboarding/sample_health_card_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/sample_health_card_page.dart @@ -3,6 +3,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/pages/onboarding/knowledge_panel_page_template.dart'; import 'package:smooth_app/pages/onboarding/onboarding_flow_navigator.dart'; +import 'package:smooth_app/widgets/smooth_scaffold.dart'; class SampleHealthCardPage extends StatelessWidget { const SampleHealthCardPage(this._localDatabase, this.backgroundColor); @@ -11,13 +12,16 @@ class SampleHealthCardPage extends StatelessWidget { final Color backgroundColor; @override - Widget build(BuildContext context) => KnowledgePanelPageTemplate( - headerTitle: AppLocalizations.of(context).healthCardUtility, - page: OnboardingPage.HEALTH_CARD_EXAMPLE, - panelId: 'health_card', - localDatabase: _localDatabase, - backgroundColor: backgroundColor, - svgAsset: 'assets/onboarding/health.svg', - nextKey: const Key('nextAfterHealth'), + Widget build(BuildContext context) => SmoothBrightnessOverride( + brightness: Brightness.dark, + child: KnowledgePanelPageTemplate( + headerTitle: AppLocalizations.of(context).healthCardUtility, + page: OnboardingPage.HEALTH_CARD_EXAMPLE, + panelId: 'health_card', + localDatabase: _localDatabase, + backgroundColor: backgroundColor, + svgAsset: 'assets/onboarding/health.svg', + nextKey: const Key('nextAfterHealth'), + ), ); } diff --git a/packages/smooth_app/lib/pages/onboarding/welcome_page.dart b/packages/smooth_app/lib/pages/onboarding/welcome_page.dart index 8d13819db45..f56ff1692ee 100644 --- a/packages/smooth_app/lib/pages/onboarding/welcome_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/welcome_page.dart @@ -23,6 +23,7 @@ class WelcomePage extends StatelessWidget { return SmoothScaffold( backgroundColor: backgroundColor, + brightness: Brightness.dark, body: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, diff --git a/packages/smooth_app/lib/widgets/smooth_scaffold.dart b/packages/smooth_app/lib/widgets/smooth_scaffold.dart index add92c68ee4..3be5bf5611a 100644 --- a/packages/smooth_app/lib/widgets/smooth_scaffold.dart +++ b/packages/smooth_app/lib/widgets/smooth_scaffold.dart @@ -100,7 +100,13 @@ class SmoothScaffoldState extends ScaffoldState { return AnnotatedRegion( value: _overlayStyle, - child: child, + child: Theme( + data: Theme.of(context).copyWith( + appBarTheme: AppBarTheme.of(context) + .copyWith(systemOverlayStyle: _overlayStyle), + ), + child: child, + ), ); } @@ -110,7 +116,9 @@ class SmoothScaffoldState extends ScaffoldState { bool get _spaceBehindStatusBar => (widget as SmoothScaffold).spaceBehindStatusBar == true; - Brightness? get _brightness => (widget as SmoothScaffold).brightness; + Brightness? get _brightness => + (widget as SmoothScaffold).brightness ?? + SmoothBrightnessOverride.of(context)?.brightness; SystemUiOverlayStyle get _overlayStyle { switch (_brightness) { @@ -130,3 +138,24 @@ class SmoothScaffoldState extends ScaffoldState { } } } + +/// Class allowing to override the default [Brightness] of +/// a [SmoothScaffold]. +class SmoothBrightnessOverride extends InheritedWidget { + const SmoothBrightnessOverride({ + required Widget child, + Key? key, + this.brightness, + }) : super(key: key, child: child); + + final Brightness? brightness; + + @override + bool updateShouldNotify(SmoothBrightnessOverride oldWidget) => + brightness != oldWidget.brightness; + + static SmoothBrightnessOverride? of(BuildContext context) { + return context + .dependOnInheritedWidgetOfExactType(); + } +} From b42ddb7d160661af5ba5823fdbf3d2065dcec10a Mon Sep 17 00:00:00 2001 From: Pierre Slamich Date: Tue, 6 Sep 2022 10:09:39 +0200 Subject: [PATCH 07/16] fix: remove the epic horse --- .github/ISSUE_TEMPLATE/epic.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/epic.md b/.github/ISSUE_TEMPLATE/epic.md index 69eca15a110..afe071efd9d 100644 --- a/.github/ISSUE_TEMPLATE/epic.md +++ b/.github/ISSUE_TEMPLATE/epic.md @@ -3,13 +3,14 @@ name: Epic about: Template for epics. Epics group several user stories together into a main piece of added value. title: '' -labels: "♞ epic" +labels: "epic" assignees: '' --- ### Who for - +- ### What - +- ### Why +- From bf1304a7f1f58edb2bbf421e0156e34810673fd7 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 6 Sep 2022 10:19:29 +0200 Subject: [PATCH 08/16] When returning to the camera's page, the decoder may be disposed (in low memory mode for example). (#2932) When a new image is sent by the camera, we now re-initialize the controller if necessary --- .../lib/pages/scan/ml_kit_scan_page.dart | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart b/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart index e70aff6b192..261080c5e6e 100644 --- a/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/ml_kit_scan_page.dart @@ -239,16 +239,6 @@ class MLKitScannerPageState extends LifecycleAwareState stoppingCamera = false; - // If the controller is initialized update the UI. - _barcodeDecoder ??= MLKitScanDecoder( - camera: _camera!, - scanMode: DevModeScanMode.fromIndex( - _userPreferences.getDevModeIndex( - UserPreferencesDevMode.userPreferencesEnumScanMode, - ), - ), - ); - CameraHelper.initController( SmoothCameraController( _userPreferences, @@ -274,8 +264,19 @@ class MLKitScannerPageState extends LifecycleAwareState final DateTime start = DateTime.now(); try { - final List? res = - await _barcodeDecoder?.processImage(image); + // If the decoder is not initialized yet… + _barcodeDecoder ??= MLKitScanDecoder( + camera: _camera!, + scanMode: DevModeScanMode.fromIndex( + _userPreferences.getDevModeIndex( + UserPreferencesDevMode.userPreferencesEnumScanMode, + ), + ), + ); + + final List? res = await _barcodeDecoder + ?.processImage(image) + .timeout(const Duration(seconds: 5)); _averageProcessingTime.add( DateTime.now().difference(start).inMilliseconds, From 90f9d9edc772f0369403c298fb8bc925876f31fd Mon Sep 17 00:00:00 2001 From: Pierre Slamich Date: Tue, 6 Sep 2022 10:42:42 +0200 Subject: [PATCH 09/16] fix: Improve the issue template for better issues (#2930) --- .github/ISSUE_TEMPLATE/bug_report.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dbbeeb05b46..baa3c2c61f5 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,13 +1,13 @@ --- name: Bug report -about: Create a report to help us improve Project Smoothie +about: Create a report to help us improve the Open Food Facts mobile app (iPhone and Android) title: "" -labels: "" +labels: "bug" assignees: "" --- ### What -- Describe the issue clearly +- ### Steps to reproduce the behavior 1. Go to '...' @@ -16,21 +16,21 @@ assignees: "" 4. See error ### Expected behavior -A clear and concise description of what you expected to happen. + ### Why -- (optional, delete if empty) Why it's important +- ### Part of -- Add the issue number preceded by # (that also allows searching by name for similar issues): eg #525 +- #525 ### Screenshot/Mockup/Before-After -(optional, delete if empty) + ### Smartphone model - - Device: [e.g. Pixel6] - - OS: [e.g. Android 10] - - App Version [e.g. 22] - you can see that either in the About Smoothie dialog in the settings or using https://nerdschalk.com/how-to-find-version-number-of-an-app-installed-on-your-device/ + - Device: + - OS: + - App Version: ### Additional context -(optional, delete if empty) + From 47bbf89a421718f4dcf1c6e2e04ab0198d9b0514 Mon Sep 17 00:00:00 2001 From: Pierre Slamich Date: Tue, 6 Sep 2022 10:43:20 +0200 Subject: [PATCH 10/16] feat: Improve the Feature request template (#2931) --- .github/ISSUE_TEMPLATE/feature_request.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index cf9d966305d..d7bc0190c31 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,21 +2,21 @@ name: Feature request about: Suggest an idea for this project title: '' -labels: '' +labels: 'enhancement' assignees: '' --- ### Problem -(Please replace me by a clear and concise description of what the problem is. Ex. I'm always frustrated when [...]) + ### Proposed solution -(Please replace me by a clear and concise description of what you want to happen) + ### Additional context -(Please replace me by any other context or screenshots about the feature request here.) + ### Mockups ### Part of -- #525 (Please remplace 525 by the most specific parent issue possible) +- #525 From 23b1dd4a4ff56108fbc07e71c7382e1d05d04853 Mon Sep 17 00:00:00 2001 From: Pierre Slamich Date: Tue, 6 Sep 2022 10:44:07 +0200 Subject: [PATCH 11/16] fix: improve the PR template (#2933) --- .github/pull_request_template.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/pull_request_template.yml b/.github/pull_request_template.yml index c997dea3b89..b0fb5d985fd 100644 --- a/.github/pull_request_template.yml +++ b/.github/pull_request_template.yml @@ -1,6 +1,6 @@ ### What -- Changed x to achieve y +- ### Screenshot @@ -8,9 +8,7 @@ ### Fixes bug(s) -- Fixes: #1 -- Closes: #2 +- Fixes: ### Part of -- https://github.com/openfoodfacts/smooth-app/issues/525 - +- #525 From 43aa96d6068bedd5bedb5224a0e545bcd2fe7416 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 10:45:18 +0200 Subject: [PATCH 12/16] chore(develop): release 3.12.0 (#2922) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 22 ++++++++++++++++++++++ version.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f20e6e071eb..45282a6ca01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [3.12.0](https://github.com/openfoodfacts/smooth-app/compare/v3.11.0...v3.12.0) (2022-09-06) + + +### Features + +* Improve the Feature request template ([#2931](https://github.com/openfoodfacts/smooth-app/issues/2931)) ([47bbf89](https://github.com/openfoodfacts/smooth-app/commit/47bbf89a421718f4dcf1c6e2e04ab0198d9b0514)) + + +### Bug Fixes + +* [#2846](https://github.com/openfoodfacts/smooth-app/issues/2846) horizontal layout buttons ([#2899](https://github.com/openfoodfacts/smooth-app/issues/2899)) ([91aa457](https://github.com/openfoodfacts/smooth-app/commit/91aa45782793d9e1f78c5201053c599d08314260)) +* back to flutter 3.0.5 ([#2923](https://github.com/openfoodfacts/smooth-app/issues/2923)) ([513af0e](https://github.com/openfoodfacts/smooth-app/commit/513af0e22df0939ba4a59994c1b26f84447af9e4)) +* Dark status bar for onboarding ([#2864](https://github.com/openfoodfacts/smooth-app/issues/2864)) ([e8c97e4](https://github.com/openfoodfacts/smooth-app/commit/e8c97e479b408e745a7e8e26eb3cc38a9a637881)) +* Improve the issue template for better issues ([#2930](https://github.com/openfoodfacts/smooth-app/issues/2930)) ([90f9d9e](https://github.com/openfoodfacts/smooth-app/commit/90f9d9edc772f0369403c298fb8bc925876f31fd)) +* improve the PR template ([#2933](https://github.com/openfoodfacts/smooth-app/issues/2933)) ([23b1dd4](https://github.com/openfoodfacts/smooth-app/commit/23b1dd4a4ff56108fbc07e71c7382e1d05d04853)) +* remove the epic horse ([b42ddb7](https://github.com/openfoodfacts/smooth-app/commit/b42ddb7d160661af5ba5823fdbf3d2065dcec10a)) + + +### Miscellaneous + +* New Crowdin translations ([#2920](https://github.com/openfoodfacts/smooth-app/issues/2920)) ([a5f5343](https://github.com/openfoodfacts/smooth-app/commit/a5f53430a5164ba198b6269867a20d1a1db8fdd2)) + ## [3.11.0](https://github.com/openfoodfacts/smooth-app/compare/v3.10.3...v3.11.0) (2022-09-04) diff --git a/version.txt b/version.txt index afad818663d..92536a9e485 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.11.0 +3.12.0 From 54eae2ba09f422c6df0c9308b29873138c51e8c3 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 6 Sep 2022 10:55:47 +0200 Subject: [PATCH 13/16] Update README.md (#2935) Fix a small typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d635ef73668..7ad9cbb1a04 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ We are currently using Flutter 3.0.5 as the new 3.3.0 [has some bugs](https://github.com/openfoodfacts/smooth-app/issues/2919). -Running `flutter downgrade 3.0.5` downgrades the version.- +Running `flutter downgrade 3.0.5` downgrades the version. ------ From 0d2be113fc3fd79a1f16db72437843d702c6d2ab Mon Sep 17 00:00:00 2001 From: Aman Raj <57723319+AshAman999@users.noreply.github.com> Date: Tue, 6 Sep 2022 16:16:22 +0530 Subject: [PATCH 14/16] feat: Instant refresh views (#2901) * instant refresh views * instantly update the state for all field changes * documentation correction * function refactor * efficient way to merge the changes into chached P * updated method for edit ingredients page * simple input page refactored * add missing data on nutritionpageloaded * remove un nessary try catch and modularise add_basic_details_page * fix for ocr_packaging_helper.dart * Refactor and suggested changes on pr Co-authored-by: Abu Ghalib Co-authored-by: Abu Ghalib --- .../pages/product/add_basic_details_page.dart | 52 +++++++++---------- .../pages/product/edit_ingredients_page.dart | 47 +++++++---------- .../pages/product/nutrition_container.dart | 15 +++--- .../pages/product/nutrition_page_loaded.dart | 43 ++++++++------- .../pages/product/ocr_ingredients_helper.dart | 9 ++-- .../pages/product/ocr_packaging_helper.dart | 9 ++-- .../lib/pages/product/simple_input_page.dart | 23 ++++++-- 7 files changed, 100 insertions(+), 98 deletions(-) diff --git a/packages/smooth_app/lib/pages/product/add_basic_details_page.dart b/packages/smooth_app/lib/pages/product/add_basic_details_page.dart index fe9295e9f27..764c906d8b4 100644 --- a/packages/smooth_app/lib/pages/product/add_basic_details_page.dart +++ b/packages/smooth_app/lib/pages/product/add_basic_details_page.dart @@ -5,6 +5,7 @@ import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/utils/CountryHelper.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/cards/product_cards/product_image_carousel.dart'; +import 'package:smooth_app/data_models/up_to_date_product_provider.dart'; import 'package:smooth_app/database/dao_product.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; @@ -51,11 +52,22 @@ class _AddBasicDetailsPageState extends State { _brandNameController.text = _product.brands ?? ''; } + /// Returns a [Product] with the values from the text fields. + Product _getChangedProduct(Product product) { + product.productName = _productNameController.text; + product.quantity = _weightController.text; + product.brands = _brandNameController.text; + return product; + } + @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); final Size size = MediaQuery.of(context).size; final LocalDatabase localDatabase = context.read(); + final UpToDateProductProvider provider = + context.read(); + final DaoProduct daoProduct = DaoProduct(localDatabase); return SmoothScaffold( appBar: AppBar( title: Text(appLocalizations.basic_details), @@ -135,12 +147,15 @@ class _AddBasicDetailsPageState extends State { if (!_formKey.currentState!.validate()) { return; } - final Product inputProduct = Product( - productName: _productNameController.text, - quantity: _weightController.text, - brands: _brandNameController.text, + Product inputProduct = Product( barcode: _product.barcode, ); + inputProduct = _getChangedProduct(inputProduct); + final Product? cachedProduct = + await daoProduct.get(_product.barcode!); + if (cachedProduct != null) { + _getChangedProduct(cachedProduct); + } final String uniqueId = UniqueIdGenerator.generateUniqueId( _product.barcode!, BASIC_DETAILS); final BackgroundOtherDetailsInput @@ -160,29 +175,10 @@ class _AddBasicDetailsPageState extends State { uniqueId: uniqueId, ), ); - - final DaoProduct daoProduct = DaoProduct(localDatabase); - final Product? product = await daoProduct.get( - _product.barcode!, - ); - // We go and chek in the local database if the product is - // already in the database. If it is, we update the fields of the product. - //And if it is not, we create a new product with the fields of the _product - // and we insert it in the database. (Giving the user an immediate feedback) - if (product == null) { - daoProduct.put(Product( - barcode: _product.barcode, - productName: _productNameController.text, - brands: _brandNameController.text, - quantity: _weightController.text, - lang: ProductQuery.getLanguage(), - )); - } else { - product.productName = _productNameController.text; - product.brands = _brandNameController.text; - product.quantity = _weightController.text; - daoProduct.put(product); - } + final Product upToDateProduct = + cachedProduct ?? inputProduct; + await daoProduct.put(upToDateProduct); + provider.set(upToDateProduct); localDatabase.notifyListeners(); if (!mounted) { return; @@ -195,7 +191,7 @@ class _AddBasicDetailsPageState extends State { duration: SnackBarDuration.medium, ), ); - Navigator.pop(context, product); + Navigator.pop(context, upToDateProduct); }, ), ), diff --git a/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart b/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart index 895a8fb841a..17a31e41aff 100644 --- a/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ingredients_page.dart @@ -56,14 +56,9 @@ class _EditOcrPageState extends State { Future _onSubmitField() async { setState(() => _updatingText = true); - - try { - await _updateText(_controller.text); - } catch (error) { - final AppLocalizations appLocalizations = AppLocalizations.of(context); - _showError(_helper.getError(appLocalizations)); - } - + final UpToDateProductProvider provider = + context.read(); + await _updateText(_controller.text, provider); setState(() => _updatingText = false); } @@ -129,18 +124,25 @@ class _EditOcrPageState extends State { } } - Future _updateText(final String text) async { - final Product minimalistProduct = - _helper.getMinimalistProduct(_product, text); + Future _updateText( + final String text, UpToDateProductProvider provider) async { + final LocalDatabase localDatabase = context.read(); + final DaoProduct daoProduct = DaoProduct(localDatabase); + Product changedProduct = Product(barcode: _product.barcode); + Product? cachedProduct = await daoProduct.get(_product.barcode!); + if (cachedProduct != null) { + cachedProduct = _helper.getMinimalistProduct(cachedProduct, text); + } + changedProduct = _helper.getMinimalistProduct(changedProduct, text); final String uniqueId = UniqueIdGenerator.generateUniqueId(_product.barcode!, INGREDIENT_EDIT); final BackgroundOtherDetailsInput backgroundOtherDetailsInput = BackgroundOtherDetailsInput( processName: PRODUCT_EDIT_TASK, uniqueId: uniqueId, - barcode: minimalistProduct.barcode!, + barcode: changedProduct.barcode!, languageCode: ProductQuery.getLanguage().code, - inputMap: jsonEncode(minimalistProduct.toJson()), + inputMap: jsonEncode(changedProduct.toJson()), user: jsonEncode(ProductQuery.getUser().toJson()), country: ProductQuery.getCountry()!.iso2Code, ); @@ -151,22 +153,9 @@ class _EditOcrPageState extends State { ), ); - // ignore: use_build_context_synchronously - final LocalDatabase localDatabase = context.read(); - final DaoProduct daoProduct = DaoProduct(localDatabase); - final Product? localProduct = - await daoProduct.get(minimalistProduct.barcode!); - // We go and chek in the local database if the product is - // already in the database. If it is, we update the fields of the product. - //And if it is not, we create a new product with the fields of the minimalistProduct - // and we insert it in the database. (Giving the user an immediate feedback) - if (localProduct != null) { - localProduct.ingredientsText = minimalistProduct.ingredientsText; - await daoProduct.put(localProduct); - } else { - await daoProduct.put(minimalistProduct); - } - + final Product upToDateProduct = cachedProduct ?? changedProduct; + await daoProduct.put(upToDateProduct); + provider.set(upToDateProduct); localDatabase.notifyListeners(); if (!mounted) { return false; diff --git a/packages/smooth_app/lib/pages/product/nutrition_container.dart b/packages/smooth_app/lib/pages/product/nutrition_container.dart index 6db409d3eb5..832541505e0 100644 --- a/packages/smooth_app/lib/pages/product/nutrition_container.dart +++ b/packages/smooth_app/lib/pages/product/nutrition_container.dart @@ -95,13 +95,14 @@ class NutritionContainer { (!_added.contains(nutrientId)); } - /// Returns a [Product] with only nutrients data. - Product getProduct() => Product( - barcode: _barcode, - noNutritionData: noNutritionData, - nutriments: _getNutriments(), - servingSize: _servingSize, - ); + /// Returns a [Product] with changed nutrients data. + Product getProduct(Product product) { + product.barcode = _barcode; + product.noNutritionData = noNutritionData; + product.nutriments = _getNutriments(); + product.servingSize = _servingSize; + return product; + } void copyUnitsFrom(final NutritionContainer other) => _units.addAll(other._units); diff --git a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart index a939798d496..d0e65d87858 100644 --- a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart +++ b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart @@ -11,6 +11,7 @@ import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/utils/CountryHelper.dart'; import 'package:openfoodfacts/utils/UnitHelper.dart'; import 'package:provider/provider.dart'; +import 'package:smooth_app/data_models/up_to_date_product_provider.dart'; import 'package:smooth_app/database/dao_product.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; @@ -69,7 +70,7 @@ class _NutritionPageLoadedState extends State { void initState() { super.initState(); _product = widget.product; - _nutritionContainer = _getFreshContainer(); + _nutritionContainer = _getFreshContainer(widget.product); _numberFormat = NumberFormat('####0.#####', ProductQuery.getLocaleString()); _noNutritionData = _product.noNutritionData ?? false; } @@ -454,13 +455,13 @@ class _NutritionPageLoadedState extends State { _noNutritionData, ); - Product? _getChangedProduct() { + Product? _getChangedProduct(Product product) { if (!_formKey.currentState!.validate()) { return null; } // We use a separate fresh container here. // If something breaks while saving, we won't get a half written object. - final NutritionContainer output = _getFreshContainer(); + final NutritionContainer output = _getFreshContainer(product); // we copy the values for (final String key in _controllers.keys) { final TextEditingController controller = _controllers[key]!; @@ -470,12 +471,12 @@ class _NutritionPageLoadedState extends State { output.noNutritionData = _noNutritionData; // we copy the units output.copyUnitsFrom(_nutritionContainer); - return output.getProduct(); + return output.getProduct(product); } - NutritionContainer _getFreshContainer() => NutritionContainer( + NutritionContainer _getFreshContainer(Product product) => NutritionContainer( orderedNutrients: widget.orderedNutrients, - product: _product, + product: product, ); /// Exits the page if the [flag] is `true`. @@ -495,6 +496,9 @@ class _NutritionPageLoadedState extends State { } final AppLocalizations appLocalizations = AppLocalizations.of(context); final LocalDatabase localDatabase = context.read(); + final UpToDateProductProvider provider = + context.read(); + final DaoProduct daoProduct = DaoProduct(localDatabase); if (!saving) { final bool? pleaseSave = await showDialog( context: context, @@ -519,7 +523,16 @@ class _NutritionPageLoadedState extends State { return true; } } - final Product? changedProduct = _getChangedProduct(); + + final Product? changedProduct = + _getChangedProduct(Product(barcode: widget.product.barcode)); + Product? cachedProduct = await daoProduct.get( + _product.barcode!, + ); + if (cachedProduct != null) { + cachedProduct = _getChangedProduct(_product); + } + if (changedProduct == null) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( @@ -550,19 +563,9 @@ class _NutritionPageLoadedState extends State { uniqueId: uniqueId, ), ); - final DaoProduct daoProduct = DaoProduct(localDatabase); - final Product? product = await daoProduct.get( - _product.barcode!, - ); - // We go and chek in the local database if the product is - // already in the database. If it is, we update the fields of the product. - //And if it is not, we create a new product with the fields of the _product - // and we insert it in the database. (Giving the user an immediate feedback) - if (product != null) { - product.servingSize = changedProduct.servingSize; - product.nutriments = changedProduct.nutriments; - await daoProduct.put(product); - } + final Product upToDateProduct = cachedProduct ?? changedProduct; + await daoProduct.put(upToDateProduct); + provider.set(upToDateProduct); localDatabase.notifyListeners(); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( diff --git a/packages/smooth_app/lib/pages/product/ocr_ingredients_helper.dart b/packages/smooth_app/lib/pages/product/ocr_ingredients_helper.dart index 9d1b9f25fd4..ef001df4780 100644 --- a/packages/smooth_app/lib/pages/product/ocr_ingredients_helper.dart +++ b/packages/smooth_app/lib/pages/product/ocr_ingredients_helper.dart @@ -9,11 +9,10 @@ class OcrIngredientsHelper extends OcrHelper { String getText(final Product product) => product.ingredientsText ?? ''; @override - Product getMinimalistProduct(final Product product, final String text) => - Product( - barcode: product.barcode, - ingredientsText: text, - ); + Product getMinimalistProduct(final Product product, final String text) { + product.ingredientsText = text; + return product; + } @override String? getImageUrl(final Product product) => product.imageIngredientsUrl; 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 915fcadb59e..8926caf8423 100644 --- a/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart +++ b/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart @@ -11,11 +11,10 @@ class OcrPackagingHelper extends OcrHelper { String getText(final Product product) => product.packaging ?? ''; @override - Product getMinimalistProduct(final Product product, final String text) => - Product( - barcode: product.barcode, - packaging: text, - ); + Product getMinimalistProduct(Product product, final String text) { + product.packaging = text; + return product; + } @override String? getImageUrl(final Product product) => product.imagePackagingUrl; 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 94a5413e724..b0d2b2e2583 100644 --- a/packages/smooth_app/lib/pages/product/simple_input_page.dart +++ b/packages/smooth_app/lib/pages/product/simple_input_page.dart @@ -6,6 +6,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/utils/CountryHelper.dart'; import 'package:provider/provider.dart'; +import 'package:smooth_app/data_models/up_to_date_product_provider.dart'; +import 'package:smooth_app/database/dao_product.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'; @@ -44,7 +46,6 @@ class SimpleInputPage extends StatefulWidget { class _SimpleInputPageState extends State { final List _controllers = []; - @override void initState() { super.initState(); @@ -149,6 +150,14 @@ class _SimpleInputPageState extends State { /// or have we clicked on the "save" button? Future _mayExitPage({required final bool saving}) async { final Product changedProduct = Product(barcode: widget.product.barcode); + final LocalDatabase localDatabase = context.read(); + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final UpToDateProductProvider provider = + context.read(); + final DaoProduct daoProduct = DaoProduct(localDatabase); + final Product? cachedProduct = await daoProduct.get( + changedProduct.barcode!, + ); bool changed = false; bool added = false; String pageName = ''; @@ -158,8 +167,11 @@ class _SimpleInputPageState extends State { } if (widget.helpers[i].getChangedProduct(changedProduct)) { changed = true; + if (cachedProduct != null) { + widget.helpers[i].getChangedProduct(cachedProduct); + } } - pageName = widget.helpers[i].getTitle(AppLocalizations.of(context)); + pageName = widget.helpers[i].getTitle(appLocalizations); } if (added) { setState(() {}); @@ -167,8 +179,7 @@ class _SimpleInputPageState extends State { if (!changed) { return true; } - final AppLocalizations appLocalizations = AppLocalizations.of(context); - final LocalDatabase localDatabase = context.read(); + if (!saving) { final bool? pleaseSave = await showDialog( context: context, @@ -215,6 +226,10 @@ class _SimpleInputPageState extends State { uniqueId: uniqueId, ), ); + + final Product upToDateProduct = cachedProduct ?? changedProduct; + await daoProduct.put(upToDateProduct); + provider.set(upToDateProduct); localDatabase.notifyListeners(); if (!mounted) { return false; From d7ed37133e4fc31f7ee588c4912c2e225fb93871 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Tue, 6 Sep 2022 12:50:04 +0200 Subject: [PATCH 15/16] fix: fixed package versions (#2936) --- packages/smooth_app/pubspec.lock | 32 +++++------ packages/smooth_app/pubspec.yaml | 96 ++++++++++++++++---------------- 2 files changed, 64 insertions(+), 64 deletions(-) diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index a18f22835c7..923c83d3057 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -42,7 +42,7 @@ packages: name: audioplayers url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.0.0" audioplayers_android: dependency: transitive description: @@ -335,42 +335,42 @@ packages: name: device_info_plus url: "https://pub.dartlang.org" source: hosted - version: "4.1.2" + version: "4.0.1" device_info_plus_linux: dependency: transitive description: name: device_info_plus_linux url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "2.1.1" device_info_plus_macos: dependency: transitive description: name: device_info_plus_macos url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "2.2.3" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "2.6.1" device_info_plus_web: dependency: transitive description: name: device_info_plus_web url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "2.1.0" device_info_plus_windows: dependency: transitive description: name: device_info_plus_windows url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "3.0.3" device_preview: dependency: "direct main" description: @@ -469,7 +469,7 @@ packages: name: flutter_native_splash url: "https://pub.dartlang.org" source: hosted - version: "2.2.8" + version: "2.2.3+1" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -483,7 +483,7 @@ packages: name: flutter_secure_storage url: "https://pub.dartlang.org" source: hosted - version: "5.1.2" + version: "5.0.2" flutter_secure_storage_linux: dependency: transitive description: @@ -617,7 +617,7 @@ packages: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.13.5" + version: "0.13.4" http_parser: dependency: transitive description: @@ -804,7 +804,7 @@ packages: name: mockito url: "https://pub.dartlang.org" source: hosted - version: "5.3.0" + version: "5.2.0" modal_bottom_sheet: dependency: "direct main" description: @@ -855,7 +855,7 @@ packages: name: package_info_plus url: "https://pub.dartlang.org" source: hosted - version: "1.4.3+1" + version: "1.4.3" package_info_plus_linux: dependency: transitive description: @@ -1093,7 +1093,7 @@ packages: name: rxdart url: "https://pub.dartlang.org" source: hosted - version: "0.27.5" + version: "0.27.4" sentry: dependency: transitive description: @@ -1114,7 +1114,7 @@ packages: name: share_plus url: "https://pub.dartlang.org" source: hosted - version: "4.0.10+1" + version: "4.0.10" share_plus_linux: dependency: transitive description: @@ -1238,7 +1238,7 @@ packages: name: sqflite url: "https://pub.dartlang.org" source: hosted - version: "2.0.3+1" + version: "2.0.2+1" sqflite_common: dependency: transitive description: @@ -1352,7 +1352,7 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.1.5" + version: "6.1.3" url_launcher_android: dependency: transitive description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index 4e22675bd59..9a0220834ec 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -13,36 +13,36 @@ dependencies: flutter_localizations: sdk: flutter - barcode_widget: ^2.0.3 - carousel_slider: ^4.1.1 - cupertino_icons: ^1.0.5 - device_preview: ^1.1.0 - flutter_svg: ^1.1.4 - flutter_map: ^1.1.1 + barcode_widget: 2.0.3 + carousel_slider: 4.1.1 + cupertino_icons: 1.0.5 + device_preview: 1.1.0 + flutter_svg: 1.1.4 + flutter_map: 1.1.1 flutter_widget_from_html_core: any - fwfh_selectable_text: ^0.8.3+1 - flutter_secure_storage: ^5.0.2 - hive: ^2.2.2 - hive_flutter: ^1.1.0 - http: ^0.13.4 - image_picker: ^0.8.5+3 + fwfh_selectable_text: 0.8.3+1 + flutter_secure_storage: 5.0.2 + hive: 2.2.3 + hive_flutter: 1.1.0 + http: 0.13.4 + image_picker: 0.8.5+3 iso_countries: 2.1.0 - latlong2: ^0.8.1 - matomo_tracker: ^1.3.0 - modal_bottom_sheet: ^2.1.0 - openfoodfacts: ^1.24.0 + latlong2: 0.8.1 + matomo_tracker: 1.3.0 + modal_bottom_sheet: 2.1.0 + openfoodfacts: 1.24.0 # openfoodfacts: # path: ../../../openfoodfacts-dart - package_info_plus: ^1.4.2 - device_info_plus: ^4.0.1 - permission_handler: ^9.2.0 - photo_view: ^0.14.0 - uuid: ^3.0.6 - provider: ^6.0.3 - sentry_flutter: ^6.9.1 # careful with upgrading cf: https://github.com/openfoodfacts/smooth-app/issues/1300 - sqflite: ^2.0.2+1 - url_launcher: ^6.1.3 - visibility_detector: ^0.3.3 + package_info_plus: 1.4.3 + device_info_plus: 4.0.1 + permission_handler: 9.2.0 + photo_view: 0.14.0 + uuid: 3.0.6 + provider: 6.0.3 + sentry_flutter: 6.9.1 # careful with upgrading cf: https://github.com/openfoodfacts/smooth-app/issues/1300 + sqflite: 2.0.2+1 + url_launcher: 6.1.3 + visibility_detector: 0.3.3 # Camera (custom implementation for Android) camera: @@ -59,41 +59,41 @@ dependencies: git: url: "https://github.com/g123k/flutter_task_manager.git" - audioplayers: ^1.0.0 - percent_indicator: ^4.2.2 - flutter_email_sender: ^5.1.0 - flutter_native_splash: ^2.2.3+1 + audioplayers: 1.0.0 + percent_indicator: 4.2.2 + flutter_email_sender: 5.1.0 + flutter_native_splash: 2.2.3+1 google_mlkit_barcode_scanning: 0.3.0 - image_cropper: ^2.0.3 - auto_size_text: ^3.0.0 - shared_preferences: ^2.0.15 - typed_data: ^1.3.0 # careful with 1.3.1 because of flutter_driver dependence - intl: ^0.17.0 - flutter_isolate: ^2.0.2 - rxdart: ^0.27.4 - collection: ^1.16.0 - path: ^1.8.2 # careful with 1.8.1 because of https://github.com/flutter/flutter/issues/95478 - path_provider: ^2.0.11 + image_cropper: 2.0.3 + auto_size_text: 3.0.0 + shared_preferences: 2.0.15 + typed_data: 1.3.0 # careful with 1.3.1 because of flutter_driver dependence + intl: 0.17.0 + flutter_isolate: 2.0.2 + rxdart: 0.27.4 + collection: 1.16.0 + path: 1.8.2 # careful with 1.8.1 because of https://github.com/flutter/flutter/issues/95478 + path_provider: 2.0.11 data_importer_shared: path: ../data_importer_shared data_importer: path: ../data_importer - share_plus: ^4.0.10 - fimber: ^0.6.6 - shimmer: ^2.0.0 + share_plus: 4.0.10 + fimber: 0.6.6 + shimmer: 2.0.0 dev_dependencies: integration_test: sdk: flutter flutter_driver: sdk: flutter - flutter_launcher_icons: ^0.10.0 + flutter_launcher_icons: 0.10.0 flutter_test: sdk: flutter - mockito: ^5.2.0 - path_provider_platform_interface: ^2.0.4 - plugin_platform_interface: ^2.1.2 - flutter_lints: ^2.0.1 + mockito: 5.2.0 + path_provider_platform_interface: 2.0.4 + plugin_platform_interface: 2.1.2 + flutter_lints: 2.0.1 openfoodfacts_flutter_lints: git: https://github.com/openfoodfacts/openfoodfacts_flutter_lints.git From e9e538ff93d3fe580bfbf00dfa62021670bba1b1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 12:55:53 +0200 Subject: [PATCH 16/16] chore(develop): release 3.13.0 (#2938) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 12 ++++++++++++ version.txt | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45282a6ca01..aca15cba8f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [3.13.0](https://github.com/openfoodfacts/smooth-app/compare/v3.12.0...v3.13.0) (2022-09-06) + + +### Features + +* Instant refresh views ([#2901](https://github.com/openfoodfacts/smooth-app/issues/2901)) ([0d2be11](https://github.com/openfoodfacts/smooth-app/commit/0d2be113fc3fd79a1f16db72437843d702c6d2ab)) + + +### Bug Fixes + +* fixed package versions ([#2936](https://github.com/openfoodfacts/smooth-app/issues/2936)) ([d7ed371](https://github.com/openfoodfacts/smooth-app/commit/d7ed37133e4fc31f7ee588c4912c2e225fb93871)) + ## [3.12.0](https://github.com/openfoodfacts/smooth-app/compare/v3.11.0...v3.12.0) (2022-09-06) diff --git a/version.txt b/version.txt index 92536a9e485..4eba2a62eb7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.12.0 +3.13.0