Enable rendering of HEIC images

This commit is contained in:
Vishnu Mohandas 2020-04-24 01:30:20 +05:30
parent 293e2cae95
commit 20f4f6324b
14 changed files with 226 additions and 74 deletions

17
android/.project Normal file
View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>android</name>
<comment>Project android created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,13 @@
arguments=
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home
jvm.arguments=
offline.mode=false
override.workspace.settings=true
show.console.view=true
show.executions.view=true

6
android/app/.classpath Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>

23
android/app/.project Normal file
View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>app</name>
<comment>Project app created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,2 @@
connection.project.dir=..
eclipse.preferences.version=1

View file

@ -1,16 +1,38 @@
PODS:
- Flutter (1.0.0)
- flutter_image_compress (0.0.1):
- Flutter
- Mantle
- SDWebImageWebPCoder
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- libwebp (1.1.0):
- libwebp/demux (= 1.1.0)
- libwebp/mux (= 1.1.0)
- libwebp/webp (= 1.1.0)
- libwebp/demux (1.1.0):
- libwebp/webp
- libwebp/mux (1.1.0):
- libwebp/demux
- libwebp/webp (1.1.0)
- local_image_provider (0.0.1):
- Flutter
- Mantle (2.1.1):
- Mantle/extobjc (= 2.1.1)
- Mantle/extobjc (2.1.1)
- path_provider (0.0.1):
- Flutter
- path_provider_macos (0.0.1):
- Flutter
- photo_manager (0.0.1):
- Flutter
- SDWebImage/Core (5.7.3)
- SDWebImageWebPCoder (0.6.1):
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.7)
- share_extend (0.0.1):
- Flutter
- shared_preferences (0.0.1):
- Flutter
- shared_preferences_macos (0.0.1):
@ -23,10 +45,12 @@ PODS:
DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_image_compress (from `.symlinks/plugins/flutter_image_compress/ios`)
- local_image_provider (from `.symlinks/plugins/local_image_provider/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`)
- photo_manager (from `.symlinks/plugins/photo_manager/ios`)
- share_extend (from `.symlinks/plugins/share_extend/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- shared_preferences_macos (from `.symlinks/plugins/shared_preferences_macos/ios`)
- shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`)
@ -35,10 +59,16 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- FMDB
- libwebp
- Mantle
- SDWebImage
- SDWebImageWebPCoder
EXTERNAL SOURCES:
Flutter:
:path: Flutter
flutter_image_compress:
:path: ".symlinks/plugins/flutter_image_compress/ios"
local_image_provider:
:path: ".symlinks/plugins/local_image_provider/ios"
path_provider:
@ -47,6 +77,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/path_provider_macos/ios"
photo_manager:
:path: ".symlinks/plugins/photo_manager/ios"
share_extend:
:path: ".symlinks/plugins/share_extend/ios"
shared_preferences:
:path: ".symlinks/plugins/shared_preferences/ios"
shared_preferences_macos:
@ -58,11 +90,17 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
flutter_image_compress: 082f8daaf6c1b0c9fe798251c750ef0ecd98d7ae
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3
local_image_provider: cf979b81bc1cacc81867d3511a1b6b7216411e93
Mantle: 35238ae6f2e2b2d474fa7b67fee82a59fea71915
path_provider: fb74bd0465e96b594bb3b5088ee4a4e7bb1f2a9d
path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0
photo_manager: f7c619c2cc8c2adb8d85c63363babac477de9c67
SDWebImage: 97351f6582ceca541ea294ba66a1fcb342a331c2
SDWebImageWebPCoder: d0dac55073088d24b2ac1b191a71a8f8d0adac21
share_extend: b6748dc53695587891126a89533b862b92548c7b
shared_preferences: 430726339841afefe5142b9c1f50cb6bd7793e01
shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087
shared_preferences_web: 141cce0c3ed1a1c5bf2a0e44f52d31eeb66e5ea9

View file

@ -10,11 +10,7 @@
06CC0CFA92976FDBA53FAAE5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB5F531E492C7002EAC4CE42 /* Pods_Runner.framework */; };
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@ -27,8 +23,6 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@ -39,14 +33,12 @@
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
6A8718E36D8B0CC6360ADB0D /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
97A6D25F159DA10C77E8A78D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
@ -62,8 +54,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
06CC0CFA92976FDBA53FAAE5 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -74,9 +64,7 @@
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
@ -133,7 +121,6 @@
A3AB65855D82977B2D2D5B35 /* Pods-Runner.release.xcconfig */,
6A8718E36D8B0CC6360ADB0D /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
@ -232,7 +219,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
481FE5B058006945E0569431 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
@ -376,7 +363,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 37L77XPSDP;
@ -391,7 +378,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = Orma.FlutterApp;
PRODUCT_BUNDLE_IDENTIFIER = orma.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -515,7 +502,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 37L77XPSDP;
@ -530,7 +517,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = Orma.FlutterApp;
PRODUCT_BUNDLE_IDENTIFIER = orma.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -547,7 +534,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 37L77XPSDP;
@ -562,7 +549,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = Orma.FlutterApp;
PRODUCT_BUNDLE_IDENTIFIER = orma.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";

View file

@ -22,6 +22,8 @@
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo Library Access Warning</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
@ -41,7 +43,5 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo Library Access Warning</string>
</dict>
</plist>

View file

@ -1,6 +1,5 @@
import 'dart:collection';
import 'package:flutter/material.dart';
import 'dart:typed_data';
typedef EvictionHandler<K, V>(K key, V value);
@ -37,31 +36,31 @@ class LRUMap<K, V> {
}
class ImageLruCache {
static LRUMap<_ImageCacheEntity, Image> _map = LRUMap(500);
static LRUMap<_ImageCacheEntity, Uint8List> _map = LRUMap(500);
static Image getData(String path, [int size = 64]) {
return _map.get(_ImageCacheEntity(path, size));
static Uint8List getData(int id, [int size = 64]) {
return _map.get(_ImageCacheEntity(id, size));
}
static void setData(String path, int size, Image image) {
_map.put(_ImageCacheEntity(path, size), image);
static void setData(int id, int size, Uint8List imageData) {
_map.put(_ImageCacheEntity(id, size), imageData);
}
}
class _ImageCacheEntity {
String path;
int id;
int size;
_ImageCacheEntity(this.path, this.size);
_ImageCacheEntity(this.id, this.size);
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is _ImageCacheEntity &&
runtimeType == other.runtimeType &&
path == other.path &&
id == other.id &&
size == other.size;
@override
int get hashCode => path.hashCode ^ size.hashCode;
int get hashCode => id.hashCode ^ size.hashCode;
}

View file

@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:io';
import 'package:crypto/crypto.dart';
@ -47,14 +48,16 @@ class Photo {
return photo;
}
AssetEntity getAsset() {
return AssetEntity(id: localId);
}
static String getHash(File file) {
return sha256.convert(file.readAsBytesSync()).toString();
}
int get hashCode => generatedId;
@override
bool operator ==(other) {
return generatedId == other.generatedId;
String toString() {
return 'Photo(generatedId: $generatedId, uploadedFileId: $uploadedFileId, localId: $localId, path: $path, localPath: $localPath, relativePath: $relativePath, thumbnailPath: $thumbnailPath, hash: $hash, createTimestamp: $createTimestamp, syncTimestamp: $syncTimestamp)';
}
}

View file

@ -1,11 +1,16 @@
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
import 'package:myapp/core/lru_map.dart';
import 'package:myapp/models/photo.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:photo_view/photo_view.dart';
import 'package:share_extend/share_extend.dart';
import 'extents_page_view.dart';
import 'loading_widget.dart';
import 'package:path/path.dart' as path;
import 'package:flutter_image_compress/flutter_image_compress.dart';
class DetailPage extends StatefulWidget {
final List<Photo> photos;
@ -20,28 +25,38 @@ class DetailPage extends StatefulWidget {
class _DetailPageState extends State<DetailPage> {
bool _shouldDisableScroll = false;
int _selectedIndex = 0;
final _cachedImages = LRUMap<int, ZoomableImage>(5);
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
_selectedIndex = widget.selectedIndex;
Logger().i("Loading " + widget.photos[_selectedIndex].toString());
var pageController = PageController(initialPage: _selectedIndex);
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
icon: Icon(Icons.share),
onPressed: () {
ShareExtend.share(
widget.photos[_selectedIndex].localPath, "image");
},
)
],
),
appBar: _buildAppBar(),
body: Center(
child: Container(
child: ExtentsPageView.extents(
itemBuilder: (context, index) {
return _buildItem(context, widget.photos[index]);
if (_cachedImages.get(index) != null) {
return _cachedImages.get(index);
}
final image = ZoomableImage(
photo: widget.photos[index],
shouldDisableScroll: (value) {
setState(() {
_shouldDisableScroll = value;
});
},
);
_cachedImages.put(index, image);
return image;
},
onPageChanged: (int index) {
_selectedIndex = index;
@ -57,28 +72,68 @@ class _DetailPageState extends State<DetailPage> {
);
}
Widget _buildItem(BuildContext context, Photo photo) {
var image = ImageLruCache.getData(photo.localPath) == null
? Image.file(
File(photo.localPath),
filterQuality: FilterQuality.low,
)
: ImageLruCache.getData(photo.localPath);
AppBar _buildAppBar() {
return AppBar(
actions: <Widget>[
IconButton(
icon: Icon(Icons.share),
onPressed: () {
ShareExtend.share(widget.photos[_selectedIndex].localPath, "image");
},
)
],
);
}
}
class ZoomableImage extends StatelessWidget {
final Function(bool) shouldDisableScroll;
const ZoomableImage({
Key key,
@required this.photo,
this.shouldDisableScroll,
}) : super(key: key);
final Photo photo;
@override
Widget build(BuildContext context) {
Logger().i("Building " + photo.generatedId.toString());
if (ImageLruCache.getData(photo.generatedId) != null) {
return _buildPhotoView(ImageLruCache.getData(photo.generatedId));
}
var future;
if (path.extension(photo.localPath) == '.HEIC') {
Logger().i("Decoding HEIC");
future = photo.getAsset().originBytes.then((bytes) =>
FlutterImageCompress.compressWithList(bytes)
.then((result) => Uint8List.fromList(result)));
} else {
future = AssetEntity(id: photo.localId).originBytes;
}
return FutureBuilder<Uint8List>(
future: future,
builder: (_, snapshot) {
if (snapshot.hasData) {
return _buildPhotoView(snapshot.data);
} else if (snapshot.hasError) {
return Text(snapshot.error);
} else {
return loadWidget;
}
},
);
}
Widget _buildPhotoView(Uint8List imageData) {
ValueChanged<PhotoViewScaleState> scaleStateChangedCallback = (value) {
var shouldDisableScroll;
if (value == PhotoViewScaleState.initial) {
shouldDisableScroll = false;
} else {
shouldDisableScroll = true;
}
if (shouldDisableScroll != _shouldDisableScroll) {
setState(() {
_shouldDisableScroll = shouldDisableScroll;
});
if (shouldDisableScroll != null) {
shouldDisableScroll(value != PhotoViewScaleState.initial);
}
};
return PhotoView(
imageProvider: image.image,
imageProvider: Image.memory(imageData).image,
scaleStateChangedCallback: scaleStateChangedCallback,
minScale: PhotoViewComputedScale.contained,
);

View file

@ -26,14 +26,14 @@ class _ImageWidgetState extends State<ImageWidget> {
);
@override
Widget build(BuildContext context) {
final path = widget.photo.localPath;
final size = widget.size == null ? 124 : widget.size;
final cachedImage = ImageLruCache.getData(path, size);
final cachedImageData =
ImageLruCache.getData(widget.photo.generatedId, size);
Widget image;
if (cachedImage != null) {
image = cachedImage;
if (cachedImageData != null) {
image = Image.memory(cachedImageData);
} else {
if (widget.photo.localId != null) {
image = FutureBuilder<Uint8List>(
@ -41,11 +41,12 @@ class _ImageWidgetState extends State<ImageWidget> {
.thumbDataWithSize(size, size),
builder: (context, snapshot) {
if (snapshot.hasData) {
ImageLruCache.setData(
widget.photo.generatedId, size, snapshot.data);
Image image = Image.memory(snapshot.data,
width: size.toDouble(),
height: size.toDouble(),
fit: BoxFit.cover);
ImageLruCache.setData(path, size, image);
return image;
} else {
return loadingWidget;
@ -64,7 +65,7 @@ class _ImageWidgetState extends State<ImageWidget> {
@override
void didUpdateWidget(ImageWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.photo.localPath != oldWidget.photo.localPath) {
if (widget.photo.generatedId != oldWidget.photo.generatedId) {
setState(() {});
}
}

View file

@ -83,6 +83,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_image_compress:
dependency: "direct main"
description:
name: flutter_image_compress
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.7"
flutter_test:
dependency: "direct dev"
description: flutter

View file

@ -37,6 +37,7 @@ dependencies:
share_extend: "^1.1.2"
draggable_scrollbar: ^0.0.4
photo_view: ^0.9.2
flutter_image_compress: ^0.6.5+1
dev_dependencies:
flutter_test: