Skip to content

Commit

Permalink
refactor: ProductImageData to contain all image links
Browse files Browse the repository at this point in the history
  • Loading branch information
WildOrangutan committed Oct 3, 2022
1 parent dde3f44 commit 1a02022
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 36 deletions.
14 changes: 9 additions & 5 deletions packages/smooth_app/lib/cards/data_cards/image_upload_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,10 @@ class _ImageUploadCardState extends State<ImageUploadCard> {
// We can already have an _imageProvider for a file that is going to be uploaded
// or an imageUrl for a network image
// or no image yet
if (widget.productImageData.imageUrl != null) {
_imageProvider = NetworkImage(widget.productImageData.imageUrl!);
final String? imageUrl =
widget.productImageData.getImageUrl(ImageSize.ORIGINAL);
if (imageUrl != null) {
_imageProvider = NetworkImage(imageUrl);
} else {
if (_imageProvider != null) {
//Refresh when image has been deselected on server side
Expand Down Expand Up @@ -104,9 +106,11 @@ class _ImageUploadCardState extends State<ImageUploadCard> {
// we need to load the full resolution image

if (_imageFullProvider == null) {
final String imageFullUrl =
widget.productImageData.imageUrl!.replaceAll('.400.', '.full.');
_imageFullProvider = NetworkImage(imageFullUrl);
final String? imageFullUrl =
widget.productImageData.getImageUrl(ImageSize.ORIGINAL);
if (imageFullUrl != null) {
_imageFullProvider = NetworkImage(imageFullUrl);
}
}

// TODO(monsieurtanuki): careful, waiting for pop'ed value
Expand Down
34 changes: 31 additions & 3 deletions packages/smooth_app/lib/data_models/product_image_data.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,43 @@
import 'package:openfoodfacts/model/ProductImage.dart';
import 'package:collection/collection.dart';
import 'package:openfoodfacts/openfoodfacts.dart';

class ProductImageData {
const ProductImageData({
required this.imageField,
required this.title,
required this.buttonText,
this.imageUrl,
required this.imageSizeToUrlMap,
});

ProductImageData.from({
required this.imageField,
required this.title,
required this.buttonText,
required String? barcode,
required Iterable<ProductImage> productImages,
}) : imageSizeToUrlMap = _mapProductImages(barcode, productImages);

final ImageField imageField;
final String title;
final String buttonText;
final String? imageUrl;
final Map<ImageSize?, String> imageSizeToUrlMap;

static Map<ImageSize?, String> _mapProductImages(
String? barcode, Iterable<ProductImage> images) {
final Map<ImageSize?, String?> map = images
.groupListsBy((ProductImage element) => element.size)
.map((ImageSize? size, List<ProductImage> images) =>
MapEntry<ImageSize?, ProductImage>(size, images.first))
.map((ImageSize? size, ProductImage image) {
final String? url = image.url ?? ImageHelper.buildUrl(barcode, image);
return MapEntry<ImageSize?, String?>(size, url);
});
map.removeWhere((_, String? image) => image == null);
return map.cast();
}

String? getImageUrl(ImageSize preferredSize) {
return imageSizeToUrlMap[preferredSize] ??
imageSizeToUrlMap.values.firstOrNull;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:openfoodfacts/model/ProductImage.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';
Expand Down Expand Up @@ -44,11 +45,12 @@ class SmoothImagesSliverGrid extends SmoothImagesView {
final MapEntry<ProductImageData, ImageProvider<Object>?> entry =
imageList[index];
final ImageProvider? imageProvider = entry.value;
final String? imageUrl = entry.key.getImageUrl(ImageSize.THUMB);

return imageProvider == null
return imageProvider == null || imageUrl == null
? const PictureNotFound()
: Hero(
tag: entry.key.imageUrl!,
tag: imageUrl,
child: _ImageTile(
image: imageProvider,
onTap: onTap == null
Expand Down
27 changes: 22 additions & 5 deletions packages/smooth_app/lib/helpers/product_cards_helper.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:collection';

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/model/Attribute.dart';
Expand Down Expand Up @@ -96,32 +98,47 @@ List<ProductImageData> getProductMainImagesData(
<ProductImageData>[
ProductImageData(
imageField: ImageField.FRONT,
imageUrl: product.imageFrontUrl,
imageSizeToUrlMap:
imageUrlToMap(product.imageFrontUrl, product.imageFrontSmallUrl),
title: appLocalizations.product,
buttonText: appLocalizations.front_photo,
),
ProductImageData(
imageField: ImageField.INGREDIENTS,
imageUrl: product.imageIngredientsUrl,
imageSizeToUrlMap: imageUrlToMap(
product.imageIngredientsUrl, product.imageIngredientsSmallUrl),
title: appLocalizations.ingredients,
buttonText: appLocalizations.ingredients_photo,
),
ProductImageData(
imageField: ImageField.NUTRITION,
imageUrl: product.imageNutritionUrl,
imageSizeToUrlMap: imageUrlToMap(
product.imageNutritionUrl, product.imageNutritionSmallUrl),
title: appLocalizations.nutrition,
buttonText: appLocalizations.nutrition_facts_photo,
),
ProductImageData(
imageField: ImageField.PACKAGING,
imageUrl: product.imagePackagingUrl,
imageSizeToUrlMap: imageUrlToMap(
product.imagePackagingUrl, product.imagePackagingSmallUrl),
title: appLocalizations.packaging_information,
buttonText: appLocalizations.packaging_information_photo,
),
ProductImageData(
imageField: ImageField.OTHER,
imageUrl: null,
imageSizeToUrlMap: {},
title: appLocalizations.more_photos,
buttonText: appLocalizations.more_photos,
),
];

Map<ImageSize?, String> imageUrlToMap(String? url, String? smallUrl) {
Map<ImageSize?, String> map = HashMap<ImageSize?, String>();
if (url != null) {
map[ImageSize.DISPLAY] = url;
}
if (smallUrl != null) {
map[ImageSize.SMALL] = smallUrl;
}
return map;
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ class _ProductImageGalleryViewState extends State<ProductImageGalleryView> {
bool _isRefreshed = false;
bool _isLoadingMore = true;

ImageProvider? _provideImage(ProductImageData imageData) =>
imageData.imageUrl == null ? null : NetworkImage(imageData.imageUrl!);
ImageProvider? _provideImage(ProductImageData imageData) {
final String? url = imageData.getImageUrl(ImageSize.SMALL);
return url == null ? null : NetworkImage(url);
}

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -120,9 +122,10 @@ class _ProductImageGalleryViewState extends State<ProductImageGalleryView> {
_buildTitle(appLocalizations.selected_images, theme: theme),
SmoothImagesSliverList(
imagesData: _selectedImages,
onTap: (ProductImageData data, _) => data.imageUrl != null
? _openImage(data)
: _newImage(data),
onTap: (ProductImageData data, _) =>
data.getImageUrl(ImageSize.ORIGINAL) != null
? _openImage(data)
: _newImage(data),
),
_buildTitle(appLocalizations.all_images, theme: theme),
SmoothImagesSliverGrid(
Expand Down Expand Up @@ -250,24 +253,25 @@ class _ProductImageGalleryViewState extends State<ProductImageGalleryView> {
return null;
}

return _deduplicateImages(resultProduct.images!).map(_getProductImageData);
return _mapToProductImageData(resultProduct.images!);
}

/// Groups the list of [ProductImage] by [ProductImage.imgid]
/// and returns the first of every group
Iterable<ProductImage> _deduplicateImages(Iterable<ProductImage> images) =>
Iterable<ProductImageData> _mapToProductImageData(
Iterable<ProductImage> images) =>
images
.groupListsBy((ProductImage element) => element.imgid)
.values
.map((List<ProductImage> sameIdImages) => sameIdImages.firstOrNull)
.whereNotNull();
.map(_createProductImageData);

/// 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.product.barcode, image),
);
ProductImageData _createProductImageData(List<ProductImage> images) {
final ProductImage image = images.last;
return ProductImageData.from(
imageField: image.field,
// TODO(VaiTon): i18n
title: image.imgid ?? '',
buttonText: image.imgid ?? '',
barcode: widget.product.barcode,
productImages: images,
);
}
}
10 changes: 8 additions & 2 deletions packages/smooth_app/lib/pages/product/product_image_viewer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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:openfoodfacts/model/ProductImage.dart';
import 'package:path_provider/path_provider.dart';
import 'package:photo_view/photo_view.dart';
import 'package:provider/provider.dart';
Expand Down Expand Up @@ -40,7 +41,7 @@ class _ProductImageViewerState extends State<ProductImageViewer> {
@override
void initState() {
imageData = widget.imageData;
imageProvider = NetworkImage(imageData.imageUrl!);
imageProvider = NetworkImage(imageData.getImageUrl(ImageSize.DISPLAY)!);

super.initState();
}
Expand Down Expand Up @@ -90,9 +91,14 @@ class _ProductImageViewerState extends State<ProductImageViewer> {
);

Future<void> _editImage(final DaoInt daoInt) async {
final String? imageUrl = imageData.getImageUrl(ImageSize.ORIGINAL);
if (imageUrl == null) {
return;
}

final File? imageFile = await LoadingDialog.run<File>(
context: context,
future: _downloadImageFile(daoInt, imageData.imageUrl!),
future: _downloadImageFile(daoInt, imageUrl),
);

if (imageFile == null) {
Expand Down

0 comments on commit 1a02022

Please sign in to comment.