2018-06-23 01:22:04 +00:00
# import "FilePickerPlugin.h"
2018-12-05 15:32:02 +00:00
# import "FileUtils.h"
2019-03-05 19:02:14 +00:00
# import "ImageUtils.h"
2018-06-23 01:22:04 +00:00
2020-04-26 20:47:49 +00:00
@ import DKImagePickerController ;
2020-04-22 21:27:46 +00:00
2020-09-25 14:24:12 +00:00
@ interface FilePickerPlugin ( ) < DKImageAssetExporterObserver >
2018-11-30 18:06:11 +00:00
@ property ( nonatomic ) FlutterResult result ;
2020-06-12 01:19:25 +00:00
@ property ( nonatomic ) FlutterEventSink eventSink ;
2020-12-13 16:19:48 +00:00
@ property ( nonatomic , readonly ) UIViewController * viewController ;
2019-03-05 19:02:14 +00:00
@ property ( nonatomic ) UIImagePickerController * galleryPickerController ;
2019-03-11 00:01:44 +00:00
@ property ( nonatomic ) UIDocumentPickerViewController * documentPickerController ;
2018-11-30 18:06:11 +00:00
@ property ( nonatomic ) UIDocumentInteractionController * interactionController ;
2019-03-06 01:16:35 +00:00
@ property ( nonatomic ) MPMediaPickerController * audioPickerController ;
2020-04-05 22:06:48 +00:00
@ property ( nonatomic ) NSArray < NSString * > * allowedExtensions ;
2020-09-11 17:01:34 +00:00
@ property ( nonatomic ) BOOL loadDataToMemory ;
2020-12-10 13:00:56 +00:00
@ property ( nonatomic ) dispatch_group _t group ;
2018-11-30 18:06:11 +00:00
@ end
2018-06-23 01:22:04 +00:00
2018-11-30 18:06:11 +00:00
@ implementation FilePickerPlugin
2018-06-23 01:22:04 +00:00
+ ( void ) registerWithRegistrar : ( NSObject < FlutterPluginRegistrar > * ) registrar {
2018-11-30 18:06:11 +00:00
FlutterMethodChannel * channel = [ FlutterMethodChannel
2020-04-05 22:06:48 +00:00
methodChannelWithName : @ "miguelruivo.flutter.plugins.filepicker"
2018-11-30 18:06:11 +00:00
binaryMessenger : [ registrar messenger ] ] ;
2018-06-24 15:07:34 +00:00
2020-06-12 01:19:25 +00:00
FlutterEventChannel * eventChannel = [ FlutterEventChannel
eventChannelWithName : @ "miguelruivo.flutter.plugins.filepickerevent"
binaryMessenger : [ registrar messenger ] ] ;
2020-12-13 16:19:48 +00:00
FilePickerPlugin * instance = [ [ FilePickerPlugin alloc ] init ] ;
2018-06-23 01:22:04 +00:00
2018-11-30 18:06:11 +00:00
[ registrar addMethodCallDelegate : instance channel : channel ] ;
2020-06-12 01:19:25 +00:00
[ eventChannel setStreamHandler : instance ] ;
2018-06-23 01:22:04 +00:00
}
2020-12-13 16:19:48 +00:00
- ( instancetype ) init {
2018-06-23 01:22:04 +00:00
self = [ super init ] ;
2018-11-30 18:06:11 +00:00
2018-12-05 15:32:02 +00:00
return self ;
2018-11-30 18:06:11 +00:00
}
2020-12-13 16:19:48 +00:00
- ( UIViewController * ) viewController {
UIViewController * rootViewController = [ UIApplication sharedApplication ] . delegate . window . rootViewController ;
while ( rootViewController . presentedViewController ) {
rootViewController = rootViewController . presentedViewController ;
}
return rootViewController ;
}
2020-06-12 01:19:25 +00:00
- ( FlutterError * ) onListenWithArguments : ( id ) arguments eventSink : ( FlutterEventSink ) events {
_eventSink = events ;
return nil ;
}
- ( FlutterError * ) onCancelWithArguments : ( id ) arguments {
_eventSink = nil ;
return nil ;
}
2018-06-23 01:22:04 +00:00
- ( void ) handleMethodCall : ( FlutterMethodCall * ) call result : ( FlutterResult ) result {
if ( _result ) {
2019-03-11 00:01:44 +00:00
result ( [ FlutterError errorWithCode : @ "multiple_request"
2020-09-23 09:23:38 +00:00
message : @ "Cancelled by a second request"
details : nil ] ) ;
2018-06-23 01:22:04 +00:00
_result = nil ;
2019-03-11 00:01:44 +00:00
return ;
2018-06-23 01:22:04 +00:00
}
2018-11-30 18:06:11 +00:00
2018-12-05 15:32:02 +00:00
_result = result ;
2020-05-01 16:49:35 +00:00
if ( [ call . method isEqualToString : @ "clear" ] ) {
_result ( [ NSNumber numberWithBool : [ FileUtils clearTemporaryFiles ] ] ) ;
_result = nil ;
return ;
}
2020-06-04 21:49:39 +00:00
if ( [ call . method isEqualToString : @ "dir" ] ) {
2020-10-07 14:16:56 +00:00
if ( @ available ( iOS 13 , * ) ) {
[ self resolvePickDocumentWithMultiPick : NO pickDirectory : YES ] ;
} else {
_result ( [ self getDocumentDirectory ] ) ;
_result = nil ;
}
2020-06-04 21:49:39 +00:00
return ;
}
2020-04-05 22:06:48 +00:00
NSDictionary * arguments = call . arguments ;
BOOL isMultiplePick = ( ( NSNumber * ) [ arguments valueForKey : @ "allowMultipleSelection" ] ) . boolValue ;
2020-09-11 17:01:34 +00:00
self . loadDataToMemory = ( ( NSNumber * ) [ arguments valueForKey : @ "withData" ] ) . boolValue ;
2020-04-27 21:25:57 +00:00
if ( [ call . method isEqualToString : @ "any" ] || [ call . method containsString : @ "custom" ] ) {
2020-04-05 22:06:48 +00:00
self . allowedExtensions = [ FileUtils resolveType : call . method withAllowedExtensions : [ arguments valueForKey : @ "allowedExtensions" ] ] ;
if ( self . allowedExtensions = = nil ) {
2019-03-12 01:25:23 +00:00
_result ( [ FlutterError errorWithCode : @ "Unsupported file extension"
2020-04-05 22:06:48 +00:00
message : @ "If you are providing extension filters make sure that you are only using FileType.custom and the extension are provided without the dot, (ie., jpg instead of .jpg). This could also have happened because you are using an unsupported file extension. If the problem persists, you may want to consider using FileType.all instead."
2019-03-12 01:25:23 +00:00
details : nil ] ) ;
_result = nil ;
2020-04-05 22:06:48 +00:00
} else if ( self . allowedExtensions ! = nil ) {
2020-06-04 21:49:39 +00:00
[ self resolvePickDocumentWithMultiPick : isMultiplePick pickDirectory : NO ] ;
2019-03-12 01:25:23 +00:00
}
2020-04-27 21:25:57 +00:00
} else if ( [ call . method isEqualToString : @ "video" ] || [ call . method isEqualToString : @ "image" ] || [ call . method isEqualToString : @ "media" ] ) {
2020-07-20 14:31:14 +00:00
[ self resolvePickMedia : [ FileUtils resolveMediaType : call . method ] withMultiPick : isMultiplePick withCompressionAllowed : [ arguments valueForKey : @ "allowCompression" ] ] ;
2020-04-27 21:25:57 +00:00
} else if ( [ call . method isEqualToString : @ "audio" ] ) {
2020-09-11 17:01:34 +00:00
[ self resolvePickAudioWithMultiPick : isMultiplePick ] ;
2019-03-05 19:02:14 +00:00
} else {
2019-03-12 01:25:23 +00:00
result ( FlutterMethodNotImplemented ) ;
_result = nil ;
2018-11-30 18:06:11 +00:00
}
2020-10-07 14:16:56 +00:00
}
- ( NSString * ) getDocumentDirectory {
NSArray * paths = NSSearchPathForDirectoriesInDomains ( NSDocumentDirectory , NSUserDomainMask , YES ) ;
return paths . firstObject ;
2018-06-23 01:22:04 +00:00
}
2019-03-05 19:02:14 +00:00
# pragma mark - Resolvers
2020-06-04 21:49:39 +00:00
- ( void ) resolvePickDocumentWithMultiPick : ( BOOL ) allowsMultipleSelection pickDirectory : ( BOOL ) isDirectory {
2019-03-05 19:02:14 +00:00
2019-03-11 00:01:44 +00:00
@ try {
self . documentPickerController = [ [ UIDocumentPickerViewController alloc ]
2020-06-04 21:49:39 +00:00
initWithDocumentTypes : isDirectory ? @ [ @ "public.folder" ] : self . allowedExtensions
inMode : isDirectory ? UIDocumentPickerModeOpen : UIDocumentPickerModeImport ] ;
2019-03-11 00:01:44 +00:00
} @ catch ( NSException * e ) {
2020-09-23 09:23:38 +00:00
Log ( @ "Couldn't launch documents file picker. Probably due to iOS version being below 11.0 and not having the iCloud entitlement. If so, just make sure to enable it for your app in Xcode. Exception was: %@" , e ) ;
2019-03-11 00:01:44 +00:00
_result = nil ;
return ;
}
2019-03-05 19:02:14 +00:00
if ( @ available ( iOS 11.0 , * ) ) {
2019-03-11 00:01:44 +00:00
self . documentPickerController . allowsMultipleSelection = allowsMultipleSelection ;
2019-03-06 01:16:35 +00:00
} else if ( allowsMultipleSelection ) {
2020-09-23 09:23:38 +00:00
Log ( @ "Multiple file selection is only supported on iOS 11 and above. Single selection will be used." ) ;
2019-03-05 19:02:14 +00:00
}
2019-03-06 01:16:35 +00:00
2019-03-11 00:01:44 +00:00
self . documentPickerController . delegate = self ;
2019-03-05 19:02:14 +00:00
self . galleryPickerController . allowsEditing = NO ;
2019-03-11 00:01:44 +00:00
2020-12-13 16:19:48 +00:00
[ self . viewController presentViewController : self . documentPickerController animated : YES completion : nil ] ;
2019-03-05 19:02:14 +00:00
}
2020-07-20 14:31:14 +00:00
- ( void ) resolvePickMedia : ( MediaType ) type withMultiPick : ( BOOL ) multiPick withCompressionAllowed : ( BOOL ) allowCompression {
2020-10-25 18:07:36 +00:00
# ifdef PHPicker
2020-09-23 09:23:38 +00:00
if ( @ available ( iOS 14 , * ) ) {
PHPickerConfiguration * config = [ [ PHPickerConfiguration alloc ] init ] ;
config . filter = type = = IMAGE ? [ PHPickerFilter imagesFilter ] : type = = VIDEO ? [ PHPickerFilter videosFilter ] : [ PHPickerFilter anyFilterMatchingSubfilters : @ [ [ PHPickerFilter videosFilter ] , [ PHPickerFilter imagesFilter ] ] ] ;
2021-02-21 18:35:13 +00:00
if ( type = = VIDEO ) {
config . preferredAssetRepresentationMode = PHPickerConfigurationAssetRepresentationModeCurrent ;
}
2020-09-23 09:23:38 +00:00
if ( multiPick ) {
config . selectionLimit = 0 ;
}
PHPickerViewController * pickerViewController = [ [ PHPickerViewController alloc ] initWithConfiguration : config ] ;
pickerViewController . delegate = self ;
2020-10-20 10:19:20 +00:00
[ self . viewController presentViewController : pickerViewController animated : YES completion : nil ] ;
2020-09-23 09:23:38 +00:00
return ;
}
2020-10-25 18:07:36 +00:00
# endif
2019-03-05 19:02:14 +00:00
2020-04-27 21:25:57 +00:00
if ( multiPick ) {
2020-07-20 14:31:14 +00:00
[ self resolveMultiPickFromGallery : type withCompressionAllowed : allowCompression ] ;
2020-04-26 20:47:49 +00:00
return ;
}
2020-04-27 21:25:57 +00:00
NSArray < NSString * > * videoTypes = @ [ ( NSString * ) kUTTypeMovie , ( NSString * ) kUTTypeAVIMovie , ( NSString * ) kUTTypeVideo , ( NSString * ) kUTTypeMPEG4 ] ;
NSArray < NSString * > * imageTypes = @ [ ( NSString * ) kUTTypeImage ] ;
2020-04-26 20:47:49 +00:00
self . galleryPickerController = [ [ UIImagePickerController alloc ] init ] ;
self . galleryPickerController . delegate = self ;
self . galleryPickerController . videoQuality = UIImagePickerControllerQualityTypeHigh ;
2020-04-27 21:25:57 +00:00
switch ( type ) {
case IMAGE :
self . galleryPickerController . mediaTypes = imageTypes ;
2020-07-20 14:31:14 +00:00
if ( @ available ( iOS 11.0 , * ) ) {
self . galleryPickerController . imageExportPreset = allowCompression ? UIImagePickerControllerImageURLExportPresetCompatible : UIImagePickerControllerImageURLExportPresetCurrent ;
}
2020-04-27 21:25:57 +00:00
break ;
2020-07-20 14:31:14 +00:00
2020-04-27 21:25:57 +00:00
case VIDEO :
self . galleryPickerController . mediaTypes = videoTypes ;
2020-07-20 14:31:14 +00:00
if ( @ available ( iOS 11.0 , * ) ) {
self . galleryPickerController . videoExportPreset = allowCompression ? AVAssetExportPresetHighestQuality : AVAssetExportPresetPassthrough ;
}
2020-04-27 21:25:57 +00:00
break ;
default :
self . galleryPickerController . mediaTypes = [ videoTypes arrayByAddingObjectsFromArray : imageTypes ] ;
break ;
}
2020-04-26 20:47:49 +00:00
[ self . viewController presentViewController : self . galleryPickerController animated : YES completion : nil ] ;
2020-09-23 09:23:38 +00:00
2020-04-26 20:47:49 +00:00
}
2020-07-20 14:31:14 +00:00
- ( void ) resolveMultiPickFromGallery : ( MediaType ) type withCompressionAllowed : ( BOOL ) allowCompression {
2020-04-26 20:47:49 +00:00
DKImagePickerController * dkImagePickerController = [ [ DKImagePickerController alloc ] init ] ;
UIAlertController * alert = [ UIAlertController alertControllerWithTitle : @ "" message : @ "" preferredStyle : UIAlertControllerStyleAlert ] ;
UIActivityIndicatorView * indicator = [ [ UIActivityIndicatorView alloc ] initWithActivityIndicatorStyle : UIActivityIndicatorViewStyleWhite ] ;
2020-06-12 01:19:25 +00:00
2020-12-13 16:19:48 +00:00
UIViewController * currentViewController = self . viewController ;
2020-06-12 01:19:25 +00:00
if ( _eventSink = = nil ) {
// Create alert dialog for asset caching
2020-12-13 16:19:48 +00:00
[ alert . view setCenter : currentViewController . view . center ] ;
2020-06-12 01:19:25 +00:00
[ alert . view addConstraint : [ NSLayoutConstraint constraintWithItem : alert . view attribute : NSLayoutAttributeHeight relatedBy : NSLayoutRelationEqual toItem : nil attribute : NSLayoutAttributeNotAnAttribute multiplier : 1 constant : 100 ] ] ;
// Create a default loader if user don ' t provide a status handler
indicator . hidesWhenStopped = YES ;
[ indicator setCenter : alert . view . center ] ;
indicator . autoresizingMask = ( UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin ) ;
[ alert . view addSubview : indicator ] ;
}
2020-04-26 20:47:49 +00:00
2020-07-20 14:31:14 +00:00
if ( @ available ( iOS 11.0 , * ) ) {
DKImageAssetExporterConfiguration * exportConfiguration = [ [ DKImageAssetExporterConfiguration alloc ] init ] ;
2021-08-31 11:02:15 +00:00
exportConfiguration . imageExportPreset = allowCompression ? DKImageExportPresentCompatible : DKImageExportPresentCurrent ;
2020-07-20 14:31:14 +00:00
exportConfiguration . videoExportPreset = allowCompression ? AVAssetExportPresetHighestQuality : AVAssetExportPresetPassthrough ;
dkImagePickerController . exporter = [ dkImagePickerController . exporter initWithConfiguration : exportConfiguration ] ;
}
2020-04-26 20:47:49 +00:00
dkImagePickerController . exportsWhenCompleted = YES ;
dkImagePickerController . showsCancelButton = YES ;
dkImagePickerController . sourceType = DKImagePickerControllerSourceTypePhoto ;
2020-04-27 21:25:57 +00:00
dkImagePickerController . assetType = type = = VIDEO ? DKImagePickerControllerAssetTypeAllVideos : type = = IMAGE ? DKImagePickerControllerAssetTypeAllPhotos : DKImagePickerControllerAssetTypeAllAssets ;
2020-04-26 20:47:49 +00:00
// Export status changed
[ dkImagePickerController setExportStatusChanged : ^ ( enum DKImagePickerControllerExportStatus status ) {
2020-04-22 21:27:46 +00:00
2020-04-26 20:47:49 +00:00
if ( status = = DKImagePickerControllerExportStatusExporting && dkImagePickerController . selectedAssets . count > 0 ) {
Log ( "Exporting assets, this operation may take a while if remote (iCloud) assets are being cached." ) ;
2020-06-12 01:19:25 +00:00
if ( self -> _eventSink ! = nil ) {
self -> _eventSink ( [ NSNumber numberWithBool : YES ] ) ;
} else {
[ indicator startAnimating ] ;
2020-12-13 16:19:48 +00:00
[ currentViewController showViewController : alert sender : nil ] ;
2020-06-12 01:19:25 +00:00
}
2020-04-26 20:47:49 +00:00
} else {
2020-06-12 01:19:25 +00:00
if ( self -> _eventSink ! = nil ) {
self -> _eventSink ( [ NSNumber numberWithBool : NO ] ) ;
} else {
[ indicator stopAnimating ] ;
[ alert dismissViewControllerAnimated : YES completion : nil ] ;
}
2020-04-26 20:47:49 +00:00
}
} ] ;
// Did cancel
[ dkImagePickerController setDidCancel : ^ ( ) {
self -> _result ( nil ) ;
self -> _result = nil ;
} ] ;
// Did select
[ dkImagePickerController setDidSelectAssets : ^ ( NSArray < DKAsset * > * __nonnull DKAssets ) {
2020-09-11 17:01:34 +00:00
NSMutableArray < NSURL * > * paths = [ [ NSMutableArray < NSURL * > alloc ] init ] ;
2020-04-22 21:27:46 +00:00
2021-03-03 22:08:52 +00:00
for ( DKAsset * asset in DKAssets ) {
if ( asset . localTemporaryPath . absoluteURL ! = nil ) {
[ paths addObject : asset . localTemporaryPath . absoluteURL ] ;
}
2020-04-25 18:00:23 +00:00
}
2020-04-26 20:47:49 +00:00
2020-09-11 17:01:34 +00:00
[ self handleResult : paths ] ;
2020-04-26 20:47:49 +00:00
} ] ;
2020-12-13 16:19:48 +00:00
[ self . viewController presentViewController : dkImagePickerController animated : YES completion : nil ] ;
2019-03-05 19:02:14 +00:00
}
2020-09-11 17:01:34 +00:00
- ( void ) resolvePickAudioWithMultiPick : ( BOOL ) isMultiPick {
2019-03-05 19:02:14 +00:00
self . audioPickerController = [ [ MPMediaPickerController alloc ] initWithMediaTypes : MPMediaTypeAnyAudio ] ;
self . audioPickerController . delegate = self ;
2020-09-11 17:01:34 +00:00
self . audioPickerController . showsCloudItems = YES ;
self . audioPickerController . allowsPickingMultipleItems = isMultiPick ;
2019-03-12 01:25:23 +00:00
2019-03-05 19:02:14 +00:00
[ self . viewController presentViewController : self . audioPickerController animated : YES completion : nil ] ;
}
2020-09-11 17:01:34 +00:00
- ( void ) handleResult : ( id ) files {
_result ( [ FileUtils resolveFileInfo : [ files isKindOfClass : [ NSArray class ] ] ? files : @ [ files ] withData : self . loadDataToMemory ] ) ;
_result = nil ;
}
2019-03-05 19:02:14 +00:00
# pragma mark - Delegates
2019-05-29 13:02:26 +00:00
// DocumentPicker delegate - iOS 10 only
- ( void ) documentPicker : ( UIDocumentPickerViewController * ) controller didPickDocumentAtURL : ( NSURL * ) url {
[ self . documentPickerController dismissViewControllerAnimated : YES completion : nil ] ;
2020-09-11 17:01:34 +00:00
[ self handleResult : url ] ;
2019-05-29 13:02:26 +00:00
}
2019-03-05 19:02:14 +00:00
// DocumentPicker delegate
2018-06-23 01:22:04 +00:00
- ( void ) documentPicker : ( UIDocumentPickerViewController * ) controller
didPickDocumentsAtURLs : ( NSArray < NSURL * > * ) urls {
2018-11-30 18:06:11 +00:00
2020-03-29 22:22:40 +00:00
if ( _result = = nil ) {
return ;
}
2019-03-11 00:01:44 +00:00
[ self . documentPickerController dismissViewControllerAnimated : YES completion : nil ] ;
2019-03-06 01:16:35 +00:00
2020-09-11 17:01:34 +00:00
if ( controller . documentPickerMode = = UIDocumentPickerModeOpen ) {
_result ( [ urls objectAtIndex : 0 ] . path ) ;
_result = nil ;
return ;
}
[ self handleResult : urls ] ;
2018-06-23 01:22:04 +00:00
}
2019-03-05 19:02:14 +00:00
// ImagePicker delegate
- ( void ) imagePickerController : ( UIImagePickerController * ) picker didFinishPickingMediaWithInfo : ( NSDictionary * ) info {
2019-11-20 00:48:53 +00:00
if ( _result = = nil ) {
return ;
}
2018-12-05 15:32:02 +00:00
2019-03-05 19:02:14 +00:00
NSURL * pickedVideoUrl = [ info objectForKey : UIImagePickerControllerMediaURL ] ;
NSURL * pickedImageUrl ;
2018-12-05 15:32:02 +00:00
2020-09-23 09:23:38 +00:00
if ( @ available ( iOS 13.0 , * ) ) {
2019-09-24 09:59:01 +00:00
if ( pickedVideoUrl ! = nil ) {
NSString * fileName = [ pickedVideoUrl lastPathComponent ] ;
NSURL * destination = [ NSURL fileURLWithPath : [ NSTemporaryDirectory ( ) stringByAppendingPathComponent : fileName ] ] ;
if ( [ [ NSFileManager defaultManager ] isReadableFileAtPath : [ pickedVideoUrl path ] ] ) {
Log ( @ "Caching video file for iOS 13 or above..." ) ;
[ [ NSFileManager defaultManager ] copyItemAtURL : pickedVideoUrl toURL : destination error : nil ] ;
pickedVideoUrl = destination ;
}
} else {
pickedImageUrl = [ info objectForKey : UIImagePickerControllerImageURL ] ;
}
} else if ( @ available ( iOS 11.0 , * ) ) {
2020-09-23 09:23:38 +00:00
pickedImageUrl = [ info objectForKey : UIImagePickerControllerImageURL ] ;
2019-03-05 19:02:14 +00:00
} else {
2020-09-23 09:23:38 +00:00
UIImage * pickedImage = [ info objectForKey : UIImagePickerControllerEditedImage ] ;
2019-03-05 19:02:14 +00:00
if ( pickedImage = = nil ) {
pickedImage = [ info objectForKey : UIImagePickerControllerOriginalImage ] ;
}
pickedImageUrl = [ ImageUtils saveTmpImage : pickedImage ] ;
}
2018-11-30 18:06:11 +00:00
2018-12-05 15:32:02 +00:00
[ picker dismissViewControllerAnimated : YES completion : NULL ] ;
2020-09-23 09:23:38 +00:00
2019-03-05 19:02:14 +00:00
if ( pickedImageUrl = = nil && pickedVideoUrl = = nil ) {
_result ( [ FlutterError errorWithCode : @ "file_picker_error"
message : @ "Temporary file could not be created"
details : nil ] ) ;
2019-03-11 00:01:44 +00:00
_result = nil ;
return ;
2019-03-05 19:02:14 +00:00
}
2020-09-11 17:01:34 +00:00
[ self handleResult : pickedVideoUrl ! = nil ? pickedVideoUrl : pickedImageUrl ] ;
2019-03-05 19:02:14 +00:00
}
2020-09-25 14:24:12 +00:00
# ifdef PHPicker
2020-09-23 09:23:38 +00:00
- ( void ) picker : ( PHPickerViewController * ) picker didFinishPicking : ( NSArray < PHPickerResult * > * ) results API_AVAILABLE ( ios ( 14 ) ) {
2020-12-10 13:00:56 +00:00
if ( self . group ! = nil ) {
return ;
}
2020-09-23 09:23:38 +00:00
Log ( @ "Picker:%@ didFinishPicking:%@" , picker , results ) ;
[ picker dismissViewControllerAnimated : YES completion : nil ] ;
if ( results . count = = 0 ) {
Log ( @ "FilePicker canceled" ) ;
_result ( nil ) ;
_result = nil ;
return ;
}
NSMutableArray < NSURL * > * urls = [ [ NSMutableArray alloc ] initWithCapacity : results . count ] ;
2020-12-10 13:00:56 +00:00
self . group = dispatch_group _create ( ) ;
2020-09-23 09:23:38 +00:00
2021-01-31 17:28:09 +00:00
if ( self -> _eventSink ! = nil ) {
self -> _eventSink ( [ NSNumber numberWithBool : YES ] ) ;
}
2020-09-23 09:23:38 +00:00
for ( PHPickerResult * result in results ) {
2020-12-10 13:00:56 +00:00
dispatch_group _enter ( _group ) ;
2020-09-29 17:03:09 +00:00
[ result . itemProvider loadFileRepresentationForTypeIdentifier : @ "public.item" completionHandler : ^ ( NSURL * _Nullable url , NSError * _Nullable error ) {
if ( url = = nil ) {
Log ( "Could not load the picked given file: %@" , error ) ;
2020-12-10 13:00:56 +00:00
dispatch_group _leave ( self -> _group ) ;
2020-09-29 17:03:09 +00:00
return ;
}
NSString * filename = url . lastPathComponent ;
NSString * cachedFile = [ NSTemporaryDirectory ( ) stringByAppendingPathComponent : filename ] ;
NSFileManager * fileManager = NSFileManager . defaultManager ;
if ( [ fileManager fileExistsAtPath : cachedFile ] ) {
[ fileManager removeItemAtPath : cachedFile error : NULL ] ;
}
NSURL * cachedUrl = [ NSURL fileURLWithPath : cachedFile ] ;
NSError * copyError ;
[ NSFileManager . defaultManager copyItemAtURL : url
toURL : cachedUrl
error : & copyError ] ;
2020-10-25 18:07:36 +00:00
2020-09-29 17:03:09 +00:00
if ( copyError ) {
Log ( "%@ Error while caching picked file: %@" , self , copyError ) ;
return ;
}
[ urls addObject : cachedUrl ] ;
2020-12-10 13:00:56 +00:00
dispatch_group _leave ( self -> _group ) ;
2020-09-23 09:23:38 +00:00
} ] ;
}
2020-12-10 13:00:56 +00:00
dispatch_group _notify ( _group , dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _DEFAULT , 0 ) , ^ {
self -> _group = nil ;
2021-01-31 17:28:09 +00:00
if ( self -> _eventSink ! = nil ) {
self -> _eventSink ( [ NSNumber numberWithBool : NO ] ) ;
}
2020-09-23 09:23:38 +00:00
[ self handleResult : urls ] ;
} ) ;
}
2020-09-25 14:24:12 +00:00
# endif
2019-03-05 19:02:14 +00:00
// AudioPicker delegate
- ( void ) mediaPicker : ( MPMediaPickerController * ) mediaPicker didPickMediaItems : ( MPMediaItemCollection * ) mediaItemCollection
{
[ mediaPicker dismissViewControllerAnimated : YES completion : NULL ] ;
2020-10-25 18:07:36 +00:00
int numberOfItems = ( int ) [ mediaItemCollection items ] . count ;
if ( numberOfItems = = 0 ) {
return ;
}
if ( _eventSink ! = nil ) {
_eventSink ( [ NSNumber numberWithBool : YES ] ) ;
}
NSMutableArray < NSURL * > * urls = [ [ NSMutableArray alloc ] initWithCapacity : numberOfItems ] ;
2020-09-11 17:01:34 +00:00
for ( MPMediaItemCollection * item in [ mediaItemCollection items ] ) {
2020-10-25 18:07:36 +00:00
NSURL * cachedAsset = [ FileUtils exportMusicAsset : [ item valueForKey : MPMediaItemPropertyAssetURL ] withName : [ item valueForKey : MPMediaItemPropertyTitle ] ] ;
[ urls addObject : cachedAsset ] ;
}
if ( _eventSink ! = nil ) {
_eventSink ( [ NSNumber numberWithBool : NO ] ) ;
2020-09-11 17:01:34 +00:00
}
2020-09-23 09:23:38 +00:00
2020-09-11 17:01:34 +00:00
if ( urls . count = = 0 ) {
2019-03-12 01:25:23 +00:00
Log ( @ "Couldn't retrieve the audio file path, either is not locally downloaded or the file is DRM protected." ) ;
2019-03-05 19:02:14 +00:00
}
2020-09-11 17:01:34 +00:00
[ self handleResult : urls ] ;
2019-03-05 19:02:14 +00:00
}
# pragma mark - Actions canceled
- ( void ) mediaPickerDidCancel : ( MPMediaPickerController * ) controller {
2019-03-08 01:42:07 +00:00
Log ( @ "FilePicker canceled" ) ;
_result ( nil ) ;
2019-03-05 19:02:14 +00:00
_result = nil ;
[ controller dismissViewControllerAnimated : YES completion : NULL ] ;
2018-06-23 01:22:04 +00:00
}
2018-12-27 14:02:24 +00:00
- ( void ) documentPickerWasCancelled : ( UIDocumentPickerViewController * ) controller {
2019-03-08 01:42:07 +00:00
Log ( @ "FilePicker canceled" ) ;
_result ( nil ) ;
2018-12-27 14:02:24 +00:00
_result = nil ;
[ controller dismissViewControllerAnimated : YES completion : NULL ] ;
}
2018-12-05 15:32:02 +00:00
- ( void ) imagePickerControllerDidCancel : ( UIImagePickerController * ) picker {
2019-03-08 01:42:07 +00:00
Log ( @ "FilePicker canceled" ) ;
_result ( nil ) ;
2018-12-27 14:02:24 +00:00
_result = nil ;
2018-12-05 15:32:02 +00:00
[ picker dismissViewControllerAnimated : YES completion : NULL ] ;
2018-06-23 01:22:04 +00:00
}
2020-04-26 20:47:49 +00:00
# pragma mark - Alert dialog
2018-06-23 01:22:04 +00:00
@ end