From 7c795a1a88b5e23983ddbc705187a06a82e119c6 Mon Sep 17 00:00:00 2001 From: Micah Morrison Date: Mon, 22 Jan 2024 11:53:54 -0500 Subject: [PATCH] Fix issue with advanced image preview --- lib/core/models/pictr_media_extension.dart | 2 +- lib/post/utils/post.dart | 6 +- lib/shared/image_viewer.dart | 16 ++++-- lib/utils/image.dart | 66 +++++++++++++--------- 4 files changed, 54 insertions(+), 36 deletions(-) diff --git a/lib/core/models/pictr_media_extension.dart b/lib/core/models/pictr_media_extension.dart index 05185e686..989e1d883 100644 --- a/lib/core/models/pictr_media_extension.dart +++ b/lib/core/models/pictr_media_extension.dart @@ -20,7 +20,7 @@ abstract class PictrsMediaExtension { try { if (url.contains("/pictrs/image/")) { MediaType mediaType = MediaType.image; - Size result = await retrieveImageDimensions(url); + Size result = await retrieveImageDimensions(imageUrl: url); Size size = MediaExtension.getScaledMediaSize(width: result.width, height: result.height); mediaList.add(Media(mediaUrl: url, originalUrl: url, width: size.width, height: size.height, mediaType: mediaType)); diff --git a/lib/post/utils/post.dart b/lib/post/utils/post.dart index 20c26ca27..c8fa3ba30 100644 --- a/lib/post/utils/post.dart +++ b/lib/post/utils/post.dart @@ -133,7 +133,7 @@ Future parsePostView(PostView postView, bool fetchImageDimensions MediaType mediaType = MediaType.image; if (fetchImageDimensions) { - Size result = await retrieveImageDimensions(url); + Size result = await retrieveImageDimensions(imageUrl: url); Size size = MediaExtension.getScaledMediaSize(width: result.width, height: result.height, offset: edgeToEdgeImages ? 0 : 24, tabletMode: tabletMode); media.add(Media(mediaUrl: url, originalUrl: url, width: size.width, height: size.height, mediaType: mediaType)); } else { @@ -147,7 +147,7 @@ Future parsePostView(PostView postView, bool fetchImageDimensions if (fetchImageDimensions) { if (postView.post.thumbnailUrl?.isNotEmpty == true) { try { - Size result = await retrieveImageDimensions(postView.post.thumbnailUrl!); + Size result = await retrieveImageDimensions(imageUrl: postView.post.thumbnailUrl!); Size size = MediaExtension.getScaledMediaSize(width: result.width, height: result.height, offset: edgeToEdgeImages ? 0 : 24, tabletMode: tabletMode); media.add(Media( mediaUrl: postView.post.thumbnailUrl!, @@ -166,7 +166,7 @@ Future parsePostView(PostView postView, bool fetchImageDimensions LinkInfo linkInfo = await getLinkInfo(url); if (linkInfo.imageURL != null && linkInfo.imageURL!.isNotEmpty) { - Size result = await retrieveImageDimensions(linkInfo.imageURL!); + Size result = await retrieveImageDimensions(imageUrl: linkInfo.imageURL!); int mediaHeight = result.height.toInt(); int mediaWidth = result.width.toInt(); diff --git a/lib/shared/image_viewer.dart b/lib/shared/image_viewer.dart index 7b37c5af5..7754fe747 100644 --- a/lib/shared/image_viewer.dart +++ b/lib/shared/image_viewer.dart @@ -111,8 +111,8 @@ class _ImageViewerState extends State with TickerProviderStateMixin ); } - Future getImageSize(String imageUrl, context) async { - Size decodedImage = await retrieveImageDimensions(imageUrl); + Future getImageSize() async { + Size decodedImage = await retrieveImageDimensions(imageUrl: widget.url, imageBytes: widget.bytes); setState(() { imageWidth = decodedImage.width; @@ -127,7 +127,7 @@ class _ImageViewerState extends State with TickerProviderStateMixin void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { - getImageSize(widget.url!, context); + getImageSize(); }); } @@ -347,8 +347,14 @@ class _ImageViewerState extends State with TickerProviderStateMixin ), ), ) - : const Center( - child: CircularProgressIndicator(), + : Center( + child: SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + color: Colors.white.withOpacity(0.90), + ), + ), )), ), AnimatedOpacity( diff --git a/lib/utils/image.dart b/lib/utils/image.dart index 5df24a793..d9bdea389 100644 --- a/lib/utils/image.dart +++ b/lib/utils/image.dart @@ -59,35 +59,47 @@ Future isImageUriSvg(Uri? imageUri) async { } } -Future retrieveImageDimensions(String imageUrl) async { - try { - bool isImage = isImageUrl(imageUrl); - if (!isImage) throw Exception('The URL provided was not an image'); - - final uri = Uri.parse(imageUrl); - final path = uri.path.toLowerCase(); - - // We'll just retrieve the first part of the image - final rangeResponse = await http.get( - uri, - headers: {'Range': 'bytes=0-1000'}, - ); +/// Retrieves the size of the given image. +/// Must provide either [imageUrl] or [imageBytes]. +Future retrieveImageDimensions({String? imageUrl, Uint8List? imageBytes}) async { + assert(imageUrl != null || imageBytes != null); - // Read the response body as bytes - final imageData = rangeResponse.bodyBytes; - - // Get the image dimensions - if (path.endsWith('jpg') || path.endsWith('jpeg')) { - return getJPEGImageDimensions(imageData); - } - if (path.endsWith('gif')) { - return getGIFImageDimensions(imageData); - } - if (path.endsWith('png')) { - return getPNGImageDimensions(imageData); + try { + if (imageBytes != null) { + // We assume that byte-based images, which are only generated in-app by Thunder + // are all PNGs. + return getPNGImageDimensions(imageBytes); } - if (path.endsWith('webp')) { - return getWEBPImageDimensions(imageData); + // We know imageUrl is not null here due to the assertion. + else { + bool isImage = isImageUrl(imageUrl!); + if (!isImage) throw Exception('The URL provided was not an image'); + + final uri = Uri.parse(imageUrl); + final path = uri.path.toLowerCase(); + + // We'll just retrieve the first part of the image + final rangeResponse = await http.get( + uri, + headers: {'Range': 'bytes=0-1000'}, + ); + + // Read the response body as bytes + final imageData = rangeResponse.bodyBytes; + + // Get the image dimensions + if (path.endsWith('jpg') || path.endsWith('jpeg')) { + return getJPEGImageDimensions(imageData); + } + if (path.endsWith('gif')) { + return getGIFImageDimensions(imageData); + } + if (path.endsWith('png')) { + return getPNGImageDimensions(imageData); + } + if (path.endsWith('webp')) { + return getWEBPImageDimensions(imageData); + } } } catch (e) { throw Exception('Failed to retrieve image dimensions');