Skip to content

Commit

Permalink
fix: openfoodfacts#3238 - removed "other" pictures in gallery (keep j…
Browse files Browse the repository at this point in the history
…ust the main 4)

Impacted files:
* `product_cards_helper.dart`: added an optional parameter in order to ignore "other" pictures
* `product_image_gallery_view.dart`: removed the "other" pictures
  • Loading branch information
monsieurtanuki committed Oct 31, 2022
1 parent 14cfed4 commit 2d6d82a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 116 deletions.
18 changes: 10 additions & 8 deletions packages/smooth_app/lib/helpers/product_cards_helper.dart
Expand Up @@ -109,8 +109,9 @@ Widget addPanelButton(

List<ProductImageData> getProductMainImagesData(
Product product,
AppLocalizations appLocalizations,
) =>
AppLocalizations appLocalizations, {
final bool includeOther = true,
}) =>
<ProductImageData>[
ProductImageData(
imageField: ImageField.FRONT,
Expand All @@ -136,10 +137,11 @@ List<ProductImageData> getProductMainImagesData(
title: appLocalizations.packaging_information,
buttonText: appLocalizations.packaging_information_photo,
),
ProductImageData(
imageField: ImageField.OTHER,
imageUrl: null,
title: appLocalizations.more_photos,
buttonText: appLocalizations.more_photos,
),
if (includeOther)
ProductImageData(
imageField: ImageField.OTHER,
imageUrl: null,
title: appLocalizations.more_photos,
buttonText: appLocalizations.more_photos,
),
];
130 changes: 22 additions & 108 deletions packages/smooth_app/lib/pages/product/product_image_gallery_view.dart
@@ -1,6 +1,5 @@
import 'dart:io';

import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
Expand All @@ -9,15 +8,13 @@ import 'package:smooth_app/data_models/product_image_data.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/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/helpers/product_cards_helper.dart';
import 'package:smooth_app/pages/image_crop_page.dart';
import 'package:smooth_app/pages/product/common/product_refresher.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_app_bar.dart';
import 'package:smooth_app/widgets/smooth_scaffold.dart';

Expand All @@ -41,14 +38,9 @@ class ProductImageGalleryView extends StatefulWidget {
class _ProductImageGalleryViewState extends State<ProductImageGalleryView> {
late final LocalDatabase _localDatabase;

Map<ProductImageData, ImageProvider?> _selectedImages =
<ProductImageData, ImageProvider<Object>?>{};

final Map<ProductImageData, ImageProvider?> _unselectedImages =
<ProductImageData, ImageProvider?>{};
late Map<ProductImageData, ImageProvider?> _selectedImages;

bool _isRefreshed = false;
bool _isLoadingMore = true;

ImageProvider? _provideImage(ProductImageData imageData) =>
imageData.imageUrl == null ? null : NetworkImage(imageData.imageUrl!);
Expand Down Expand Up @@ -79,48 +71,22 @@ class _ProductImageGalleryViewState extends State<ProductImageGalleryView> {
product = refreshedProduct;
}
final List<ProductImageData> allProductImagesData =
getProductMainImagesData(product, appLocalizations);
getProductMainImagesData(
product,
appLocalizations,
includeOther: false,
);
_selectedImages = Map<ProductImageData, ImageProvider?>.fromIterables(
allProductImagesData,
allProductImagesData.map(_provideImage),
);

_getProductImages().then(
(Iterable<ProductImageData>? loadedData) {
if (loadedData == null) {
return;
}

final Map<ProductImageData, ImageProvider<Object>?> newMap =
Map<ProductImageData, ImageProvider?>.fromIterables(
loadedData,
loadedData.map(_provideImage),
);
if (mounted) {
setState(
() {
_unselectedImages.clear();
_unselectedImages.addAll(newMap);
_isLoadingMore = false;
},
);
}
},
);
if (_selectedImages.isEmpty) {
return SmoothScaffold(
body: Center(
child: Text(appLocalizations.error),
),
);
}
return SmoothScaffold(
appBar: SmoothAppBar(
title: Text(appLocalizations.edit_product_form_item_photos_title),
subTitle: widget.product.productName != null
title: widget.product.productName != null
? Text(
widget.product.productName!,
maxLines: 1,
maxLines: 2,
overflow: TextOverflow.ellipsis,
)
: null,
Expand All @@ -136,18 +102,15 @@ class _ProductImageGalleryViewState extends State<ProductImageGalleryView> {
child: Scrollbar(
child: CustomScrollView(
slivers: <Widget>[
_buildTitle(appLocalizations.selected_images, theme: theme),
_buildTitle(
appLocalizations.edit_product_form_item_photos_title,
theme: theme,
),
SmoothImagesSliverList(
imagesData: _selectedImages,
onTap: (ProductImageData data, _) =>
data.imageUrl != null ? _openImage(data) : _newImage(data),
),
_buildTitle(appLocalizations.all_images, theme: theme),
SmoothImagesSliverGrid(
imagesData: _unselectedImages,
loading: _isLoadingMore,
onTap: (ProductImageData data, _) => _openImage(data),
),
],
),
),
Expand Down Expand Up @@ -182,21 +145,19 @@ class _ProductImageGalleryViewState extends State<ProductImageGalleryView> {
if (croppedImageFile == null) {
return;
}
if (mounted) {
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;
}
setState(() {
final FileImage fileImage = FileImage(croppedImageFile);
final ImageField imageField = data.imageField;
for (final ProductImageData productImageData in _selectedImages.keys) {
if (productImageData.imageField == imageField) {
_selectedImages[productImageData] = fileImage;
return;
}
}
});
final bool isUploaded = await uploadCapturedPicture(
widget: this,
barcode: _barcode,
Expand All @@ -222,51 +183,4 @@ class _ProductImageGalleryViewState extends State<ProductImageGalleryView> {
);
}
}

Future<Iterable<ProductImageData>?> _getProductImages() async {
final ProductQueryConfiguration configuration = ProductQueryConfiguration(
_barcode,
fields: <ProductField>[ProductField.IMAGES],
language: ProductQuery.getLanguage(),
country: ProductQuery.getCountry(),
);

final ProductResult result;
try {
result = await OpenFoodAPIClient.getProduct(configuration);
} catch (e) {
return null;
}

if (result.status != 1) {
return null;
}

final Product? resultProduct = result.product;
if (resultProduct == null || resultProduct.images == null) {
return null;
}

return _deduplicateImages(resultProduct.images!)
.map((ProductImage image) => ProductImageData.from(image, _barcode));
}

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

ProductImage? _findBestProductImage(Iterable<ProductImage> images) {
final Map<ImageSize?, ProductImage> map = images
.groupListsBy((ProductImage image) => image.size)
.map((ImageSize? key, List<ProductImage> value) =>
MapEntry<ImageSize?, ProductImage>(key, value.first));
return map[ImageSize.DISPLAY] ??
map[ImageSize.SMALL] ??
map[ImageSize.THUMB];
}
}

0 comments on commit 2d6d82a

Please sign in to comment.