-
-
Notifications
You must be signed in to change notification settings - Fork 280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Fix performances on the photos gallery #5447
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,3 +1,4 @@ | ||||||
import 'package:collection/collection.dart'; | ||||||
import 'package:flutter/material.dart'; | ||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
import 'package:openfoodfacts/openfoodfacts.dart'; | ||||||
|
@@ -108,6 +109,8 @@ class _RawGridGallery extends StatelessWidget { | |||||
@override | ||||||
Widget build(BuildContext context) { | ||||||
final double squareSize = _getSquareSize(context); | ||||||
final ImageSize? imageSize = _computeImageSize(squareSize); | ||||||
|
||||||
return SliverGrid( | ||||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( | ||||||
crossAxisCount: _columns, | ||||||
|
@@ -137,6 +140,7 @@ class _RawGridGallery extends StatelessWidget { | |||||
productImage: productImage, | ||||||
barcode: product.barcode!, | ||||||
squareSize: squareSize, | ||||||
imageSize: imageSize, | ||||||
), | ||||||
), | ||||||
); | ||||||
|
@@ -146,4 +150,12 @@ class _RawGridGallery extends StatelessWidget { | |||||
), | ||||||
); | ||||||
} | ||||||
|
||||||
ImageSize? _computeImageSize(double squareSize) => <ImageSize>[ | ||||||
ImageSize.THUMB, | ||||||
ImageSize.SMALL, | ||||||
Comment on lines
+155
to
+156
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's OK with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I want to ditch them because I have experience in images and I remember that not all values are always populated, only 400 and FULL. {
"code": "3661344961326",
"errors": [],
"product": {
"images": {
"1": {
"sizes": {
"100": {
"h": 100,
"w": 75
},
"400": {
"h": 400,
"w": 300
},
"full": {
"h": 3264,
"w": 2448
}
},
"uploaded_t": 1428607891,
"uploader": "openfoodfacts-contributors"
},
"12": {
"sizes": {
"100": {
"h": 100,
"w": 99
},
"400": {
"h": 400,
"w": 396
},
"full": {
"h": 2475,
"w": 2448
}
},
"uploaded_t": 1550253015,
"uploader": "moon-rabbit"
}, And so on. That's why I recommend 400 or FULL:
|
||||||
ImageSize.DISPLAY | ||||||
].firstWhereOrNull( | ||||||
(ImageSize element) => squareSize <= int.parse(element.number), | ||||||
); | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,43 +11,20 @@ import 'package:smooth_app/resources/app_icons.dart'; | |
import 'package:smooth_app/themes/smooth_theme_colors.dart'; | ||
|
||
/// Displays a product image thumbnail with the upload date on top. | ||
class ProductImageWidget extends StatefulWidget { | ||
class ProductImageWidget extends StatelessWidget { | ||
const ProductImageWidget({ | ||
required this.productImage, | ||
required this.barcode, | ||
required this.squareSize, | ||
this.imageSize, | ||
}); | ||
|
||
final ProductImage productImage; | ||
final String barcode; | ||
final double squareSize; | ||
|
||
@override | ||
State<ProductImageWidget> createState() => _ProductImageWidgetState(); | ||
} | ||
|
||
class _ProductImageWidgetState extends State<ProductImageWidget> { | ||
@override | ||
void initState() { | ||
super.initState(); | ||
_loadImagePalette(); | ||
} | ||
|
||
Future<void> _loadImagePalette() async { | ||
final ColorScheme palette = await ColorScheme.fromImageProvider( | ||
provider: NetworkImage(widget.productImage.getUrl( | ||
widget.barcode, | ||
uriHelper: ProductQuery.uriProductHelper, | ||
))); | ||
|
||
setState(() { | ||
backgroundColor = palette.primaryContainer; | ||
darkBackground = backgroundColor!.computeLuminance() < 0.5; | ||
}); | ||
} | ||
|
||
Color? backgroundColor; | ||
bool? darkBackground; | ||
/// Allows to fetch the optimized version of the image | ||
final ImageSize? imageSize; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
|
@@ -57,20 +34,21 @@ class _ProductImageWidgetState extends State<ProductImageWidget> { | |
final DateFormat dateFormat = | ||
DateFormat.yMd(ProductQuery.getLanguage().offTag); | ||
|
||
darkBackground = darkBackground ?? true; | ||
|
||
final Widget image = SmoothImage( | ||
width: widget.squareSize, | ||
height: widget.squareSize, | ||
cacheHeight: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No It's a bit strange to say "you can force There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we have a square, but the server's photo may have a different ratio. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand the square effect. I don't know how relevant this cache option would be, performance-wise. I also fear that this cache option entail side-effects: what if I download a full image with that cache option for a thumbnail, and then display the full image on a full screen after a tap? From the docs, I assume that the cached image will be stored as resized, and then reused, which would render a pixelized image. At least, you could add a comment about why cacheHeight but not cacheWidth. |
||
(squareSize * MediaQuery.devicePixelRatioOf(context)).toInt(), | ||
width: squareSize, | ||
height: squareSize, | ||
imageProvider: NetworkImage( | ||
widget.productImage.getUrl( | ||
widget.barcode, | ||
productImage.getUrl( | ||
barcode, | ||
uriHelper: ProductQuery.uriProductHelper, | ||
imageSize: imageSize, | ||
), | ||
), | ||
rounded: false, | ||
); | ||
final DateTime? uploaded = widget.productImage.uploaded; | ||
final DateTime? uploaded = productImage.uploaded; | ||
if (uploaded == null) { | ||
return image; | ||
} | ||
|
@@ -85,7 +63,7 @@ class _ProductImageWidgetState extends State<ProductImageWidget> { | |
button: true, | ||
child: SmoothCard( | ||
padding: EdgeInsets.zero, | ||
color: backgroundColor ?? colors.primaryBlack, | ||
color: colors.primaryBlack, | ||
borderRadius: ANGULAR_BORDER_RADIUS, | ||
margin: EdgeInsets.zero, | ||
child: ClipRRect( | ||
|
@@ -108,11 +86,7 @@ class _ProductImageWidgetState extends State<ProductImageWidget> { | |
child: AutoSizeText( | ||
date, | ||
maxLines: 1, | ||
style: TextStyle( | ||
color: darkBackground! | ||
? Colors.white | ||
: colors.primaryDark, | ||
), | ||
style: const TextStyle(color: Colors.white), | ||
), | ||
), | ||
if (expired) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those
cache
parameters may be helpful regarding memory, but not network latency.Please consider implementing my suggestion about
ImageSize.DISPLAY
. That will dramatically help for memory too!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I will.
I think, I will also add all variants of
ImageSize
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good. Btw I don't think all variants are always implemented; I would focus on 400 and FULL only.