-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change picker to Finder for import when running on macOS #5
base: rma-androidx-33
Are you sure you want to change the base?
Changes from all commits
97b1622
83201a3
5e96c30
09fb0bc
779debf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ Licensed to the Apache Software Foundation (ASF) under one | |
#import <objc/message.h> | ||
#import <Photos/Photos.h> | ||
#import <PhotosUI/PhotosUI.h> | ||
#import <UniformTypeIdentifiers/UTCoreTypes.h> | ||
|
||
#ifndef __CORDOVA_4_0_0 | ||
#import <Cordova/NSData+Base64.h> | ||
|
@@ -218,7 +219,17 @@ - (void)takePicture:(CDVInvokedUrlCommand*)command | |
CDVGalleryPicker* picker = [CDVGalleryPicker createFromPictureOptions:pictureOptions]; | ||
picker.callbackId = command.callbackId; | ||
weakSelf.galleryPicker = picker; | ||
picker.pickerViewController.delegate = weakSelf; | ||
|
||
if ([picker.pickerViewController isKindOfClass:[PHPickerViewController class]]) { | ||
PHPickerViewController* controller = (PHPickerViewController*) picker.pickerViewController; | ||
controller.delegate = weakSelf; | ||
} else if ([picker.pickerViewController isKindOfClass:[UIDocumentPickerViewController class]]) { | ||
UIDocumentPickerViewController* controller = (UIDocumentPickerViewController*) picker.pickerViewController; | ||
controller.delegate = weakSelf; | ||
} else { | ||
NSLog(@"FIA: no class matched"); | ||
} | ||
|
||
|
||
[weakSelf.viewController presentViewController:picker.pickerViewController animated:true completion:^{ | ||
weakSelf.hasPendingOperation = NO; | ||
|
@@ -459,56 +470,99 @@ - (NSData*)processImage:(UIImage*)image info:(NSDictionary*)info options:(CDVPic | |
return data; | ||
} | ||
|
||
- (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results API_AVAILABLE(ios(14)) { | ||
- (void)documentPicker:(UIDocumentPickerViewController *)controller | ||
didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls; { | ||
__weak CDVCamera* weakSelf = self; | ||
|
||
if (urls.count > 0) { | ||
NSURL *fileURL = [urls firstObject]; | ||
|
||
NSError *error; | ||
NSData *data = [NSData dataWithContentsOfURL:fileURL options:NSDataReadingMappedIfSafe error:&error]; | ||
|
||
if (error) { | ||
[self sendErrorResultWithMessage]; | ||
return; | ||
} | ||
|
||
// Create a UIImage from the data | ||
UIImage *original = [[UIImage alloc] initWithData:data]; | ||
[self handleImageFromPicker:original withData:data]; | ||
} else { | ||
[self sendErrorResultWithMessage]; | ||
} | ||
} | ||
|
||
- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller; { | ||
[self sendErrorResultWithMessage]; | ||
} | ||
|
||
- (void)sendErrorResultWithMessage { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does more than the naming implies. More like onEndSelectionWithoutImage. And use it also in other instances (e.g. insisde picker:didFinishPicking:) |
||
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No Image Selected"]; | ||
[self.commandDelegate sendPluginResult:result callbackId:self.galleryPicker.callbackId]; | ||
|
||
// Reset any pending operation state | ||
self.hasPendingOperation = NO; | ||
self.galleryPicker = nil; | ||
} | ||
|
||
- (void)handleImageFromPicker:(UIImage *)original withData:(NSData *)data { | ||
|
||
__weak CDVCamera* weakSelf = self; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Weak reference is unncessary at this point. |
||
|
||
UIImage* image = [weakSelf conformImage:original toOptions:weakSelf.galleryPicker.pictureOptions]; | ||
|
||
NSData* processedImageData = nil; | ||
switch (weakSelf.galleryPicker.pictureOptions.encodingType) { | ||
case EncodingTypePNG: | ||
processedImageData = UIImagePNGRepresentation(image); | ||
break; | ||
case EncodingTypeJPEG: | ||
processedImageData = UIImageJPEGRepresentation(image, weakSelf.galleryPicker.pictureOptions.quality.floatValue / 100.0f); | ||
break; | ||
default: | ||
NSAssert(NO, @"Missing implementation for encoding type (fallback to jpg)"); | ||
processedImageData = UIImageJPEGRepresentation(image, weakSelf.galleryPicker.pictureOptions.quality.floatValue / 100.0f); | ||
} | ||
CGImageSourceRef processedImageSource = CGImageSourceCreateWithData((__bridge CFDataRef) processedImageData, NULL); | ||
|
||
NSDictionary* completeMetadata = [self convertImageMetadata:data]; | ||
NSDictionary* metadata = [self filterImageMetadataFrom:completeMetadata]; | ||
|
||
NSMutableData* imageDataWithExif = [NSMutableData data]; | ||
CFStringRef fileFormat = kuTTypeFromCDVEncodingType(weakSelf.galleryPicker.pictureOptions.encodingType); | ||
|
||
CGImageDestinationRef destinationImage = CGImageDestinationCreateWithData((__bridge CFMutableDataRef) imageDataWithExif, fileFormat, 1, NULL); | ||
CGImageDestinationAddImageFromSource(destinationImage, processedImageSource, 0, (__bridge CFDictionaryRef) metadata); | ||
CGImageDestinationFinalize(destinationImage); | ||
|
||
CFRelease(processedImageSource); | ||
CFRelease(destinationImage); | ||
|
||
NSString* extension = ExtensionFromCDVEncodingType(weakSelf.galleryPicker.pictureOptions.encodingType); | ||
NSString* filePath = [self tempFilePath:extension]; | ||
NSError* err = nil; | ||
|
||
CDVPluginResult* result = nil; | ||
if (![imageDataWithExif writeToFile:filePath options:NSAtomicWrite error:&err]) { | ||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]]; | ||
} else { | ||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[self urlTransformer:[NSURL fileURLWithPath:filePath]] absoluteString]]; | ||
} | ||
|
||
[weakSelf.commandDelegate sendPluginResult:result callbackId:weakSelf.galleryPicker.callbackId]; | ||
weakSelf.hasPendingOperation = NO; | ||
weakSelf.galleryPicker = nil; | ||
} | ||
|
||
- (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results API_AVAILABLE(ios(14)) { | ||
|
||
|
||
[picker dismissViewControllerAnimated:YES completion:^{ | ||
if (results.count > 0 && [results.firstObject.itemProvider hasItemConformingToTypeIdentifier:(NSString*)kUTTypeImage]) { | ||
[results.firstObject.itemProvider loadDataRepresentationForTypeIdentifier:(NSString*)kUTTypeImage completionHandler:^(NSData* data, NSError* error) { | ||
UIImage* original = [[UIImage alloc] initWithData:data]; | ||
UIImage* image = [weakSelf conformImage:original toOptions:weakSelf.galleryPicker.pictureOptions]; | ||
|
||
NSData* processedImageData = nil; | ||
switch (weakSelf.galleryPicker.pictureOptions.encodingType) { | ||
case EncodingTypePNG: | ||
processedImageData = UIImagePNGRepresentation(image); | ||
break; | ||
case EncodingTypeJPEG: | ||
processedImageData = UIImageJPEGRepresentation(image, weakSelf.galleryPicker.pictureOptions.quality.floatValue / 100.0f); | ||
break; | ||
default: | ||
NSAssert(NO, @"Missing implementation for encoding type (fallback to jpg)"); | ||
processedImageData = UIImageJPEGRepresentation(image, weakSelf.galleryPicker.pictureOptions.quality.floatValue / 100.0f); | ||
} | ||
CGImageSourceRef processedImageSource = CGImageSourceCreateWithData((__bridge CFDataRef) processedImageData, NULL); | ||
|
||
NSDictionary* completeMetadata = [self convertImageMetadata:data]; | ||
NSDictionary* metadata = [self filterImageMetadataFrom:completeMetadata]; | ||
|
||
NSMutableData* imageDataWithExif = [NSMutableData data]; | ||
CFStringRef fileFormat = kuTTypeFromCDVEncodingType(weakSelf.galleryPicker.pictureOptions.encodingType); | ||
|
||
CGImageDestinationRef destinationImage = CGImageDestinationCreateWithData((__bridge CFMutableDataRef) imageDataWithExif, fileFormat, 1, NULL); | ||
CGImageDestinationAddImageFromSource(destinationImage, processedImageSource, 0, (__bridge CFDictionaryRef) metadata); | ||
CGImageDestinationFinalize(destinationImage); | ||
|
||
CFRelease(processedImageSource); | ||
CFRelease(destinationImage); | ||
|
||
NSString* extension = ExtensionFromCDVEncodingType(weakSelf.galleryPicker.pictureOptions.encodingType); | ||
NSString* filePath = [self tempFilePath:extension]; | ||
NSError* err = nil; | ||
|
||
CDVPluginResult* result = nil; | ||
if (![imageDataWithExif writeToFile:filePath options:NSAtomicWrite error:&err]) { | ||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]]; | ||
} else { | ||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[self urlTransformer:[NSURL fileURLWithPath:filePath]] absoluteString]]; | ||
} | ||
|
||
[weakSelf.commandDelegate sendPluginResult:result callbackId:weakSelf.galleryPicker.callbackId]; | ||
weakSelf.hasPendingOperation = NO; | ||
weakSelf.galleryPicker = nil; | ||
[self handleImageFromPicker:original withData:data]; | ||
}]; | ||
} else { | ||
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No Image Selected"]; | ||
|
@@ -969,11 +1023,23 @@ + (instancetype) createFromPictureOptions:(CDVPictureOptions*)pictureOptions { | |
CDVGalleryPicker* instance = [[CDVGalleryPicker alloc] init]; | ||
instance.pictureOptions = pictureOptions; | ||
|
||
PHPickerConfiguration* singleImage = [[PHPickerConfiguration alloc] initWithPhotoLibrary:PHPhotoLibrary.sharedPhotoLibrary]; | ||
singleImage.filter = PHPickerFilter.imagesFilter; | ||
singleImage.selectionLimit = 1; | ||
instance.pickerViewController = [[PHPickerViewController alloc] initWithConfiguration:singleImage]; | ||
instance.pickerViewController.presentationController.delegate = instance; | ||
NSProcessInfo *processInfo = [NSProcessInfo processInfo]; | ||
|
||
if ((processInfo.isMacCatalystApp || processInfo.iOSAppOnMac)) { | ||
// Running on macOS under Mac Catalyst, use UIDocumentPickerViewController for image selection | ||
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initForOpeningContentTypes:@[UTTypeImage]]; | ||
documentPicker.allowsMultipleSelection = NO; | ||
instance.pickerViewController = documentPicker; // Store as generic view controller | ||
instance.pickerViewController.presentationController.delegate = instance; | ||
} else { | ||
// Use PHPickerViewController for image selection | ||
PHPickerConfiguration* singleImage = [[PHPickerConfiguration alloc] initWithPhotoLibrary:PHPhotoLibrary.sharedPhotoLibrary]; | ||
singleImage.filter = PHPickerFilter.imagesFilter; | ||
singleImage.selectionLimit = 1; | ||
PHPickerViewController *photoPicker = [[PHPickerViewController alloc] initWithConfiguration:singleImage]; | ||
instance.pickerViewController = photoPicker; // Store as generic view controller | ||
instance.pickerViewController.presentationController.delegate = instance; | ||
} | ||
|
||
return instance; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't used anywhere.