⚡ Improve image loading
This commit is contained in:
		| @@ -65,8 +65,9 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|               } | ||||
|                   .toDouble(); | ||||
|  | ||||
|           return Padding( | ||||
|           return Container( | ||||
|             padding: widget.padding ?? EdgeInsets.zero, | ||||
|             constraints: BoxConstraints(maxHeight: constraints.maxHeight), | ||||
|             child: Container( | ||||
|               constraints: constraints, | ||||
|               width: double.infinity, | ||||
| @@ -132,7 +133,7 @@ class _AttachmentListState extends State<AttachmentList> { | ||||
|                             child: AttachmentItem( | ||||
|                               data: ele, | ||||
|                               heroTag: heroTags[idx], | ||||
|                               fit: widget.fit, | ||||
|                               fit: BoxFit.cover, | ||||
|                             ), | ||||
|                           ), | ||||
|                           onTap: () { | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import 'package:cached_network_image/cached_network_image.dart'; | ||||
| import 'package:extended_image/extended_image.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| @@ -7,7 +7,6 @@ import 'package:styled_widget/styled_widget.dart'; | ||||
| import 'package:flutter_animate/flutter_animate.dart'; | ||||
|  | ||||
| // Keep this import to make the web image render work | ||||
| import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart'; | ||||
| import 'package:surface/providers/config.dart'; | ||||
|  | ||||
| class UniversalImage extends StatelessWidget { | ||||
| @@ -34,64 +33,54 @@ class UniversalImage extends StatelessWidget { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final devicePixelRatio = MediaQuery.of(context).devicePixelRatio; | ||||
|     final double? resizeHeight = cacheHeight != null ? (cacheHeight! * devicePixelRatio) : null; | ||||
|     final double? resizeWidth = cacheWidth != null ? (cacheWidth! * devicePixelRatio) : null; | ||||
|     final quality = filterQuality ?? context.read<ConfigProvider>().imageQuality; | ||||
|  | ||||
|     return Image( | ||||
|       filterQuality: filterQuality ?? context.read<ConfigProvider>().imageQuality, | ||||
|       image: kIsWeb | ||||
|           ? UniversalImage.provider(url) | ||||
|           : ResizeImage( | ||||
|               UniversalImage.provider(url), | ||||
|               width: resizeWidth?.round(), | ||||
|               height: resizeHeight?.round(), | ||||
|               policy: ResizeImagePolicy.fit, | ||||
|             ), | ||||
|     return ExtendedImage.network( | ||||
|       url, | ||||
|       width: width, | ||||
|       height: height, | ||||
|       fit: fit, | ||||
|       loadingBuilder: noProgressIndicator | ||||
|           ? null | ||||
|           : (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) { | ||||
|               if (loadingProgress == null) return child; | ||||
|               return Center( | ||||
|                 child: TweenAnimationBuilder( | ||||
|                   tween: Tween( | ||||
|                     begin: 0, | ||||
|                     end: loadingProgress.expectedTotalBytes != null | ||||
|                         ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! | ||||
|                         : 0, | ||||
|       cache: true, | ||||
|       compressionRatio: kIsWeb ? 1 : switch(quality) { | ||||
|         FilterQuality.high => 1, | ||||
|         FilterQuality.medium => 0.75, | ||||
|         FilterQuality.low => 0.5, | ||||
|         FilterQuality.none => 0.25, | ||||
|       }, | ||||
|       filterQuality: quality, | ||||
|       enableLoadState: true, | ||||
|       retries: 3, | ||||
|       loadStateChanged: (ExtendedImageState state) { | ||||
|         if (state.extendedImageLoadState == LoadState.completed) { | ||||
|           return state.completedWidget; | ||||
|         } else if (state.extendedImageLoadState == LoadState.failed) { | ||||
|           return Material( | ||||
|             color: Theme.of(context).colorScheme.surface, | ||||
|             child: Container( | ||||
|               constraints: const BoxConstraints(maxWidth: 280), | ||||
|               child: Column( | ||||
|                 mainAxisAlignment: MainAxisAlignment.center, | ||||
|                 children: [ | ||||
|                   AnimateWidgetExtensions(Icon(Symbols.close, size: 24)) | ||||
|                       .animate(onPlay: (e) => e.repeat(reverse: true)) | ||||
|                       .fade(duration: 500.ms), | ||||
|                   Text( | ||||
|                     state.lastException.toString(), | ||||
|                     textAlign: TextAlign.center, | ||||
|                   ), | ||||
|                   duration: const Duration(milliseconds: 300), | ||||
|                   builder: (context, value, _) => CircularProgressIndicator( | ||||
|                     value: loadingProgress.expectedTotalBytes != null ? value.toDouble() : null, | ||||
|                   ), | ||||
|                 ), | ||||
|               ); | ||||
|             }, | ||||
|       errorBuilder: noErrorWidget | ||||
|           ? null | ||||
|           : (context, error, stackTrace) { | ||||
|               return Material( | ||||
|                 color: Theme.of(context).colorScheme.surface, | ||||
|                 child: Container( | ||||
|                   constraints: const BoxConstraints(maxWidth: 280), | ||||
|                   child: Column( | ||||
|                     mainAxisAlignment: MainAxisAlignment.center, | ||||
|                     children: [ | ||||
|                       AnimateWidgetExtensions(Icon(Symbols.close, size: 24)) | ||||
|                           .animate(onPlay: (e) => e.repeat(reverse: true)) | ||||
|                           .fade(duration: 500.ms), | ||||
|                       Text( | ||||
|                         error.toString(), | ||||
|                         textAlign: TextAlign.center, | ||||
|                       ), | ||||
|                     ], | ||||
|                   ).center(), | ||||
|                 ), | ||||
|               ); | ||||
|             }, | ||||
|                 ], | ||||
|               ).center(), | ||||
|             ), | ||||
|           ); | ||||
|         } | ||||
|         return Center( | ||||
|           child: CircularProgressIndicator( | ||||
|             value: state.loadingProgress != null | ||||
|                 ? state.loadingProgress!.cumulativeBytesLoaded / state.loadingProgress!.expectedTotalBytes! | ||||
|                 : null, | ||||
|           ), | ||||
|         ); | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| @@ -99,9 +88,10 @@ class UniversalImage extends StatelessWidget { | ||||
|     // This place used to use network image or cached network image depending on the platform. | ||||
|     // But now the cached network image is working on every platform. | ||||
|     // So we just use it now. | ||||
|     return CachedNetworkImageProvider( | ||||
|     return ExtendedNetworkImageProvider( | ||||
|       url, | ||||
|       imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet, | ||||
|       cache: true, | ||||
|       retries: 3, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -26,7 +26,6 @@ import path_provider_foundation | ||||
| import screen_brightness_macos | ||||
| import share_plus | ||||
| import shared_preferences_foundation | ||||
| import sqflite_darwin | ||||
| import url_launcher_macos | ||||
| import video_compress | ||||
| import wakelock_plus | ||||
| @@ -53,7 +52,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { | ||||
|   ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin")) | ||||
|   SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) | ||||
|   SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) | ||||
|   SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) | ||||
|   UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) | ||||
|   VideoCompressPlugin.register(with: registry.registrar(forPlugin: "VideoCompressPlugin")) | ||||
|   WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) | ||||
|   | ||||
							
								
								
									
										112
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								pubspec.lock
									
									
									
									
									
								
							| @@ -182,30 +182,6 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "8.9.3" | ||||
|   cached_network_image: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: cached_network_image | ||||
|       sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.4.1" | ||||
|   cached_network_image_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: cached_network_image_platform_interface | ||||
|       sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "4.1.1" | ||||
|   cached_network_image_web: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: cached_network_image_web | ||||
|       sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.3.1" | ||||
|   cassowary: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -454,6 +430,22 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.0.7" | ||||
|   extended_image: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: extended_image | ||||
|       sha256: "93890a88d89ce017789f6c031c32ad8d2c685f1a5c25c169550746d973ca5e44" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "9.0.9" | ||||
|   extended_image_library: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: extended_image_library | ||||
|       sha256: "9a94ec9314aa206cfa35f16145c3cd6e2c924badcc670eaaca8a3a8063a68cd7" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "4.0.5" | ||||
|   fading_edge_scrollview: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -643,14 +635,6 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.2.2" | ||||
|   flutter_cache_manager: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: flutter_cache_manager | ||||
|       sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.4.1" | ||||
|   flutter_colorpicker: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
| @@ -890,6 +874,14 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.2.2" | ||||
|   http_client_helper: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: http_client_helper | ||||
|       sha256: "8a9127650734da86b5c73760de2b404494c968a3fd55602045ffec789dac3cb1" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.0.0" | ||||
|   http_multi_server: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -1250,14 +1242,6 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.5.0" | ||||
|   octo_image: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: octo_image | ||||
|       sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.1.0" | ||||
|   package_config: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -1546,14 +1530,6 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.5.1" | ||||
|   rxdart: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: rxdart | ||||
|       sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.28.0" | ||||
|   safe_local_storage: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @@ -1767,46 +1743,6 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "7.0.0" | ||||
|   sqflite: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: sqflite | ||||
|       sha256: "2d7299468485dca85efeeadf5d38986909c5eb0cd71fd3db2c2f000e6c9454bb" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.4.1" | ||||
|   sqflite_android: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: sqflite_android | ||||
|       sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.4.0" | ||||
|   sqflite_common: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: sqflite_common | ||||
|       sha256: "761b9740ecbd4d3e66b8916d784e581861fd3c3553eda85e167bc49fdb68f709" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.5.4+6" | ||||
|   sqflite_darwin: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: sqflite_darwin | ||||
|       sha256: "96a698e2bc82bd770a4d6aab00b42396a7c63d9e33513a56945cbccb594c2474" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.4.1" | ||||
|   sqflite_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: sqflite_platform_interface | ||||
|       sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.4.0" | ||||
|   stack_trace: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|   | ||||
| @@ -53,7 +53,6 @@ dependencies: | ||||
|   markdown: ^7.2.2 | ||||
|   flutter_markdown: ^0.7.4+1 | ||||
|   url_launcher: ^6.3.1 | ||||
|   cached_network_image: ^3.4.1 | ||||
|   flutter_animate: ^4.5.0 | ||||
|   syntax_highlight: ^0.4.0 | ||||
|   google_fonts: ^6.2.1 | ||||
| @@ -116,6 +115,7 @@ dependencies: | ||||
|   flutter_webrtc: ^0.12.5+hotfix.1 | ||||
|   slide_countdown: ^2.0.2 | ||||
|   video_compress: ^3.1.3 | ||||
|   extended_image: ^9.0.9 | ||||
|  | ||||
| dev_dependencies: | ||||
|   flutter_test: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user