From 7805efa81be2f04954bcfd104848603ec292d286 Mon Sep 17 00:00:00 2001
From: humblerookie <1428864+humblerookie@users.noreply.github.com>
Date: Sun, 1 Aug 2021 09:47:32 +0530
Subject: [PATCH] feat(null-safety): migrate to null safety
---
CHANGELOG.md | 17 ++--
example/ios/Podfile | 79 ++++--------------
example/ios/Podfile.lock | 30 +++----
example/ios/Runner.xcodeproj/project.pbxproj | 19 +++++
.../contents.xcworkspacedata | 2 +-
example/lib/main.dart | 6 +-
example/pubspec.lock | 56 ++++++-------
example/pubspec.yaml | 8 +-
.../cache/default_image_cache_manager.dart | 4 +-
lib/src/cache/image_cache_manager.dart | 54 ++++++++++---
.../image_provider/_image_provider_io.dart | 21 +++--
.../image_provider/_image_provider_web.dart | 26 +++---
.../multi_image_stream_completer.dart | 51 ++++++------
.../optimized_cached_image_provider.dart | 26 +++---
lib/src/oci_widget.dart | 81 +++++++++----------
lib/src/transformer/image_transformer.dart | 15 ++--
pubspec.yaml | 4 +-
17 files changed, 243 insertions(+), 256 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3581d0b..6176d82 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,15 @@
+## 3.0.0
+
+* Null safety and interim gif support.
+
## 2.0.2-alpha
* Limited gif support. Gifs are compressed into webp and rendered as of now.
## 2.0.1
-* Update to null safety package dependencies. OCI still needs to migrate code to respect null safety. Additionally fix issue with hero widgets
+* Update to null safety package dependencies. OCI still needs to migrate code to respect null safety. Additionally fix
+ issue with hero widgets
## 2.0.0
@@ -28,7 +33,8 @@
## 1.0.0-beta
-* Prevent unnecessary downloads from happening by caching the image from the original url and resizing it for different sizes.
+* Prevent unnecessary downloads from happening by caching the image from the original url and resizing it for different
+ sizes.
## 0.1.15
@@ -62,25 +68,24 @@
* Fix dependency version breaking change in flutter cache library.
-
## 0.1.7
-
* Add style fixes
## 0.1.6
-* Add experimental support for streamed downloading via `useHttpStream` flag which further
-reduces the memory footprint.
+* Add experimental support for streamed downloading via `useHttpStream` flag which further reduces the memory footprint.
## 0.1.5
* Minor lint issues and formatting patched.
## 0.1.4
+
* Fixed issue faced while specifying custom width and height.
## 0.1.3
+
* Readme updated.
## 0.1.2
diff --git a/example/ios/Podfile b/example/ios/Podfile
index b30a428..1e8c3c9 100644
--- a/example/ios/Podfile
+++ b/example/ios/Podfile
@@ -10,81 +10,32 @@ project 'Runner', {
'Release' => :release,
}
-def parse_KV_file(file, separator='=')
- file_abs_path = File.expand_path(file)
- if !File.exists? file_abs_path
- return [];
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
- generated_key_values = {}
- skip_line_start_symbols = ["#", "/"]
- File.foreach(file_abs_path) do |line|
- next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
- plugin = line.split(pattern=separator)
- if plugin.length == 2
- podname = plugin[0].strip()
- path = plugin[1].strip()
- podpath = File.expand_path("#{path}", file_abs_path)
- generated_key_values[podname] = podpath
- else
- puts "Invalid plugin specification: #{line}"
- end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
end
- generated_key_values
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_ios_podfile_setup
+
target 'Runner' do
use_frameworks!
use_modular_headers!
-
- # Flutter Pod
- copied_flutter_dir = File.join(__dir__, 'Flutter')
- copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
- copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
- unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
- # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
- # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
- # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
-
- generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
- unless File.exist?(generated_xcode_build_settings_path)
- raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
- end
- generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
- cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
-
- unless File.exist?(copied_framework_path)
- FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
- end
- unless File.exist?(copied_podspec_path)
- FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
- end
- end
-
- # Keep pod path relative so it can be checked into Podfile.lock.
- pod 'Flutter', :path => 'Flutter'
-
- # Plugin Pods
-
- # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
- # referring to absolute paths on developers' machines.
- system('rm -rf .symlinks')
- system('mkdir -p .symlinks/plugins')
- plugin_pods = parse_KV_file('../.flutter-plugins')
- plugin_pods.each do |name, path|
- symlink = File.join('.symlinks', 'plugins', name)
- File.symlink(path, symlink)
- pod name, :path => File.join(symlink, 'ios')
- end
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
-# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
-install! 'cocoapods', :disable_input_output_paths => true
-
post_install do |installer|
installer.pods_project.targets.each do |target|
- target.build_configurations.each do |config|
- config.build_settings['ENABLE_BITCODE'] = 'NO'
- end
+ flutter_additional_ios_build_settings(target)
end
end
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index fd3b40f..d126ca5 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -21,25 +21,22 @@ PODS:
- Mantle/extobjc (2.1.1)
- path_provider (0.0.1):
- Flutter
- - path_provider_linux (0.0.1):
- - Flutter
- - path_provider_macos (0.0.1):
- - Flutter
- SDWebImage/Core (5.5.2)
- SDWebImageWebPCoder (0.5.0):
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.5)
- - sqflite (0.0.1):
+ - sqflite (0.0.2):
+ - Flutter
+ - FMDB (>= 2.7.5)
+ - url_launcher (0.0.1):
- Flutter
- - FMDB (~> 2.7.2)
DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_image_compress (from `.symlinks/plugins/flutter_image_compress/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- - path_provider_linux (from `.symlinks/plugins/path_provider_linux/ios`)
- - path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
+ - url_launcher (from `.symlinks/plugins/url_launcher/ios`)
SPEC REPOS:
trunk:
@@ -56,26 +53,23 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_image_compress/ios"
path_provider:
:path: ".symlinks/plugins/path_provider/ios"
- path_provider_linux:
- :path: ".symlinks/plugins/path_provider_linux/ios"
- path_provider_macos:
- :path: ".symlinks/plugins/path_provider_macos/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
+ url_launcher:
+ :path: ".symlinks/plugins/url_launcher/ios"
SPEC CHECKSUMS:
- Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
+ Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
flutter_image_compress: 082f8daaf6c1b0c9fe798251c750ef0ecd98d7ae
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3
Mantle: 35238ae6f2e2b2d474fa7b67fee82a59fea71915
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
- path_provider_linux: 4d630dc393e1f20364f3e3b4a2ff41d9674a84e4
- path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0
SDWebImage: 4d5c027c935438f341ed33dbac53ff9f479922ca
SDWebImageWebPCoder: e7ae855f058e3dcae99696920b6a5d134e9dcddf
- sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0
+ sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
+ url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
-PODFILE CHECKSUM: 1b66dae606f75376c5f2135a8290850eeb09ae83
+PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
-COCOAPODS: 1.9.1
+COCOAPODS: 1.10.1
diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj
index babb62a..9e89b83 100644
--- a/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/example/ios/Runner.xcodeproj/project.pbxproj
@@ -240,9 +240,28 @@
files = (
);
inputPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
+ "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
+ "${BUILT_PRODUCTS_DIR}/Mantle/Mantle.framework",
+ "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework",
+ "${BUILT_PRODUCTS_DIR}/SDWebImageWebPCoder/SDWebImageWebPCoder.framework",
+ "${BUILT_PRODUCTS_DIR}/flutter_image_compress/flutter_image_compress.framework",
+ "${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework",
+ "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
+ "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
+ "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Mantle.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImageWebPCoder.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_image_compress.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
index 1d526a1..919434a 100644
--- a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -2,6 +2,6 @@
+ location = "self:">
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 23463a8..912fbc5 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -74,18 +74,18 @@ class HumblerookiePluginExample extends StatelessWidget {
1,
);
}
- return MaterialColor(color.value, swatch);
+ return MaterialColor(color.value, swatch as Map);
}
}
/// A Flutter example demonstrating how the [pluginName] plugin could be used
class AppHome extends StatefulWidget {
/// Constructs the [AppHome] class
- AppHome({Key key, this.title}) : super(key: key);
+ AppHome({Key? key, this.title}) : super(key: key);
/// The [title] of the application, which is shown in the application's
/// title bar.
- final String title;
+ final String? title;
@override
_AppHomeState createState() => _AppHomeState();
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 2ffbc26..b6330aa 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -14,7 +14,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.5.0"
+ version: "2.6.1"
boolean_selector:
dependency: transitive
description:
@@ -56,14 +56,14 @@ packages:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.0"
+ version: "3.0.1"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
url: "https://pub.dartlang.org"
source: hosted
- version: "0.1.3"
+ version: "1.0.3"
fake_async:
dependency: transitive
description:
@@ -77,14 +77,14 @@ packages:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.0"
+ version: "1.1.2"
file:
dependency: "direct main"
description:
name: file
url: "https://pub.dartlang.org"
source: hosted
- version: "6.1.0"
+ version: "6.1.2"
flutter:
dependency: "direct main"
description: flutter
@@ -103,7 +103,7 @@ packages:
name: flutter_cache_manager
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.0"
+ version: "3.1.2"
flutter_image_compress:
dependency: transitive
description:
@@ -127,7 +127,7 @@ packages:
name: http
url: "https://pub.dartlang.org"
source: hosted
- version: "0.13.1"
+ version: "0.13.3"
http_parser:
dependency: transitive
description:
@@ -169,7 +169,7 @@ packages:
name: octo_image
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.0"
+ version: "1.0.0+1"
optimized_cached_image:
dependency: "direct main"
description:
@@ -190,7 +190,7 @@ packages:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.1"
+ version: "2.0.2"
path_provider_linux:
dependency: transitive
description:
@@ -211,28 +211,28 @@ packages:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
+ version: "2.0.1"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
+ version: "2.0.1"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.dartlang.org"
source: hosted
- version: "1.11.0"
+ version: "1.11.1"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
- version: "4.0.2"
+ version: "4.1.0"
platform:
dependency: transitive
description:
@@ -246,21 +246,21 @@ packages:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.2"
+ version: "2.0.1"
process:
dependency: transitive
description:
name: process
url: "https://pub.dartlang.org"
source: hosted
- version: "4.1.0"
+ version: "4.2.1"
rxdart:
dependency: transitive
description:
name: rxdart
url: "https://pub.dartlang.org"
source: hosted
- version: "0.26.0"
+ version: "0.27.1"
sky_engine:
dependency: transitive
description: flutter
@@ -272,7 +272,7 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.0"
+ version: "1.8.1"
sprintf:
dependency: transitive
description:
@@ -335,7 +335,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.19"
+ version: "0.3.0"
typed_data:
dependency: transitive
description:
@@ -349,49 +349,49 @@ packages:
name: url_launcher
url: "https://pub.dartlang.org"
source: hosted
- version: "5.7.10"
+ version: "6.0.9"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
url: "https://pub.dartlang.org"
source: hosted
- version: "0.0.1+4"
+ version: "2.0.0"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
url: "https://pub.dartlang.org"
source: hosted
- version: "0.0.1+9"
+ version: "2.0.0"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.9"
+ version: "2.0.4"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
url: "https://pub.dartlang.org"
source: hosted
- version: "0.1.5+3"
+ version: "2.0.1"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
url: "https://pub.dartlang.org"
source: hosted
- version: "0.0.1+3"
+ version: "2.0.0"
uuid:
dependency: transitive
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.3"
+ version: "3.0.4"
vector_math:
dependency: transitive
description:
@@ -405,7 +405,7 @@ packages:
name: win32
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
+ version: "2.2.5"
xdg_directories:
dependency: transitive
description:
@@ -419,7 +419,7 @@ packages:
name: xml
url: "https://pub.dartlang.org"
source: hosted
- version: "5.0.2"
+ version: "5.1.2"
sdks:
- dart: ">=2.12.0 <3.0.0"
+ dart: ">=2.13.0 <3.0.0"
flutter: ">=2.0.0"
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index f4d3050..d48d38a 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -3,7 +3,7 @@ description: Demonstrates how to use the optimized_cached_image plugin.
publish_to: 'none'
environment:
- sdk: ">=2.1.0 <3.0.0"
+ sdk: '>=2.12.0 <3.0.0'
dependencies:
flutter:
@@ -11,11 +11,11 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
- cupertino_icons: ^0.1.2
- url_launcher: ^5.4.11
+ cupertino_icons: ^1.0.3
+ url_launcher: ^6.0.9
optimized_cached_image:
path: ../
- file: ^6.1.0
+ file: ^6.1.2
dev_dependencies:
flutter_test:
diff --git a/lib/src/cache/default_image_cache_manager.dart b/lib/src/cache/default_image_cache_manager.dart
index 6f5b03d..4921bc6 100644
--- a/lib/src/cache/default_image_cache_manager.dart
+++ b/lib/src/cache/default_image_cache_manager.dart
@@ -7,10 +7,10 @@ import 'package:optimized_cached_image/src/cache/image_cache_manager.dart';
class DefaultImageCacheManager extends CacheManager with OicImageCacheManager {
static const key = 'libCachedImageData';
- static DefaultImageCacheManager _instance;
+ static DefaultImageCacheManager? _instance;
factory DefaultImageCacheManager() {
_instance ??= DefaultImageCacheManager._();
- return _instance;
+ return _instance!;
}
DefaultImageCacheManager._() : super(Config(key));
}
diff --git a/lib/src/cache/image_cache_manager.dart b/lib/src/cache/image_cache_manager.dart
index 34712e0..bd9809c 100644
--- a/lib/src/cache/image_cache_manager.dart
+++ b/lib/src/cache/image_cache_manager.dart
@@ -1,7 +1,11 @@
+import 'dart:async';
import 'dart:math';
+import 'package:flutter/widgets.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:image/image.dart';
+import 'package:file/file.dart';
import '../transformer/image_transformer.dart';
+import 'dart:ui' as ui;
const supportedFileNames = ['jpg', 'jpeg', 'png', 'tga', 'gif', 'cur', 'ico'];
mixin OicImageCacheManager on BaseCacheManager {
@@ -19,11 +23,11 @@ mixin OicImageCacheManager on BaseCacheManager {
Stream getImageFile(
String url, {
- String key,
- Map headers,
- bool withProgress,
- int maxHeight,
- int maxWidth,
+ String? key,
+ Map? headers,
+ bool withProgress = false,
+ int? maxHeight,
+ int? maxWidth,
}) async* {
if (maxHeight == null && maxWidth == null) {
yield* getFileStream(url,
@@ -55,7 +59,7 @@ mixin OicImageCacheManager on BaseCacheManager {
maxHeight: maxHeight,
);
}
- yield* _runningResizes[resizedKey];
+ yield* _runningResizes[resizedKey]!;
_runningResizes.remove(resizedKey);
}
@@ -63,8 +67,8 @@ mixin OicImageCacheManager on BaseCacheManager {
Future _resizeImageFile(
FileInfo originalFile,
String key,
- int maxWidth,
- int maxHeight,
+ int? maxWidth,
+ int? maxHeight,
) async {
var originalFileName = originalFile.file.path;
var fileExtension = originalFileName.split('.').last;
@@ -72,7 +76,15 @@ mixin OicImageCacheManager on BaseCacheManager {
return originalFile;
}
- var image = decodeImage(await originalFile.file.readAsBytes());
+ var image = await _decodeImage(originalFile.file);
+ var shouldResize = maxWidth != null
+ ? image.width > maxWidth
+ : false || maxHeight != null
+ ? image.height > maxHeight
+ : false;
+
+ if (!shouldResize) return originalFile;
+
if (maxWidth != null && maxHeight != null) {
var resizeFactorWidth = image.width / maxWidth;
var resizeFactorHeight = image.height / maxHeight;
@@ -106,10 +118,10 @@ mixin OicImageCacheManager on BaseCacheManager {
String url,
String originalKey,
String resizedKey,
- Map headers,
+ Map? headers,
bool withProgress, {
- int maxWidth,
- int maxHeight,
+ int? maxWidth,
+ int? maxHeight,
}) async* {
await for (var response in getFileStream(
url,
@@ -131,3 +143,21 @@ mixin OicImageCacheManager on BaseCacheManager {
}
}
}
+
+Future _decodeImage(File file,
+ {int? width, int? height, bool allowUpscaling = false}) {
+ var shouldResize = width != null || height != null;
+ var fileImage = FileImage(file);
+ final image = shouldResize
+ ? ResizeImage(fileImage,
+ width: width, height: height, allowUpscaling: allowUpscaling)
+ : fileImage as ImageProvider;
+ final completer = Completer();
+ image
+ .resolve(const ImageConfiguration())
+ .addListener(ImageStreamListener((info, _) {
+ completer.complete(info.image);
+ image.evict();
+ }));
+ return completer.future;
+}
diff --git a/lib/src/image_provider/_image_provider_io.dart b/lib/src/image_provider/_image_provider_io.dart
index 04249c9..d2567a5 100644
--- a/lib/src/image_provider/_image_provider_io.dart
+++ b/lib/src/image_provider/_image_provider_io.dart
@@ -29,12 +29,11 @@ class OptimizedCacheImageProvider
this.cacheManager,
this.cacheKey,
//ignore: avoid_unused_constructor_parameters
- ImageRenderMethodForWeb imageRenderMethodForWeb,
- }) : assert(url != null),
- assert(scale != null);
+ ImageRenderMethodForWeb? imageRenderMethodForWeb,
+ });
@override
- final BaseCacheManager cacheManager;
+ final BaseCacheManager? cacheManager;
/// Web url of the image to load
@override
@@ -42,7 +41,7 @@ class OptimizedCacheImageProvider
/// Cache key of the image to cache
@override
- final String cacheKey;
+ final String? cacheKey;
/// Scale of the image
@override
@@ -50,17 +49,17 @@ class OptimizedCacheImageProvider
/// Listener to be called when images fails to load.
@override
- final image_provider.ErrorListener errorListener;
+ final image_provider.ErrorListener? errorListener;
/// Set headers for the image provider, for example for authentication
@override
- final Map headers;
+ final Map? headers;
@override
- final int maxHeight;
+ final int? maxHeight;
@override
- final int maxWidth;
+ final int? maxWidth;
@override
Future obtainKey(
@@ -87,7 +86,7 @@ class OptimizedCacheImageProvider
}
Stream _loadAsync(
- OptimizedCacheImageProvider key,
+ image_provider.OptimizedCacheImageProvider key,
StreamController chunkEvents,
DecoderCallback decode,
) async* {
@@ -130,7 +129,7 @@ class OptimizedCacheImageProvider
// have had a chance to track the key in the cache at all.
// Schedule a microtask to give the cache a chance to add the key.
scheduleMicrotask(() {
- PaintingBinding.instance.imageCache.evict(key);
+ PaintingBinding.instance?.imageCache?.evict(key);
});
errorListener?.call();
diff --git a/lib/src/image_provider/_image_provider_web.dart b/lib/src/image_provider/_image_provider_web.dart
index 02436ff..d8fafdb 100644
--- a/lib/src/image_provider/_image_provider_web.dart
+++ b/lib/src/image_provider/_image_provider_web.dart
@@ -26,36 +26,34 @@ class OptimizedCacheImageProvider
this.headers,
this.cacheManager,
this.cacheKey,
- ImageRenderMethodForWeb imageRenderMethodForWeb,
- }) : _imageRenderMethodForWeb =
- imageRenderMethodForWeb ?? ImageRenderMethodForWeb.HtmlImage,
- assert(url != null),
- assert(scale != null);
+ ImageRenderMethodForWeb? imageRenderMethodForWeb,
+ }) : _imageRenderMethodForWeb =
+ imageRenderMethodForWeb ?? ImageRenderMethodForWeb.HtmlImage;
@override
- final BaseCacheManager cacheManager;
+ final BaseCacheManager? cacheManager;
@override
final String url;
@override
- final String cacheKey;
+ final String? cacheKey;
@override
final double scale;
/// Listener to be called when images fails to load.
@override
- final image_provider.ErrorListener errorListener;
+ final image_provider.ErrorListener? errorListener;
@override
- final Map headers;
+ final Map? headers;
@override
- final int maxHeight;
+ final int? maxHeight;
@override
- final int maxWidth;
+ final int? maxWidth;
final ImageRenderMethodForWeb _imageRenderMethodForWeb;
@@ -78,9 +76,9 @@ class OptimizedCacheImageProvider
informationCollector: _imageStreamInformationCollector(key));
}
- InformationCollector _imageStreamInformationCollector(
+ InformationCollector? _imageStreamInformationCollector(
image_provider.OptimizedCacheImageProvider key) {
- InformationCollector collector;
+ InformationCollector? collector;
assert(() {
collector = () {
return [
@@ -137,7 +135,7 @@ class OptimizedCacheImageProvider
// have had a chance to track the key in the cache at all.
// Schedule a microtask to give the cache a chance to add the key.
scheduleMicrotask(() {
- PaintingBinding.instance.imageCache.evict(key);
+ PaintingBinding.instance?.imageCache?.evict(key);
});
errorListener?.call();
diff --git a/lib/src/image_provider/multi_image_stream_completer.dart b/lib/src/image_provider/multi_image_stream_completer.dart
index 58fbe82..63fa5ea 100644
--- a/lib/src/image_provider/multi_image_stream_completer.dart
+++ b/lib/src/image_provider/multi_image_stream_completer.dart
@@ -16,12 +16,11 @@ class MultiImageStreamCompleter extends ImageStreamCompleter {
/// [chunkEvents] should indicate the [ImageChunkEvent]s of the first image
/// to show.
MultiImageStreamCompleter({
- @required Stream codec,
- @required double scale,
- Stream chunkEvents,
- InformationCollector informationCollector,
- }) : assert(codec != null),
- _informationCollector = informationCollector,
+ required Stream codec,
+ required double scale,
+ Stream? chunkEvents,
+ InformationCollector? informationCollector,
+ }) : _informationCollector = informationCollector,
_scale = scale {
codec.listen((event) {
if (_timer != null) {
@@ -54,18 +53,18 @@ class MultiImageStreamCompleter extends ImageStreamCompleter {
}
}
- ui.Codec _codec;
- ui.Codec _nextImageCodec;
+ ui.Codec? _codec;
+ ui.Codec? _nextImageCodec;
final double _scale;
- final InformationCollector _informationCollector;
- ui.FrameInfo _nextFrame;
+ final InformationCollector? _informationCollector;
+ ui.FrameInfo? _nextFrame;
// When the current was first shown.
- Duration _shownTimestamp;
+ Duration? _shownTimestamp;
// The requested duration for the current frame;
- Duration _frameDuration;
+ Duration? _frameDuration;
// How many frames have been emitted so far.
int _framesEmitted = 0;
- Timer _timer;
+ Timer? _timer;
// Used to guard against registering multiple _handleAppFrame callbacks for the same frame.
bool _frameCallbackScheduled = false;
@@ -73,7 +72,7 @@ class MultiImageStreamCompleter extends ImageStreamCompleter {
void _switchToNewCodec() {
_framesEmitted = 0;
_timer = null;
- _handleCodecReady(_nextImageCodec);
+ _handleCodecReady(_nextImageCodec!);
_nextImageCodec = null;
}
@@ -90,22 +89,22 @@ class MultiImageStreamCompleter extends ImageStreamCompleter {
_frameCallbackScheduled = false;
if (!hasListeners) return;
if (_isFirstFrame() || _hasFrameDurationPassed(timestamp)) {
- _emitFrame(ImageInfo(image: _nextFrame.image, scale: _scale));
+ _emitFrame(ImageInfo(image: _nextFrame!.image, scale: _scale));
_shownTimestamp = timestamp;
- _frameDuration = _nextFrame.duration;
+ _frameDuration = _nextFrame!.duration;
_nextFrame = null;
- if (_framesEmitted % _codec.frameCount == 0 && _nextImageCodec != null) {
+ if (_framesEmitted % _codec!.frameCount == 0 && _nextImageCodec != null) {
_switchToNewCodec();
} else {
- final completedCycles = _framesEmitted ~/ _codec.frameCount;
- if (_codec.repetitionCount == -1 ||
- completedCycles <= _codec.repetitionCount) {
+ final completedCycles = _framesEmitted ~/ _codec!.frameCount;
+ if (_codec!.repetitionCount == -1 ||
+ completedCycles <= _codec!.repetitionCount) {
_decodeNextFrameAndSchedule();
}
}
return;
}
- final delay = _frameDuration - (timestamp - _shownTimestamp);
+ final delay = _frameDuration! - (timestamp - _shownTimestamp!);
_timer = Timer(delay * timeDilation, _scheduleAppFrame);
}
@@ -115,12 +114,12 @@ class MultiImageStreamCompleter extends ImageStreamCompleter {
bool _hasFrameDurationPassed(Duration timestamp) {
assert(_shownTimestamp != null);
- return timestamp - _shownTimestamp >= _frameDuration;
+ return timestamp - _shownTimestamp! >= _frameDuration!;
}
Future _decodeNextFrameAndSchedule() async {
try {
- _nextFrame = await _codec.getNextFrame();
+ _nextFrame = await _codec!.getNextFrame();
} catch (exception, stack) {
reportError(
context: ErrorDescription('resolving an image frame'),
@@ -131,7 +130,7 @@ class MultiImageStreamCompleter extends ImageStreamCompleter {
);
return;
}
- if (_codec.frameCount == 1) {
+ if (_codec!.frameCount == 1) {
// ImageStreamCompleter listeners removed while waiting for next frame to
// be decoded.
// There's no reason to emit the frame without active listeners.
@@ -141,7 +140,7 @@ class MultiImageStreamCompleter extends ImageStreamCompleter {
// This is not an animated image, just return it and don't schedule more
// frames.
- _emitFrame(ImageInfo(image: _nextFrame.image, scale: _scale));
+ _emitFrame(ImageInfo(image: _nextFrame!.image, scale: _scale));
return;
}
_scheduleAppFrame();
@@ -152,7 +151,7 @@ class MultiImageStreamCompleter extends ImageStreamCompleter {
return;
}
_frameCallbackScheduled = true;
- SchedulerBinding.instance.scheduleFrameCallback(_handleAppFrame);
+ SchedulerBinding.instance?.scheduleFrameCallback(_handleAppFrame);
}
void _emitFrame(ImageInfo imageInfo) {
diff --git a/lib/src/image_provider/optimized_cached_image_provider.dart b/lib/src/image_provider/optimized_cached_image_provider.dart
index f93c8f4..08aaae5 100644
--- a/lib/src/image_provider/optimized_cached_image_provider.dart
+++ b/lib/src/image_provider/optimized_cached_image_provider.dart
@@ -40,47 +40,47 @@ abstract class OptimizedCacheImageProvider
/// for the benefits of each method.
const factory OptimizedCacheImageProvider(
String url, {
- int maxHeight,
- int maxWidth,
- String cacheKey,
+ int? maxHeight,
+ int? maxWidth,
+ String? cacheKey,
double scale,
@Deprecated('ErrorListener is deprecated, use listeners on the imagestream')
- ErrorListener errorListener,
- Map headers,
- BaseCacheManager cacheManager,
- ImageRenderMethodForWeb imageRenderMethodForWeb,
+ ErrorListener? errorListener,
+ Map? headers,
+ BaseCacheManager? cacheManager,
+ ImageRenderMethodForWeb? imageRenderMethodForWeb,
}) = image_provider.OptimizedCacheImageProvider;
/// Optional cache manager. If no cache manager is defined DefaultCacheManager()
/// will be used.
///
/// When running flutter on the web, the cacheManager is not used.
- BaseCacheManager get cacheManager;
+ BaseCacheManager? get cacheManager;
/// The errorListener is called when the ImageProvider failed loading the
/// image. Deprecated in favor of [ImageStreamListener.onError].
@deprecated
- ErrorListener get errorListener;
+ ErrorListener? get errorListener;
/// The URL from which the image will be fetched.
String get url;
/// The Key from image for cache
- String get cacheKey;
+ String? get cacheKey;
/// The scale to place in the [ImageInfo] object of the image.
double get scale;
/// The HTTP headers that will be used to fetch image from network.
- Map get headers;
+ Map? get headers;
/// Max height in pixels for the image. When set the resized image is
/// stored in the cache.
- int get maxHeight;
+ int? get maxHeight;
/// Max width in pixels for the image. When set the resized image is
/// stored in the cache.
- int get maxWidth;
+ int? get maxWidth;
@override
ImageStreamCompleter load(
diff --git a/lib/src/oci_widget.dart b/lib/src/oci_widget.dart
index 7b8a820..5f3ff8c 100644
--- a/lib/src/oci_widget.dart
+++ b/lib/src/oci_widget.dart
@@ -45,8 +45,8 @@ class OptimizedCacheImage extends StatelessWidget {
/// to clear the image from the [ImageCache].
static Future evictFromCache(
String url, {
- String cacheKey,
- BaseCacheManager cacheManager,
+ String? cacheKey,
+ BaseCacheManager? cacheManager,
double scale = 1.0,
}) async {
cacheManager = cacheManager ?? DefaultCacheManager();
@@ -54,34 +54,34 @@ class OptimizedCacheImage extends StatelessWidget {
return OptimizedCacheImageProvider(url, scale: scale).evict();
}
- OptimizedCacheImageProvider _image;
+ OptimizedCacheImageProvider? _image;
/// Option to use cachemanager with other settings
- final BaseCacheManager cacheManager;
+ final BaseCacheManager? cacheManager;
/// The target image that is displayed.
final String imageUrl;
/// The target image's cache key.
- final String cacheKey;
+ final String? cacheKey;
/// Optional builder to further customize the display of the image.
- final ImageWidgetBuilder imageBuilder;
+ final ImageWidgetBuilder? imageBuilder;
/// Widget displayed while the target [imageUrl] is loading.
- final PlaceholderWidgetBuilder placeholder;
+ final PlaceholderWidgetBuilder? placeholder;
/// Widget displayed while the target [imageUrl] is loading.
- final ProgressIndicatorBuilder progressIndicatorBuilder;
+ final ProgressIndicatorBuilder? progressIndicatorBuilder;
/// Widget displayed while the target [imageUrl] failed loading.
- final LoadingErrorWidgetBuilder errorWidget;
+ final LoadingErrorWidgetBuilder? errorWidget;
/// The duration of the fade-in animation for the [placeholder].
- final Duration placeholderFadeInDuration;
+ final Duration? placeholderFadeInDuration;
/// The duration of the fade-out animation for the [placeholder].
- final Duration fadeOutDuration;
+ final Duration? fadeOutDuration;
/// The curve of the fade-out animation for the [placeholder].
final Curve fadeOutCurve;
@@ -98,7 +98,7 @@ class OptimizedCacheImage extends StatelessWidget {
/// aspect ratio. This may result in a sudden change if the size of the
/// placeholder widget does not match that of the target image. The size is
/// also affected by the scale factor.
- final double width;
+ final double? width;
/// If non-null, require the image to have this height.
///
@@ -106,13 +106,13 @@ class OptimizedCacheImage extends StatelessWidget {
/// aspect ratio. This may result in a sudden change if the size of the
/// placeholder widget does not match that of the target image. The size is
/// also affected by the scale factor.
- final double height;
+ final double? height;
/// How to inscribe the image into the space allocated during layout.
///
/// The default varies based on the other fields. See the discussion at
/// [paintImage].
- final BoxFit fit;
+ final BoxFit? fit;
/// How to align the image within its bounds.
///
@@ -159,14 +159,14 @@ class OptimizedCacheImage extends StatelessWidget {
final bool matchTextDirection;
/// Optional headers for the http request of the image url
- final Map httpHeaders;
+ final Map? httpHeaders;
/// When set to true it will animate from the old image to the new image
/// if the url changes.
final bool useOldImageOnUrlChange;
/// If non-null, this color is blended with each image pixel using [colorBlendMode].
- final Color color;
+ final Color? color;
/// Used to combine [color] with this image.
///
@@ -176,7 +176,7 @@ class OptimizedCacheImage extends StatelessWidget {
/// See also:
///
/// * [BlendMode], which includes an illustration of the effect of each blend mode.
- final BlendMode colorBlendMode;
+ final BlendMode? colorBlendMode;
/// Target the interpolation quality for image scaling.
///
@@ -184,26 +184,26 @@ class OptimizedCacheImage extends StatelessWidget {
final FilterQuality filterQuality;
/// Will resize the image in memory to have a certain width using [ResizeImage]
- final int memCacheWidth;
+ final int? memCacheWidth;
/// Will resize the image in memory to have a certain height using [ResizeImage]
- final int memCacheHeight;
+ final int? memCacheHeight;
/// Will resize the image and store the resized image in the disk cache.
- final int maxWidthDiskCache;
+ final int? maxWidthDiskCache;
/// Will resize the image and store the resized image in the disk cache.
- final int maxHeightDiskCache;
+ final int? maxHeightDiskCache;
- final ImageRenderMethodForWeb imageRenderMethodForWeb;
+ final ImageRenderMethodForWeb? imageRenderMethodForWeb;
/// OptimizedCacheImage shows a network image using a caching mechanism. It also
/// provides support for a placeholder, showing an error and fading into the
/// loaded image. Next to that it supports most features of a default Image
/// widget.
OptimizedCacheImage({
- Key key,
- @required this.imageUrl,
+ Key? key,
+ required this.imageUrl,
this.httpHeaders,
this.imageBuilder,
this.placeholder,
@@ -231,16 +231,7 @@ class OptimizedCacheImage extends StatelessWidget {
this.maxWidthDiskCache,
this.maxHeightDiskCache,
this.imageRenderMethodForWeb,
- }) : assert(imageUrl != null),
- assert(fadeOutDuration != null),
- assert(fadeOutCurve != null),
- assert(fadeInDuration != null),
- assert(fadeInCurve != null),
- assert(alignment != null),
- assert(filterQuality != null),
- assert(repeat != null),
- assert(matchTextDirection != null),
- super(key: key);
+ }) : super(key: key);
@override
Widget build(BuildContext context) {
@@ -271,8 +262,8 @@ class OptimizedCacheImage extends StatelessWidget {
: null;
}
if (_image == null ||
- _image.maxHeight != _constrainHeight ||
- _image.maxWidth != _constrainHeight) {
+ _image?.maxHeight != _constrainHeight ||
+ _image?.maxWidth != _constrainHeight) {
_image = OptimizedCacheImageProvider(
imageUrl,
headers: httpHeaders,
@@ -284,7 +275,7 @@ class OptimizedCacheImage extends StatelessWidget {
);
}
return OctoImage(
- image: _image,
+ image: _image!,
imageBuilder: imageBuilder != null ? _octoImageBuilder : null,
placeholderBuilder: octoPlaceholderBuilder,
progressIndicatorBuilder: octoProgressIndicatorBuilder,
@@ -296,7 +287,7 @@ class OptimizedCacheImage extends StatelessWidget {
width: width,
height: height,
fit: fit,
- alignment: alignment,
+ alignment: alignment as Alignment?,
repeat: repeat,
matchTextDirection: matchTextDirection,
color: color,
@@ -309,32 +300,32 @@ class OptimizedCacheImage extends StatelessWidget {
}
Widget _octoImageBuilder(BuildContext context, Widget child) {
- return imageBuilder(context, _image);
+ return imageBuilder!(context, _image!);
}
Widget _octoPlaceholderBuilder(BuildContext context) {
- return placeholder(context, imageUrl);
+ return placeholder!(context, imageUrl);
}
Widget _octoProgressIndicatorBuilder(
BuildContext context,
- ImageChunkEvent progress,
+ ImageChunkEvent? progress,
) {
- int totalSize;
+ int? totalSize;
var downloaded = 0;
if (progress != null) {
totalSize = progress.expectedTotalBytes;
downloaded = progress.cumulativeBytesLoaded;
}
- return progressIndicatorBuilder(
+ return progressIndicatorBuilder!(
context, imageUrl, DownloadProgress(imageUrl, totalSize, downloaded));
}
Widget _octoErrorBuilder(
BuildContext context,
Object error,
- StackTrace stackTrace,
+ StackTrace? stackTrace,
) {
- return errorWidget(context, imageUrl, error);
+ return errorWidget!(context, imageUrl, error);
}
}
diff --git a/lib/src/transformer/image_transformer.dart b/lib/src/transformer/image_transformer.dart
index 7c6647c..b1844ad 100644
--- a/lib/src/transformer/image_transformer.dart
+++ b/lib/src/transformer/image_transformer.dart
@@ -31,12 +31,13 @@ class DefaultImageTransformer extends ImageTransformer {
};
@override
- Future transform(FileInfo info, int width, int height) async {
+ Future transform(FileInfo info, int? width, int? height) async {
final value = await _scaleImageFile(info, width, height);
return value;
}
- Future _scaleImageFile(FileInfo info, int width, int height) async {
+ Future _scaleImageFile(
+ FileInfo info, int? width, int? height) async {
FileInfo fileInfo = info;
final file = fileInfo.file;
log("Scaling file.. ${fileInfo.originalUrl}");
@@ -55,7 +56,7 @@ class DefaultImageTransformer extends ImageTransformer {
final localFileSystem = fileIo.LocalFileSystem();
resizedFile = localFileSystem.file(scaleInfo.file.path);
- if (resizedFile != null && resizedFile.existsSync()) {
+ if (resizedFile.existsSync()) {
if (resizedFile.lengthSync() < srcSize) {
log("Resized success ${fileInfo.originalUrl}");
} else {
@@ -74,7 +75,7 @@ class DefaultImageTransformer extends ImageTransformer {
}
@override
- ScaleInfo getScaledFileInfo(File file, int width, int height) {
+ ScaleInfo getScaledFileInfo(File file, int? width, int? height) {
final format = _getCompressionFormat(file);
final directory = file.parent;
@@ -82,18 +83,18 @@ class DefaultImageTransformer extends ImageTransformer {
"/" +
p.basenameWithoutExtension(file.path) +
sprintf(tmpFileSuffix, [width ?? 1, height ?? 1]) +
- _extensionFormats[format];
+ _extensionFormats[format]!;
final scaleFile = File(destPath);
return ScaleInfo(scaleFile, width ?? 1, height ?? 1, format);
}
CompressFormat _getCompressionFormat(File file) {
- String extension = p.extension(file.path) ?? '';
+ String extension = p.extension(file.path);
return _compressionFormats[extension] ?? CompressFormat.png;
}
}
abstract class ImageTransformer {
- Future transform(FileInfo info, int width, int height);
+ Future transform(FileInfo info, int? width, int? height);
ScaleInfo getScaledFileInfo(File file, int width, int height);
}
diff --git a/pubspec.yaml b/pubspec.yaml
index a18377e..660f8b8 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,10 +1,10 @@
name: optimized_cached_image
description: A library for loading images from network, resizing as per container size and caching while being memory sensitive.
-version: 2.0.2-alpha
+version: 3.0.0
homepage: https://github.com/humblerookie/optimized_cached_image
environment:
- sdk: ">=2.6.2 <3.0.0"
+ sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter