From aeb148a079a80d72dadca56e00179745fde96679 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Sun, 2 Jun 2024 19:09:54 +0200 Subject: [PATCH] feat: 5323 - generic way to display product images, with timestamp New file: * `product_image_widget.dart`: Displays a product image thumbnail with the upload timestamp on top. Impacted files: * `product_image_gallery_other_view.dart`: now using new widget `ProductImageWidget` * `uploaded_image_gallery.dart`: now using new widget `ProductImageWidget` --- .../product_image_gallery_other_view.dart | 64 ++--------------- .../lib/pages/image/product_image_widget.dart | 71 +++++++++++++++++++ .../pages/image/uploaded_image_gallery.dart | 30 ++------ 3 files changed, 84 insertions(+), 81 deletions(-) create mode 100644 packages/smooth_app/lib/pages/image/product_image_widget.dart diff --git a/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart b/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart index f09712597eb..677a5506017 100644 --- a/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart +++ b/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart @@ -1,17 +1,13 @@ -import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:intl/intl.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/fetched_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/widgets/images/smooth_image.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; import 'package:smooth_app/pages/image/product_image_other_page.dart'; +import 'package:smooth_app/pages/image/product_image_widget.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; -import 'package:smooth_app/query/product_query.dart'; /// Number of columns for the grid. const int _columns = 3; @@ -108,12 +104,9 @@ class _RawGridGallery extends StatelessWidget { final Product product; final List rawImages; - static final DateFormat _dateFormat = DateFormat('yyyy-MM-dd'); - @override Widget build(BuildContext context) { final double squareSize = _getSquareSize(context); - final DateTime now = DateTime.now(); return SliverGrid( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: _columns, @@ -123,27 +116,6 @@ class _RawGridGallery extends StatelessWidget { // order by descending ids index = rawImages.length - 1 - index; final ProductImage productImage = rawImages[index]; - final DateTime? uploaded = productImage.uploaded; - final String? date; - final bool expired; - if (uploaded == null) { - date = null; - expired = false; - } else { - date = _dateFormat.format(uploaded); - expired = now.difference(uploaded).inDays > 365; - } - final Widget image = SmoothImage( - width: squareSize, - height: squareSize, - imageProvider: NetworkImage( - productImage.getUrl( - product.barcode!, - uriHelper: ProductQuery.uriProductHelper, - ), - ), - rounded: false, - ); return InkWell( onTap: () async => Navigator.push( context, @@ -154,35 +126,11 @@ class _RawGridGallery extends StatelessWidget { ), ), ), - child: date == null - ? image - : Stack( - children: [ - image, - SizedBox( - width: squareSize, - height: squareSize, - child: Align( - alignment: Alignment.bottomCenter, - child: Padding( - padding: const EdgeInsets.all(SMALL_SPACE), - child: Container( - height: VERY_LARGE_SPACE, - color: expired - ? Colors.red.withAlpha(128) - : Colors.white.withAlpha(128), - child: Center( - child: AutoSizeText( - date, - maxLines: 1, - ), - ), - ), - ), - ), - ), - ], - ), + child: ProductImageWidget( + productImage: productImage, + barcode: product.barcode!, + squareSize: squareSize, + ), ); }, addAutomaticKeepAlives: false, diff --git a/packages/smooth_app/lib/pages/image/product_image_widget.dart b/packages/smooth_app/lib/pages/image/product_image_widget.dart new file mode 100644 index 00000000000..9774a555b7b --- /dev/null +++ b/packages/smooth_app/lib/pages/image/product_image_widget.dart @@ -0,0 +1,71 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:openfoodfacts/openfoodfacts.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/query/product_query.dart'; + +/// Displays a product image thumbnail with the upload date on top. +class ProductImageWidget extends StatelessWidget { + const ProductImageWidget({ + required this.productImage, + required this.barcode, + required this.squareSize, + }); + + final ProductImage productImage; + final String barcode; + final double squareSize; + + static final DateFormat _dateFormat = DateFormat('yyyy-MM-dd'); + + @override + Widget build(BuildContext context) { + final Widget image = SmoothImage( + width: squareSize, + height: squareSize, + imageProvider: NetworkImage( + productImage.getUrl( + barcode, + uriHelper: ProductQuery.uriProductHelper, + ), + ), + rounded: false, + ); + final DateTime? uploaded = productImage.uploaded; + if (uploaded == null) { + return image; + } + final DateTime now = DateTime.now(); + final String date = _dateFormat.format(uploaded); + final bool expired = now.difference(uploaded).inDays > 365; + return Stack( + children: [ + image, + SizedBox( + width: squareSize, + height: squareSize, + child: Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.all(SMALL_SPACE), + child: Container( + height: VERY_LARGE_SPACE, + color: expired + ? Colors.red.withAlpha(128) + : Colors.white.withAlpha(128), + child: Center( + child: AutoSizeText( + date, + maxLines: 1, + ), + ), + ), + ), + ), + ), + ], + ); + } +} diff --git a/packages/smooth_app/lib/pages/image/uploaded_image_gallery.dart b/packages/smooth_app/lib/pages/image/uploaded_image_gallery.dart index 3b5094fbb65..4bfdb032e7b 100644 --- a/packages/smooth_app/lib/pages/image/uploaded_image_gallery.dart +++ b/packages/smooth_app/lib/pages/image/uploaded_image_gallery.dart @@ -7,10 +7,10 @@ import 'package:provider/provider.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/widgets/images/smooth_image.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; import 'package:smooth_app/pages/crop_page.dart'; import 'package:smooth_app/pages/crop_parameters.dart'; +import 'package:smooth_app/pages/image/product_image_widget.dart'; import 'package:smooth_app/pages/image_crop_page.dart'; import 'package:smooth_app/pages/product_crop_helper.dart'; import 'package:smooth_app/query/product_query.dart'; @@ -39,7 +39,7 @@ class UploadedImageGallery extends StatelessWidget { Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); final MediaQueryData mediaQueryData = MediaQuery.of(context); - final double columnWidth = mediaQueryData.size.width * .45; + final double columnWidth = mediaQueryData.size.width / 2; return SmoothScaffold( backgroundColor: Colors.black, appBar: SmoothAppBar( @@ -54,20 +54,13 @@ class UploadedImageGallery extends StatelessWidget { body: GridView.builder( itemCount: rawImages.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: mediaQueryData.size.width / 2, + maxCrossAxisExtent: columnWidth, childAspectRatio: 1, - mainAxisSpacing: MEDIUM_SPACE, - crossAxisSpacing: MEDIUM_SPACE, ), itemBuilder: (final BuildContext context, int index) { // order by descending ids index = rawImages.length - 1 - index; final ProductImage rawImage = rawImages[index]; - final String url = rawImage.getUrl( - barcode, - imageSize: ImageSize.DISPLAY, - uriHelper: ProductQuery.uriProductHelper, - ); return GestureDetector( onTap: () async { final LocalDatabase localDatabase = context.read(); @@ -105,19 +98,10 @@ class UploadedImageGallery extends StatelessWidget { navigatorState.pop(); } }, - child: ClipRRect( - borderRadius: ROUNDED_BORDER_RADIUS, - child: Container( - width: columnWidth, - height: columnWidth, - color: Colors.grey[900], - child: SmoothImage( - width: columnWidth, - height: columnWidth, - imageProvider: NetworkImage(url), - fit: BoxFit.contain, - ), - ), + child: ProductImageWidget( + productImage: rawImage, + barcode: barcode, + squareSize: columnWidth, ), ); },