Adds support for picking remote images on iOS (multi-picking from Gallery)

This commit is contained in:
Miguel Ruivo 2020-04-25 19:00:23 +01:00
parent 806a074216
commit 7d6bffd692
5 changed files with 84 additions and 33 deletions

View File

@ -1,3 +1,7 @@
## 1.7.0
**Breaking change**
Added support for multi-picks from Photos app on iOS through [BSImagePicker](https://github.com/mikaoj/BSImagePicker) — use any of the `getMulti` methods with `FileType.image`. From now on, you'll need to set your iOS minimum version to 10.0 and add `use_frameworks!` in your ios/Podfile.
## 1.6.3+2
* Fixes a crash on Android when a file has an id that can't be resolved and uses a name instead (#221);
* Minor fix on Go (Desktop) - Windows (thanks @marchellodev);

View File

@ -99,6 +99,7 @@
[_viewController presentViewController:self.documentPickerController animated:YES completion:nil];
}
- (void) resolvePickImage:(BOOL)withMultiPick {
if(!withMultiPick) {
@ -112,42 +113,69 @@
} else {
ImagePickerController * multiImagePickerController = [[ImagePickerController alloc] initWithSelectedAssets:@[]];
UIProgressView * progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0.0, 0.0, multiImagePickerController.view.bounds.size.width, 10.0)];
CGAffineTransform transform = CGAffineTransformMakeScale(1.0f, 4.0f);
progressView.transform = transform;
[_viewController presentImagePicker:multiImagePickerController
animated:YES
select:^(PHAsset * _Nonnull selectedAsset) {}
select:^(PHAsset * _Nonnull selectedAsset) {}
deselect:^(PHAsset * _Nonnull deselectedAsset) {}
cancel:^(NSArray<PHAsset *> * _Nonnull canceledAsset) {}
finish:^(NSArray<PHAsset *> * _Nonnull assets) {
NSMutableArray<NSString*> *paths = [[NSMutableArray<NSString*> alloc] init];
if(assets.count > 0) {
dispatch_semaphore_t completer = dispatch_semaphore_create(0);
__block int processedAssets = 0;
for(PHAsset* asset in assets){
[asset requestContentEditingInputWithOptions:[PHContentEditingInputRequestOptions new] completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
NSURL *imageURL = contentEditingInput.fullSizeImageURL;
[paths addObject:imageURL.path];
if(++processedAssets == assets.count) {
dispatch_semaphore_signal(completer);
}
}];
}
if (![NSThread isMainThread]) {
dispatch_semaphore_wait(completer, DISPATCH_TIME_FOREVER);
} else {
while (dispatch_semaphore_wait(completer, DISPATCH_TIME_NOW)) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0]];
}
}
}
cancel:^(NSArray<PHAsset *> * _Nonnull canceledAsset) {
self->_result(nil);
self->_result = nil;
}
finish:^(NSArray<PHAsset *> * _Nonnull assets) {
int totalRemoteAssets = [FileUtils countRemoteAssets:assets];
NSMutableArray<NSString*> *paths = [[NSMutableArray<NSString*> alloc] init];
NSMutableDictionary<NSString*, NSNumber*> * progresses = [[NSMutableDictionary<NSString*, NSNumber*> alloc] initWithCapacity: totalRemoteAssets];
self->_result(paths);
self->_result = nil;
} completion:^{}];
if(totalRemoteAssets > 0) {
[multiImagePickerController.view addSubview:progressView];
}
if(assets.count > 0) {
dispatch_semaphore_t completer = dispatch_semaphore_create(0);
__block int processedAssets = 0;
for(PHAsset* asset in assets){
PHContentEditingInputRequestOptions * options = [[PHContentEditingInputRequestOptions alloc] init];
options.networkAccessAllowed = YES;
if(![FileUtils isLocalAsset:asset]){
options.progressHandler = ^(double progress, BOOL * _Nonnull stop) {
progresses[asset.localIdentifier] = [NSNumber numberWithFloat:progress];
@synchronized(progresses){
dispatch_async(dispatch_get_main_queue(), ^{
progressView.progress = [[[progresses allValues] valueForKeyPath:@"@sum.self"] floatValue] / totalRemoteAssets;
});
};
};
}
[asset requestContentEditingInputWithOptions:options completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
NSURL *imageURL = contentEditingInput.fullSizeImageURL;
[paths addObject:imageURL.path];
if(++processedAssets == assets.count) {
dispatch_semaphore_signal(completer);
}
}];
}
if (![NSThread isMainThread]) {
dispatch_semaphore_wait(completer, DISPATCH_TIME_FOREVER);
} else {
while (dispatch_semaphore_wait(completer, DISPATCH_TIME_NOW)) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0]];
}
}
}
self->_result(paths);
self->_result = nil;
} completion:^{}];
}
}

View File

@ -5,6 +5,7 @@
// Created by Miguel Ruivo on 05/12/2018.
//
#import <MobileCoreServices/MobileCoreServices.h>
#import <Photos/Photos.h>
#ifdef DEBUG
#define Log(fmt, ...) NSLog((@"\n\n***** " fmt @"\n* %s [Line %d]\n\n\n"), ##__VA_ARGS__, __PRETTY_FUNCTION__, __LINE__)
@ -15,6 +16,8 @@
@interface FileUtils : NSObject
+ (NSArray<NSString*>*) resolveType:(NSString*)type withAllowedExtensions:(NSArray<NSString*>*)allowedExtensions;
+ (NSArray*) resolvePath:(NSArray<NSURL *> *)urls;
+ (int) countRemoteAssets:(NSArray<PHAsset*> *)assets;
+ (BOOL) isLocalAsset:(PHAsset *) asset;
@end

View File

@ -57,4 +57,20 @@
return paths;
}
+ (int)countRemoteAssets:(NSArray<PHAsset*> *)assets {
int total = 0;
for(PHAsset * asset in assets) {
NSArray *resourceArray = [PHAssetResource assetResourcesForAsset:asset];
if(![[resourceArray.firstObject valueForKey:@"locallyAvailable"] boolValue]) {
total++;
}
}
return total;
}
+ (BOOL)isLocalAsset:(PHAsset *) asset {
NSArray *resourceArray = [PHAssetResource assetResourcesForAsset:asset];
return [[resourceArray.firstObject valueForKey:@"locallyAvailable"] boolValue];
}
@end

View File

@ -1,7 +1,7 @@
name: file_picker
description: A package that allows you to use a native file explorer to pick single or multiple absolute file paths, with extension filtering support.
homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker
version: 1.6.3+2
version: 1.7.0
dependencies:
flutter: