From 0b72aab64a25f0407e020dd09b0ec7902c71c0f1 Mon Sep 17 00:00:00 2001 From: Filip Krawczyk Date: Thu, 21 Oct 2021 14:40:28 +0200 Subject: [PATCH] transition to another image widget --- ios/Flutter/AppFrameworkInfo.plist | 2 +- ios/Podfile.lock | 17 +---- lib/pages/add_account.dart | 4 +- lib/pages/add_instance.dart | 4 +- lib/pages/community.dart | 4 +- lib/pages/home_tab.dart | 2 +- lib/pages/inbox.dart | 4 +- lib/pages/instance.dart | 6 +- lib/pages/manage_account.dart | 4 +- lib/pages/media_view.dart | 4 +- lib/widgets/avatar.dart | 4 +- lib/widgets/cached_network_image.dart | 68 ++++++++++++++++++ lib/widgets/markdown_text.dart | 4 +- lib/widgets/post.dart | 10 +-- lib/widgets/user_profile.dart | 6 +- pubspec.lock | 100 ++++++-------------------- pubspec.yaml | 2 +- 17 files changed, 121 insertions(+), 124 deletions(-) create mode 100644 lib/widgets/cached_network_image.dart diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 6b4c0f7..f2872cf 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 9.0 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 56e5c2a..7701645 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,8 +1,5 @@ PODS: - Flutter (1.0.0) - - FMDB (2.7.5): - - FMDB/standard (= 2.7.5) - - FMDB/standard (2.7.5) - image_picker (0.0.1): - Flutter - package_info_plus (0.4.5): @@ -13,9 +10,6 @@ PODS: - Flutter - shared_preferences (0.0.1): - Flutter - - sqflite (0.0.2): - - Flutter - - FMDB (>= 2.7.5) - url_launcher (0.0.1): - Flutter @@ -26,13 +20,8 @@ DEPENDENCIES: - path_provider (from `.symlinks/plugins/path_provider/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) - - sqflite (from `.symlinks/plugins/sqflite/ios`) - url_launcher (from `.symlinks/plugins/url_launcher/ios`) -SPEC REPOS: - trunk: - - FMDB - EXTERNAL SOURCES: Flutter: :path: Flutter @@ -46,22 +35,18 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/share_plus/ios" shared_preferences: :path: ".symlinks/plugins/shared_preferences/ios" - sqflite: - :path: ".symlinks/plugins/sqflite/ios" url_launcher: :path: ".symlinks/plugins/url_launcher/ios" SPEC CHECKSUMS: Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a - FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a image_picker: e06f7a68f000bd36f552c1847e33cda96ed31f1f package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d - sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c -COCOAPODS: 1.11.0 +COCOAPODS: 1.11.2 diff --git a/lib/pages/add_account.dart b/lib/pages/add_account.dart index 25822d3..beca259 100644 --- a/lib/pages/add_account.dart +++ b/lib/pages/add_account.dart @@ -1,4 +1,3 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:lemmy_api_client/v3.dart'; @@ -9,6 +8,7 @@ import '../hooks/delayed_loading.dart'; import '../hooks/stores.dart'; import '../l10n/l10n.dart'; import '../stores/config_store.dart'; +import '../widgets/cached_network_image.dart'; import '../widgets/fullscreenable_image.dart'; import '../widgets/radio_picker.dart'; import 'add_instance.dart'; @@ -96,7 +96,7 @@ class AddAccountPage extends HookWidget { url: icon.value!, child: CachedNetworkImage( imageUrl: icon.value!, - errorWidget: (_, __, ___) => const SizedBox.shrink(), + errorBuilder: (_, ___) => const SizedBox.shrink(), ), ), ), diff --git a/lib/pages/add_instance.dart b/lib/pages/add_instance.dart index 12a4637..7fdb8b6 100644 --- a/lib/pages/add_instance.dart +++ b/lib/pages/add_instance.dart @@ -1,4 +1,3 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:lemmy_api_client/v3.dart'; @@ -6,6 +5,7 @@ import 'package:lemmy_api_client/v3.dart'; import '../hooks/debounce.dart'; import '../hooks/stores.dart'; import '../util/cleanup_url.dart'; +import '../widgets/cached_network_image.dart'; import '../widgets/fullscreenable_image.dart'; /// A page that let's user add a new instance. Pops a url of the added instance @@ -76,7 +76,7 @@ class AddInstancePage extends HookWidget { url: icon.value!, child: CachedNetworkImage( imageUrl: icon.value!, - errorWidget: (_, __, ___) => const SizedBox.shrink(), + errorBuilder: (_, ___) => const SizedBox.shrink(), ), )) else if (isSite.value == false) diff --git a/lib/pages/community.dart b/lib/pages/community.dart index 2c4b981..fcbc965 100644 --- a/lib/pages/community.dart +++ b/lib/pages/community.dart @@ -1,4 +1,3 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -18,6 +17,7 @@ import '../util/more_icon.dart'; import '../util/share.dart'; import '../widgets/avatar.dart'; import '../widgets/bottom_modal.dart'; +import '../widgets/cached_network_image.dart'; import '../widgets/fullscreenable_image.dart'; import '../widgets/info_table_popup.dart'; import '../widgets/markdown_text.dart'; @@ -270,7 +270,7 @@ class _CommunityOverview extends StatelessWidget { url: community.community.banner!, child: CachedNetworkImage( imageUrl: community.community.banner!, - errorWidget: (_, __, ___) => const SizedBox.shrink(), + errorBuilder: (_, ___) => const SizedBox.shrink(), ), ), SafeArea( diff --git a/lib/pages/home_tab.dart b/lib/pages/home_tab.dart index 2334d38..039a1ac 100644 --- a/lib/pages/home_tab.dart +++ b/lib/pages/home_tab.dart @@ -1,6 +1,5 @@ import 'dart:math' show max; -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:lemmy_api_client/v3.dart'; @@ -11,6 +10,7 @@ import '../hooks/stores.dart'; import '../l10n/l10n.dart'; import '../util/goto.dart'; import '../widgets/bottom_modal.dart'; +import '../widgets/cached_network_image.dart'; import '../widgets/infinite_scroll.dart'; import '../widgets/sortable_infinite_list.dart'; import 'add_account.dart'; diff --git a/lib/pages/inbox.dart b/lib/pages/inbox.dart index b7fbdc7..ddb5e73 100644 --- a/lib/pages/inbox.dart +++ b/lib/pages/inbox.dart @@ -1,6 +1,5 @@ import 'dart:math' show pi; -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:lemmy_api_client/v3.dart'; @@ -16,6 +15,7 @@ import '../util/extensions/datetime.dart'; import '../util/goto.dart'; import '../util/more_icon.dart'; import '../widgets/bottom_modal.dart'; +import '../widgets/cached_network_image.dart'; import '../widgets/comment/comment.dart'; import '../widgets/infinite_scroll.dart'; import '../widgets/info_table_popup.dart'; @@ -307,7 +307,7 @@ class PrivateMessageTile extends HookWidget { ), ), ), - errorWidget: (_, __, ___) => const SizedBox.shrink(), + errorBuilder: (_, ___) => const SizedBox.shrink(), ), ), Text( diff --git a/lib/pages/instance.dart b/lib/pages/instance.dart index 1c86694..2d3c3fa 100644 --- a/lib/pages/instance.dart +++ b/lib/pages/instance.dart @@ -1,4 +1,3 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:lemmy_api_client/v3.dart'; @@ -14,6 +13,7 @@ import '../util/share.dart'; import '../util/text_color.dart'; import '../widgets/avatar.dart'; import '../widgets/bottom_modal.dart'; +import '../widgets/cached_network_image.dart'; import '../widgets/fullscreenable_image.dart'; import '../widgets/info_table_popup.dart'; import '../widgets/markdown_text.dart'; @@ -126,7 +126,7 @@ class InstancePage extends HookWidget { url: siteView.site.banner!, child: CachedNetworkImage( imageUrl: siteView.site.banner!, - errorWidget: (_, __, ___) => const SizedBox.shrink(), + errorBuilder: (_, ___) => const SizedBox.shrink(), ), ), SafeArea( @@ -143,7 +143,7 @@ class InstancePage extends HookWidget { width: 100, height: 100, imageUrl: siteView.site.icon!, - errorWidget: (_, __, ___) => + errorBuilder: (_, ___) => const Icon(Icons.warning), ), ), diff --git a/lib/pages/manage_account.dart b/lib/pages/manage_account.dart index 57a6809..3605418 100644 --- a/lib/pages/manage_account.dart +++ b/lib/pages/manage_account.dart @@ -1,4 +1,3 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:image_picker/image_picker.dart'; @@ -14,6 +13,7 @@ import '../util/more_icon.dart'; import '../util/pictrs.dart'; import '../widgets/bottom_modal.dart'; import '../widgets/bottom_safe.dart'; +import '../widgets/cached_network_image.dart'; import '../widgets/editor.dart'; /// Page for managing things like username, email, avatar etc @@ -506,7 +506,7 @@ class _ImagePicker extends HookWidget { if (url.value != null) CachedNetworkImage( imageUrl: url.value!, - errorWidget: (_, __, ___) => const Icon(Icons.error), + errorBuilder: (_, ___) => const Icon(Icons.error), ), ], ); diff --git a/lib/pages/media_view.dart b/lib/pages/media_view.dart index bdb417d..b735112 100644 --- a/lib/pages/media_view.dart +++ b/lib/pages/media_view.dart @@ -1,6 +1,6 @@ import 'dart:math' show max, min; -import 'package:cached_network_image/cached_network_image.dart'; +import 'package:extended_image/extended_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -144,7 +144,7 @@ class MediaViewPage extends HookWidget { : (_, __, ___) => showButtons.value = !showButtons.value, minScale: PhotoViewComputedScale.contained, initialScale: PhotoViewComputedScale.contained, - imageProvider: CachedNetworkImageProvider(url), + imageProvider: ExtendedNetworkImageProvider(url, cache: true), heroAttributes: PhotoViewHeroAttributes(tag: url), loadingBuilder: (context, event) => const Center(child: CircularProgressIndicator()), diff --git a/lib/widgets/avatar.dart b/lib/widgets/avatar.dart index e25ff82..d812c6b 100644 --- a/lib/widgets/avatar.dart +++ b/lib/widgets/avatar.dart @@ -1,8 +1,8 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import '../hooks/stores.dart'; +import 'cached_network_image.dart'; /// User's avatar. Respects the `showAvatars` setting from configStore /// If passed url is null, a blank box is displayed to prevent weird indents @@ -50,7 +50,7 @@ class Avatar extends HookWidget { width: radius * 2, imageUrl: imageUrl, fit: BoxFit.cover, - errorWidget: (_, __, ___) => blankWidget, + errorBuilder: (_, __) => blankWidget, ), ); } diff --git a/lib/widgets/cached_network_image.dart b/lib/widgets/cached_network_image.dart new file mode 100644 index 0000000..6886315 --- /dev/null +++ b/lib/widgets/cached_network_image.dart @@ -0,0 +1,68 @@ +import 'package:extended_image/extended_image.dart'; +import 'package:flutter/material.dart'; + +typedef ImageBuilder = Widget Function( + BuildContext context, ImageProvider imageProvider); + +typedef LoadingBuilder = Widget Function( + BuildContext context, ImageChunkEvent? progress); + +typedef ErrorBuilder = Widget Function( + BuildContext context, Object? lastException); + +extension Progress on ImageChunkEvent { + double? get progress { + if (expectedTotalBytes == null || + cumulativeBytesLoaded > expectedTotalBytes!) { + return null; + } + + return cumulativeBytesLoaded / expectedTotalBytes!; + } +} + +class CachedNetworkImage extends StatelessWidget { + final String imageUrl; + final double? height; + final double? width; + final BoxFit? fit; + final bool cache; + + final ErrorBuilder? errorBuilder; + final LoadingBuilder? loadingBuilder; + final ImageBuilder? imageBuilder; + + const CachedNetworkImage({ + required this.imageUrl, + this.errorBuilder, + this.loadingBuilder, + this.imageBuilder, + this.height, + this.width, + this.fit, + this.cache = true, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ExtendedImage.network( + imageUrl, + height: height, + width: width, + fit: fit, + cache: cache, + loadStateChanged: (state) { + switch (state.extendedImageLoadState) { + case LoadState.loading: + return loadingBuilder?.call(context, state.loadingProgress) ?? + SizedBox(height: height, width: width); + case LoadState.completed: + return imageBuilder?.call(context, state.imageProvider); + case LoadState.failed: + return errorBuilder?.call(context, state.lastException); + } + }, + ); + } +} diff --git a/lib/widgets/markdown_text.dart b/lib/widgets/markdown_text.dart index 23367ae..a0da202 100644 --- a/lib/widgets/markdown_text.dart +++ b/lib/widgets/markdown_text.dart @@ -1,11 +1,11 @@ import 'dart:io'; -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:markdown/markdown.dart' as md; import '../url_launcher.dart'; +import 'cached_network_image.dart'; import 'fullscreenable_image.dart'; /// A Markdown renderer with link/image handling @@ -52,7 +52,7 @@ class MarkdownText extends StatelessWidget { url: uri.toString(), child: CachedNetworkImage( imageUrl: uri.toString(), - errorWidget: (context, url, error) => Row( + errorBuilder: (context, error) => Row( children: [ const Icon(Icons.warning), Text("couldn't load image, ${error.toString()}") diff --git a/lib/widgets/post.dart b/lib/widgets/post.dart index d35a97a..dbabb9a 100644 --- a/lib/widgets/post.dart +++ b/lib/widgets/post.dart @@ -1,4 +1,3 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -23,6 +22,7 @@ import '../util/more_icon.dart'; import '../util/share.dart'; import 'avatar.dart'; import 'bottom_modal.dart'; +import 'cached_network_image.dart'; import 'fullscreenable_image.dart'; import 'info_table_popup.dart'; import 'markdown_text.dart'; @@ -309,7 +309,7 @@ class PostWidget extends HookWidget { width: 70, height: 70, fit: BoxFit.cover, - errorWidget: (context, url, error) => + errorBuilder: (context, error) => Text(error.toString()), ), ), @@ -397,9 +397,9 @@ class PostWidget extends HookWidget { url: post.post.url!, child: CachedNetworkImage( imageUrl: post.post.url!, - errorWidget: (_, __, ___) => const Icon(Icons.warning), - progressIndicatorBuilder: (context, url, progress) => - CircularProgressIndicator(value: progress.progress), + errorBuilder: (_, ___) => const Icon(Icons.warning), + loadingBuilder: (context, progress) => + CircularProgressIndicator(value: progress?.progress), ), ); } diff --git a/lib/widgets/user_profile.dart b/lib/widgets/user_profile.dart index 1f03ba8..7eb6c7d 100644 --- a/lib/widgets/user_profile.dart +++ b/lib/widgets/user_profile.dart @@ -1,4 +1,3 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:intl/intl.dart'; @@ -14,6 +13,7 @@ import '../util/extensions/datetime.dart'; import '../util/goto.dart'; import '../util/text_color.dart'; import 'avatar.dart'; +import 'cached_network_image.dart'; import 'fullscreenable_image.dart'; import 'markdown_text.dart'; import 'sortable_infinite_list.dart'; @@ -147,7 +147,7 @@ class _UserOverview extends HookWidget { url: userView.person.banner!, child: CachedNetworkImage( imageUrl: userView.person.banner!, - errorWidget: (_, __, ___) => const SizedBox.shrink(), + errorBuilder: (_, ___) => const SizedBox.shrink(), ), ) else @@ -208,7 +208,7 @@ class _UserOverview extends HookWidget { url: userView.person.avatar!, child: CachedNetworkImage( imageUrl: userView.person.avatar!, - errorWidget: (_, __, ___) => const SizedBox.shrink(), + errorBuilder: (_, ___) => const SizedBox.shrink(), ), ), ), diff --git a/pubspec.lock b/pubspec.lock index 604d757..9a5a53b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -99,27 +99,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "8.1.2" - cached_network_image: - dependency: "direct main" - description: - name: cached_network_image - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.0" - cached_network_image_platform_interface: - dependency: transitive - description: - name: cached_network_image_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - cached_network_image_web: - dependency: transitive - description: - name: cached_network_image_web - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" characters: dependency: transitive description: @@ -204,6 +183,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + extended_image: + dependency: "direct main" + description: + name: extended_image + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.2" + extended_image_library: + dependency: transitive + description: + name: extended_image_library + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" fake_async: dependency: transitive description: @@ -237,20 +230,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_blurhash: - dependency: transitive - description: - name: flutter_blurhash - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.0" - flutter_cache_manager: - dependency: transitive - description: - name: flutter_cache_manager - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.2" flutter_hooks: dependency: "direct main" description: @@ -357,6 +336,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.13.3" + http_client_helper: + dependency: transitive + description: + name: http_client_helper + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" http_multi_server: dependency: transitive description: @@ -525,13 +511,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" - octo_image: - dependency: transitive - description: - name: octo_image - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0+1" package_config: dependency: transitive description: @@ -695,13 +674,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" - rxdart: - dependency: transitive - description: - name: rxdart - url: "https://pub.dartlang.org" - source: hosted - version: "0.27.2" share_plus: dependency: "direct main" description: @@ -826,20 +798,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.1" - sqflite: - dependency: transitive - description: - name: sqflite - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0+4" - sqflite_common: - dependency: transitive - description: - name: sqflite_common - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1+1" stack_trace: dependency: transitive description: @@ -868,13 +826,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" - synchronized: - dependency: transitive - description: - name: synchronized - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" term_glyph: dependency: transitive description: @@ -952,13 +903,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.2" - uuid: - dependency: transitive - description: - name: uuid - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.4" vector_math: dependency: transitive description: @@ -1010,4 +954,4 @@ packages: version: "3.1.0" sdks: dart: ">=2.14.0 <3.0.0" - flutter: ">=2.0.0" + flutter: ">=2.5.0" diff --git a/pubspec.yaml b/pubspec.yaml index 35357a5..cf4e6b1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,7 +30,6 @@ dependencies: ref: bugfix/flutter-2.5-update markdown: ^4.0.0 flutter_markdown: ^0.6.1 - cached_network_image: ^3.0.0 modal_bottom_sheet: ^2.0.0 # native @@ -65,6 +64,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 + extended_image: ^5.1.2 dev_dependencies: flutter_test: