This is an automated email from the ASF dual-hosted git repository.

manuelbeck pushed a commit to branch pr-phpickerviewcontroller-since-ios-14
in repository https://gitbox.apache.org/repos/asf/cordova-plugin-camera.git

commit e087231d6d5897f407099e588da2a2c1f15ff649
Author: Manuel Beck <[email protected]>
AuthorDate: Thu Dec 4 00:20:03 2025 +0100

    feat(ios): integrate `PHPickerViewController` for photo library on iOS 14+
    
    - Does not need any permissions for reading images
    - The PHPickerViewController class is an alternative to 
UIImagePickerController. PHPickerViewController improves stability and 
reliability, and includes several benefits to developers and users, such as the 
following:
    - Deferred image loading and recovery UI
    - Reliable handling of large and complex assets, like RAW and panoramic 
images
    - User-selectable assets that aren’t available for UIImagePickerController
    - Configuration of the picker to display only Live Photos
    - Availability of PHLivePhoto objects without library access
    - Stricter validations against invalid inputs
    - See documentation of PHPickerViewController: 
https://developer.apple.com/documentation/photosui/phpickerviewcontroller?language=objc
    - Added tests for PHPickerViewController in `CameraTest.m`
---
 src/ios/CDVCamera.h                                |  15 +-
 src/ios/CDVCamera.m                                | 249 +++++++++++++++++++--
 .../CDVCameraTest/CDVCameraLibTests/CameraTest.m   | 135 ++++++++++-
 3 files changed, 375 insertions(+), 24 deletions(-)

diff --git a/src/ios/CDVCamera.h b/src/ios/CDVCamera.h
index 647ffab..cbc634d 100644
--- a/src/ios/CDVCamera.h
+++ b/src/ios/CDVCamera.h
@@ -21,6 +21,10 @@
 #import <CoreLocation/CoreLocation.h>
 #import <CoreLocation/CLLocationManager.h>
 #import <Cordova/CDVPlugin.h>
+// Since iOS 14, we can use PHPickerViewController to select images from the 
photo library
+#if __has_include(<PhotosUI/PhotosUI.h>)
+#import <PhotosUI/PhotosUI.h>
+#endif
 
 enum CDVDestinationType {
     DestinationTypeDataUrl = 0,
@@ -78,12 +82,21 @@ typedef NSUInteger CDVMediaType;
 @end
 
 // ======================================================================= //
-
+// Since iOS 14, we can use PHPickerViewController to select images from the 
photo library
+#if __has_include(<PhotosUI/PhotosUI.h>)
+@interface CDVCamera : CDVPlugin <UIImagePickerControllerDelegate,
+                       UINavigationControllerDelegate,
+                       UIPopoverControllerDelegate,
+                       CLLocationManagerDelegate,
+                       PHPickerViewControllerDelegate>
+{}
+#else
 @interface CDVCamera : CDVPlugin <UIImagePickerControllerDelegate,
                        UINavigationControllerDelegate,
                        UIPopoverControllerDelegate,
                        CLLocationManagerDelegate>
 {}
+#endif
 
 @property (strong) CDVCameraPicker* pickerController;
 @property (strong) NSMutableDictionary *metadata;
diff --git a/src/ios/CDVCamera.m b/src/ios/CDVCamera.m
index 9fb6c73..e19881e 100644
--- a/src/ios/CDVCamera.m
+++ b/src/ios/CDVCamera.m
@@ -30,6 +30,10 @@
 #import <MobileCoreServices/UTCoreTypes.h>
 #import <objc/message.h>
 #import <Photos/Photos.h>
+// Since iOS 14, we can use PHPickerViewController to select images from the 
photo library
+#if __has_include(<PhotosUI/PhotosUI.h>)
+#import <PhotosUI/PhotosUI.h>
+#endif
 
 #ifndef __CORDOVA_4_0_0
     #import <Cordova/NSData+Base64.h>
@@ -184,26 +188,40 @@ static NSString* MIME_JPEG    = @"image/jpeg";
                  }
              }];
         } else {
-            [weakSelf options:pictureOptions requestPhotoPermissions:^(BOOL 
granted) {
-                if (!granted) {
-                    // Denied; show an alert
-                    dispatch_async(dispatch_get_main_queue(), ^{
-                        UIAlertController *alertController = 
[UIAlertController alertControllerWithTitle:[[NSBundle mainBundle] 
objectForInfoDictionaryKey:@"CFBundleDisplayName"] 
message:NSLocalizedString(@"Access to the camera roll has been prohibited; 
please enable it in the Settings to continue.", nil) 
preferredStyle:UIAlertControllerStyleAlert];
-                        [alertController addAction:[UIAlertAction 
actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault 
handler:^(UIAlertAction * _Nonnull action) {
-                            [weakSelf 
sendNoPermissionResult:command.callbackId];
-                        }]];
-                        [alertController addAction:[UIAlertAction 
actionWithTitle:NSLocalizedString(@"Settings", nil) 
style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
-                            [[UIApplication sharedApplication] openURL:[NSURL 
URLWithString:UIApplicationOpenSettingsURLString]];
-                            [weakSelf 
sendNoPermissionResult:command.callbackId];
-                        }]];
-                        [weakSelf.viewController 
presentViewController:alertController animated:YES completion:nil];
-                    });
-                } else {
-                    dispatch_async(dispatch_get_main_queue(), ^{
-                        [weakSelf showCameraPicker:command.callbackId 
withOptions:pictureOptions];
-                    });
-                }
-            }];
+            // For photo library on iOS 14+, PHPickerViewController doesn't 
require permissions
+            // Only request permissions if we're on iOS < 14 or need 
UIImagePickerController
+            BOOL needsPermissionCheck = YES;
+            if (@available(iOS 14, *)) {
+                needsPermissionCheck = NO; // PHPickerViewController will be 
used, no permission needed
+            }
+            
+            if (needsPermissionCheck) {
+                [weakSelf options:pictureOptions 
requestPhotoPermissions:^(BOOL granted) {
+                    if (!granted) {
+                        // Denied; show an alert
+                        dispatch_async(dispatch_get_main_queue(), ^{
+                            UIAlertController *alertController = 
[UIAlertController alertControllerWithTitle:[[NSBundle mainBundle] 
objectForInfoDictionaryKey:@"CFBundleDisplayName"] 
message:NSLocalizedString(@"Access to the camera roll has been prohibited; 
please enable it in the Settings to continue.", nil) 
preferredStyle:UIAlertControllerStyleAlert];
+                            [alertController addAction:[UIAlertAction 
actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault 
handler:^(UIAlertAction * _Nonnull action) {
+                                [weakSelf 
sendNoPermissionResult:command.callbackId];
+                            }]];
+                            [alertController addAction:[UIAlertAction 
actionWithTitle:NSLocalizedString(@"Settings", nil) 
style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
+                                [[UIApplication sharedApplication] 
openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
+                                [weakSelf 
sendNoPermissionResult:command.callbackId];
+                            }]];
+                            [weakSelf.viewController 
presentViewController:alertController animated:YES completion:nil];
+                        });
+                    } else {
+                        dispatch_async(dispatch_get_main_queue(), ^{
+                            [weakSelf showCameraPicker:command.callbackId 
withOptions:pictureOptions];
+                        });
+                    }
+                }];
+            } else {
+                // iOS 14+ with PHPickerViewController - no permission needed, 
show picker directly
+                dispatch_async(dispatch_get_main_queue(), ^{
+                    [weakSelf showCameraPicker:command.callbackId 
withOptions:pictureOptions];
+                });
+            }
         }
     }];
 }
@@ -212,6 +230,15 @@ static NSString* MIME_JPEG    = @"image/jpeg";
 {
     // Perform UI operations on the main thread
     dispatch_async(dispatch_get_main_queue(), ^{
+     // Use PHPickerViewController for photo library on iOS 14+
+#if __has_include(<PhotosUI/PhotosUI.h>)
+        if (pictureOptions.sourceType == 
UIImagePickerControllerSourceTypePhotoLibrary) {
+            [self showPHPicker:callbackId withOptions:pictureOptions];
+            return;
+        }
+#endif
+        
+        // Fallback to UIImagePickerController for camera or older iOS versions
         CDVCameraPicker* cameraPicker = [CDVCameraPicker 
createFromPictureOptions:pictureOptions];
         self.pickerController = cameraPicker;
 
@@ -242,6 +269,40 @@ static NSString* MIME_JPEG    = @"image/jpeg";
     });
 }
 
+// Since iOS 14, we can use PHPickerViewController to select images from the 
photo library
+#if __has_include(<PhotosUI/PhotosUI.h>)
+- (void)showPHPicker:(NSString*)callbackId 
withOptions:(CDVPictureOptions*)pictureOptions API_AVAILABLE(ios(14))
+{
+    PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init];
+    
+    // Configure filter based on media type
+    if (pictureOptions.mediaType == MediaTypeVideo) {
+        config.filter = [PHPickerFilter videosFilter];
+    } else if (pictureOptions.mediaType == MediaTypeAll) {
+        config.filter = [PHPickerFilter anyFilterMatchingSubfilters:@[
+            [PHPickerFilter imagesFilter],
+            [PHPickerFilter videosFilter]
+        ]];
+    } else {
+        config.filter = [PHPickerFilter imagesFilter];
+    }
+    
+    config.selectionLimit = 1;
+    config.preferredAssetRepresentationMode = 
PHPickerConfigurationAssetRepresentationModeCurrent;
+    
+    PHPickerViewController *picker = [[PHPickerViewController alloc] 
initWithConfiguration:config];
+    picker.delegate = self;
+    
+    // Store callback ID and options
+    objc_setAssociatedObject(picker, "callbackId", callbackId, 
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    objc_setAssociatedObject(picker, "pictureOptions", pictureOptions, 
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    
+    [self.viewController presentViewController:picker animated:YES 
completion:^{
+        self.hasPendingOperation = NO;
+    }];
+}
+#endif
+
 - (void)sendNoPermissionResult:(NSString*)callbackId
 {
     CDVPluginResult* result = [CDVPluginResult 
resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to 
camera"];   // error callback expects string ATM
@@ -898,6 +959,154 @@ static NSString* MIME_JPEG    = @"image/jpeg";
     }
 }
 
+#if __has_include(<PhotosUI/PhotosUI.h>)
+// PHPickerViewController Delegate Methods (iOS 14+)
+- (void)picker:(PHPickerViewController *)picker 
didFinishPicking:(NSArray<PHPickerResult *> *)results API_AVAILABLE(ios(14))
+{
+    NSString *callbackId = objc_getAssociatedObject(picker, "callbackId");
+    CDVPictureOptions *pictureOptions = objc_getAssociatedObject(picker, 
"pictureOptions");
+    
+    __weak CDVCamera* weakSelf = self;
+    
+    [picker dismissViewControllerAnimated:YES completion:^{
+        if (results.count == 0) {
+            // User cancelled
+            CDVPluginResult* result = [CDVPluginResult 
resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No Image Selected"];
+            [weakSelf.commandDelegate sendPluginResult:result 
callbackId:callbackId];
+            weakSelf.hasPendingOperation = NO;
+            return;
+        }
+        
+        PHPickerResult *pickerResult = results.firstObject;
+        
+        // Check if it's a video
+        if ([pickerResult.itemProvider 
hasItemConformingToTypeIdentifier:UTTypeMovie.identifier]) {
+            [pickerResult.itemProvider 
loadFileRepresentationForTypeIdentifier:UTTypeMovie.identifier 
completionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) {
+                if (error) {
+                    CDVPluginResult* result = [CDVPluginResult 
resultWithStatus:CDVCommandStatus_ERROR messageAsString:[error 
localizedDescription]];
+                    [weakSelf.commandDelegate sendPluginResult:result 
callbackId:callbackId];
+                    weakSelf.hasPendingOperation = NO;
+                    return;
+                }
+                
+                dispatch_async(dispatch_get_main_queue(), ^{
+                    NSString* videoPath = [weakSelf createTmpVideo:[url path]];
+                    CDVPluginResult* result = [CDVPluginResult 
resultWithStatus:CDVCommandStatus_OK messageAsString:videoPath];
+                    [weakSelf.commandDelegate sendPluginResult:result 
callbackId:callbackId];
+                    weakSelf.hasPendingOperation = NO;
+                });
+            }];
+        }
+        // Handle image
+        else if ([pickerResult.itemProvider canLoadObjectOfClass:[UIImage 
class]]) {
+            [pickerResult.itemProvider loadObjectOfClass:[UIImage class] 
completionHandler:^(__kindof id<NSItemProviderReading>  _Nullable object, 
NSError * _Nullable error) {
+                if (error) {
+                    CDVPluginResult* result = [CDVPluginResult 
resultWithStatus:CDVCommandStatus_ERROR messageAsString:[error 
localizedDescription]];
+                    [weakSelf.commandDelegate sendPluginResult:result 
callbackId:callbackId];
+                    weakSelf.hasPendingOperation = NO;
+                    return;
+                }
+                
+                UIImage *image = (UIImage *)object;
+                
+                // Get asset identifier to fetch metadata
+                NSString *assetIdentifier = pickerResult.assetIdentifier;
+                
+                dispatch_async(dispatch_get_main_queue(), ^{
+                    [weakSelf processPHPickerImage:image 
assetIdentifier:assetIdentifier callbackId:callbackId options:pictureOptions];
+                });
+            }];
+        }
+    }];
+}
+
+- (void)processPHPickerImage:(UIImage*)image 
assetIdentifier:(NSString*)assetIdentifier callbackId:(NSString*)callbackId 
options:(CDVPictureOptions*)options API_AVAILABLE(ios(14))
+{
+    __weak CDVCamera* weakSelf = self;
+    
+    // Fetch metadata if asset identifier is available
+    if (assetIdentifier) {
+        PHFetchResult *result = [PHAsset 
fetchAssetsWithLocalIdentifiers:@[assetIdentifier] options:nil];
+        PHAsset *asset = result.firstObject;
+        
+        if (asset) {
+            PHImageRequestOptions *imageOptions = [[PHImageRequestOptions 
alloc] init];
+            imageOptions.synchronous = YES;
+            imageOptions.networkAccessAllowed = YES;
+            
+            [[PHImageManager defaultManager] requestImageDataForAsset:asset 
options:imageOptions resultHandler:^(NSData * _Nullable imageData, NSString * 
_Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable 
info) {
+                NSDictionary *metadata = nil;
+                if (imageData) {
+                    metadata = [weakSelf convertImageMetadata:imageData];
+                }
+                
+                dispatch_async(dispatch_get_main_queue(), ^{
+                    [weakSelf finalizePHPickerImage:image metadata:metadata 
callbackId:callbackId options:options];
+                });
+            }];
+            return;
+        }
+    }
+    
+    // No metadata available
+    [self finalizePHPickerImage:image metadata:nil callbackId:callbackId 
options:options];
+}
+
+- (void)finalizePHPickerImage:(UIImage*)image metadata:(NSDictionary*)metadata 
callbackId:(NSString*)callbackId options:(CDVPictureOptions*)options 
API_AVAILABLE(ios(14))
+{
+    // Process image according to options
+    UIImage *processedImage = image;
+    
+    if (options.correctOrientation) {
+        processedImage = [processedImage imageCorrectedForCaptureOrientation];
+    }
+    
+    if ((options.targetSize.width > 0) && (options.targetSize.height > 0)) {
+        if (options.cropToSize) {
+            processedImage = [processedImage 
imageByScalingAndCroppingForSize:options.targetSize];
+        } else {
+            processedImage = [processedImage 
imageByScalingNotCroppingForSize:options.targetSize];
+        }
+    }
+    
+    // Create info dictionary similar to UIImagePickerController
+    NSMutableDictionary *info = [NSMutableDictionary dictionary];
+    [info setObject:processedImage 
forKey:UIImagePickerControllerOriginalImage];
+    if (metadata) {
+        [info setObject:metadata 
forKey:@"UIImagePickerControllerMediaMetadata"];
+    }
+    
+    // Store metadata for processing
+    if (metadata) {
+        self.metadata = [[NSMutableDictionary alloc] init];
+        
+        NSMutableDictionary* EXIFDictionary = [[metadata 
objectForKey:(NSString*)kCGImagePropertyExifDictionary] mutableCopy];
+        if (EXIFDictionary) {
+            [self.metadata setObject:EXIFDictionary 
forKey:(NSString*)kCGImagePropertyExifDictionary];
+        }
+        
+        NSMutableDictionary* TIFFDictionary = [[metadata 
objectForKey:(NSString*)kCGImagePropertyTIFFDictionary] mutableCopy];
+        if (TIFFDictionary) {
+            [self.metadata setObject:TIFFDictionary 
forKey:(NSString*)kCGImagePropertyTIFFDictionary];
+        }
+        
+        NSMutableDictionary* GPSDictionary = [[metadata 
objectForKey:(NSString*)kCGImagePropertyGPSDictionary] mutableCopy];
+        if (GPSDictionary) {
+            [self.metadata setObject:GPSDictionary 
forKey:(NSString*)kCGImagePropertyGPSDictionary];
+        }
+    }
+    
+    __weak CDVCamera* weakSelf = self;
+    
+    // Process and return result
+    [self resultForImage:options info:info completion:^(CDVPluginResult* res) {
+        [weakSelf.commandDelegate sendPluginResult:res callbackId:callbackId];
+        weakSelf.hasPendingOperation = NO;
+        weakSelf.pickerController = nil;
+    }];
+}
+#endif
+
 @end
 
 @implementation CDVCameraPicker
diff --git a/tests/ios/CDVCameraTest/CDVCameraLibTests/CameraTest.m 
b/tests/ios/CDVCameraTest/CDVCameraLibTests/CameraTest.m
index d74cdba..bf76a86 100644
--- a/tests/ios/CDVCameraTest/CDVCameraLibTests/CameraTest.m
+++ b/tests/ios/CDVCameraTest/CDVCameraLibTests/CameraTest.m
@@ -22,6 +22,7 @@
 #import "CDVCamera.h"
 #import "UIImage+CropScaleOrientation.h"
 #import <MobileCoreServices/UTCoreTypes.h>
+#import <PhotosUI/PhotosUI.h>
 
 
 @interface CameraTest : XCTestCase
@@ -37,6 +38,10 @@
 - (UIImage*)retrieveImage:(NSDictionary*)info 
options:(CDVPictureOptions*)options;
 - (CDVPluginResult*)resultForImage:(CDVPictureOptions*)options 
info:(NSDictionary*)info;
 - (CDVPluginResult*)resultForVideo:(NSDictionary*)info;
+- (void)showPHPicker:(NSString*)callbackId 
withOptions:(CDVPictureOptions*)pictureOptions API_AVAILABLE(ios(14));
+- (void)processPHPickerImage:(UIImage*)image 
assetIdentifier:(NSString*)assetIdentifier callbackId:(NSString*)callbackId 
options:(CDVPictureOptions*)options API_AVAILABLE(ios(14));
+- (void)finalizePHPickerImage:(UIImage*)image metadata:(NSDictionary*)metadata 
callbackId:(NSString*)callbackId options:(CDVPictureOptions*)options 
API_AVAILABLE(ios(14));
+- (NSDictionary*)convertImageMetadata:(NSData*)imageData;
 
 @end
 
@@ -125,7 +130,7 @@
     CDVPictureOptions* pictureOptions;
     CDVCameraPicker* picker;
     
-    // Souce is Camera, and image type
+    // Source is Camera, and image type - Camera always uses 
UIImagePickerController
     
     popoverOptions = @{ @"x" : @1, @"y" : @2, @"width" : @3, @"height" : @4, 
@"popoverWidth": @200, @"popoverHeight": @300 };
     args = @[
@@ -157,7 +162,7 @@
         XCTAssertEqual(picker.cameraDevice, pictureOptions.cameraDirection);
     }
 
-    // Souce is not Camera, and all media types
+    // Source is Photo Library, and all media types - On iOS 14+ uses 
PHPicker, below uses UIImagePickerController
 
     args = @[
           @(49),
@@ -187,7 +192,7 @@
          XCTAssertEqualObjects(picker.mediaTypes, [UIImagePickerController 
availableMediaTypesForSourceType:picker.sourceType]);
     }
     
-    // Souce is not Camera, and either Image or Movie media type
+    // Source is Photo Library, and either Image or Movie media type - On iOS 
14+ uses PHPicker
 
     args = @[
              @(49),
@@ -508,4 +513,128 @@
     // TODO: usesGeolocation is not tested
 }
 
+- (void) testPHPickerAvailability API_AVAILABLE(ios(14))
+{
+    if (@available(iOS 14, *)) {
+        // Test that PHPickerViewController is available on iOS 14+
+        XCTAssertNotNil([PHPickerViewController class]);
+        
+        PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init];
+        XCTAssertNotNil(config);
+        
+        config.filter = [PHPickerFilter imagesFilter];
+        XCTAssertNotNil(config.filter);
+        
+        PHPickerViewController *picker = [[PHPickerViewController alloc] 
initWithConfiguration:config];
+        XCTAssertNotNil(picker);
+    }
+}
+
+- (void) testPHPickerConfiguration API_AVAILABLE(ios(14))
+{
+    if (@available(iOS 14, *)) {
+        // Test image filter configuration
+        PHPickerConfiguration *imageConfig = [[PHPickerConfiguration alloc] 
init];
+        imageConfig.filter = [PHPickerFilter imagesFilter];
+        imageConfig.selectionLimit = 1;
+        
+        XCTAssertNotNil(imageConfig);
+        XCTAssertEqual(imageConfig.selectionLimit, 1);
+        
+        // Test video filter configuration
+        PHPickerConfiguration *videoConfig = [[PHPickerConfiguration alloc] 
init];
+        videoConfig.filter = [PHPickerFilter videosFilter];
+        
+        XCTAssertNotNil(videoConfig.filter);
+        
+        // Test all media types configuration
+        PHPickerConfiguration *allConfig = [[PHPickerConfiguration alloc] 
init];
+        allConfig.filter = [PHPickerFilter anyFilterMatchingSubfilters:@[
+            [PHPickerFilter imagesFilter],
+            [PHPickerFilter videosFilter]
+        ]];
+        
+        XCTAssertNotNil(allConfig.filter);
+    }
+}
+
+- (void) testConvertImageMetadata
+{
+    // Create a test image
+    UIImage* testImage = [self createImage:CGRectMake(0, 0, 100, 100) 
orientation:UIImageOrientationUp];
+    NSData* imageData = UIImageJPEGRepresentation(testImage, 1.0);
+    
+    XCTAssertNotNil(imageData);
+    
+    // Test metadata conversion
+    NSDictionary* metadata = [self.plugin convertImageMetadata:imageData];
+    
+    // Metadata may be nil for generated images, but the method should not 
crash
+    // Real camera images would have EXIF data
+    XCTAssertTrue(metadata == nil || [metadata isKindOfClass:[NSDictionary 
class]]);
+}
+
+- (void) testPHPickerDelegateConformance API_AVAILABLE(ios(14))
+{
+    if (@available(iOS 14, *)) {
+        // Test that CDVCamera conforms to PHPickerViewControllerDelegate
+        XCTAssertTrue([self.plugin 
conformsToProtocol:@protocol(PHPickerViewControllerDelegate)]);
+        
+        // Test that the delegate method is implemented
+        SEL delegateSelector = @selector(picker:didFinishPicking:);
+        XCTAssertTrue([self.plugin respondsToSelector:delegateSelector]);
+    }
+}
+
+- (void) testShowPHPickerMethod API_AVAILABLE(ios(14))
+{
+    if (@available(iOS 14, *)) {
+        // Test that showPHPicker method exists
+        SEL showPHPickerSelector = @selector(showPHPicker:withOptions:);
+        XCTAssertTrue([self.plugin respondsToSelector:showPHPickerSelector]);
+        
+        // Test that processPHPickerImage method exists
+        SEL processSelector = 
@selector(processPHPickerImage:assetIdentifier:callbackId:options:);
+        XCTAssertTrue([self.plugin respondsToSelector:processSelector]);
+        
+        // Test that finalizePHPickerImage method exists
+        SEL finalizeSelector = 
@selector(finalizePHPickerImage:metadata:callbackId:options:);
+        XCTAssertTrue([self.plugin respondsToSelector:finalizeSelector]);
+    }
+}
+
+- (void) testPictureOptionsForPHPicker
+{
+    NSArray* args;
+    CDVPictureOptions* options;
+    
+    // Test options configuration for photo library (which would use PHPicker 
on iOS 14+)
+    args = @[
+             @(75),
+             @(DestinationTypeFileUri),
+             @(UIImagePickerControllerSourceTypePhotoLibrary),
+             @(800),
+             @(600),
+             @(EncodingTypeJPEG),
+             @(MediaTypePicture),
+             @NO,
+             @YES,
+             @NO,
+             [NSNull null],
+             @(UIImagePickerControllerCameraDeviceRear),
+             ];
+    
+    CDVInvokedUrlCommand* command = [[CDVInvokedUrlCommand alloc] 
initWithArguments:args callbackId:@"dummy" className:@"myclassname" 
methodName:@"mymethodname"];
+    options = [CDVPictureOptions createFromTakePictureArguments:command];
+    
+    // Verify options are correctly set for photo library source
+    XCTAssertEqual(options.sourceType, 
(int)UIImagePickerControllerSourceTypePhotoLibrary);
+    XCTAssertEqual([options.quality intValue], 75);
+    XCTAssertEqual(options.destinationType, (int)DestinationTypeFileUri);
+    XCTAssertEqual(options.targetSize.width, 800);
+    XCTAssertEqual(options.targetSize.height, 600);
+    XCTAssertEqual(options.correctOrientation, YES);
+    XCTAssertEqual(options.mediaType, (int)MediaTypePicture);
+}
+
 @end


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to