From aecf059925fe93567b7d24ed724c5b2ba4ab5252 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Tue, 27 Oct 2020 16:01:30 +0200 Subject: [PATCH 1/2] Add basic infrastructure for PhotosUI --- .../MediaPicker/MediaPicker.ios.cs | 104 ++++++++++++------ 1 file changed, 70 insertions(+), 34 deletions(-) diff --git a/Xamarin.Essentials/MediaPicker/MediaPicker.ios.cs b/Xamarin.Essentials/MediaPicker/MediaPicker.ios.cs index 4420dba4c..9d320e8fd 100644 --- a/Xamarin.Essentials/MediaPicker/MediaPicker.ios.cs +++ b/Xamarin.Essentials/MediaPicker/MediaPicker.ios.cs @@ -4,13 +4,14 @@ using Foundation; using MobileCoreServices; using Photos; +using PhotosUI; using UIKit; namespace Xamarin.Essentials { public static partial class MediaPicker { - static UIImagePickerController picker; + static UIViewController pickerRef; static bool PlatformIsCaptureSupported => UIImagePickerController.IsSourceTypeAvailable(UIImagePickerControllerSourceType.Camera); @@ -29,53 +30,75 @@ static Task PlatformCaptureVideoAsync(MediaPickerOptions options) static async Task PhotoAsync(MediaPickerOptions options, bool photo, bool pickExisting) { - var sourceType = pickExisting ? UIImagePickerControllerSourceType.PhotoLibrary : UIImagePickerControllerSourceType.Camera; - var mediaType = photo ? UTType.Image : UTType.Movie; - - if (!UIImagePickerController.IsSourceTypeAvailable(sourceType)) - throw new FeatureNotSupportedException(); - if (!UIImagePickerController.AvailableMediaTypes(sourceType).Contains(mediaType)) - throw new FeatureNotSupportedException(); + var vc = Platform.GetCurrentViewController(true); - if (!photo) - await Permissions.EnsureGrantedAsync(); + var tcs = new TaskCompletionSource(); - // permission is not required on iOS 11 for the picker - if (!Platform.HasOSVersion(11, 0)) + if (Platform.HasOSVersion(14, 0)) { - await Permissions.EnsureGrantedAsync(); - } + var config = new PHPickerConfiguration(); + config.Filter = photo + ? PHPickerFilter.ImagesFilter + : PHPickerFilter.VideosFilter; - var vc = Platform.GetCurrentViewController(true); + var picker = new PHPickerViewController(config); + picker.Delegate = new PPD + { + CompletedHandler = res => + tcs.TrySetResult(PickerResultsToMediaFile(res)) + }; - picker = new UIImagePickerController(); - picker.SourceType = sourceType; - picker.MediaTypes = new string[] { mediaType }; - picker.AllowsEditing = false; - if (!photo && !pickExisting) - picker.CameraCaptureMode = UIImagePickerControllerCameraCaptureMode.Video; + pickerRef = picker; + } + else + { + var sourceType = pickExisting + ? UIImagePickerControllerSourceType.PhotoLibrary + : UIImagePickerControllerSourceType.Camera; + var mediaType = photo ? UTType.Image : UTType.Movie; + + if (!UIImagePickerController.IsSourceTypeAvailable(sourceType)) + throw new FeatureNotSupportedException(); + if (!UIImagePickerController.AvailableMediaTypes(sourceType).Contains(mediaType)) + throw new FeatureNotSupportedException(); + + if (!photo) + await Permissions.EnsureGrantedAsync(); + + // permission is not required on iOS 11 for the picker + if (!Platform.HasOSVersion(11, 0)) + await Permissions.EnsureGrantedAsync(); + + var picker = new UIImagePickerController(); + picker.SourceType = sourceType; + picker.MediaTypes = new string[] { mediaType }; + picker.AllowsEditing = false; + if (!photo && !pickExisting) + picker.CameraCaptureMode = UIImagePickerControllerCameraCaptureMode.Video; + + picker.Delegate = new PhotoPickerDelegate + { + CompletedHandler = info => + tcs.TrySetResult(DictionaryToMediaFile(info)) + }; - if (!string.IsNullOrWhiteSpace(options?.Title)) - picker.Title = options.Title; + pickerRef = picker; + } - if (DeviceInfo.Idiom == DeviceIdiom.Tablet && picker.PopoverPresentationController != null && vc.View != null) - picker.PopoverPresentationController.SourceRect = vc.View.Bounds; + if (!string.IsNullOrWhiteSpace(options?.Title)) + pickerRef.Title = options.Title; - var tcs = new TaskCompletionSource(picker); - picker.Delegate = new PhotoPickerDelegate - { - CompletedHandler = info => - tcs.TrySetResult(DictionaryToMediaFile(info)) - }; + if (DeviceInfo.Idiom == DeviceIdiom.Tablet && pickerRef.PopoverPresentationController != null && vc.View != null) + pickerRef.PopoverPresentationController.SourceRect = vc.View.Bounds; - await vc.PresentViewControllerAsync(picker, true); + await vc.PresentViewControllerAsync(pickerRef, true); var result = await tcs.Task; await vc.DismissViewControllerAsync(true); - picker?.Dispose(); - picker = null; + pickerRef?.Dispose(); + pickerRef = null; return result; } @@ -134,6 +157,11 @@ static FileResult DictionaryToMediaFile(NSDictionary info) return new PHAssetFileResult(assetUrl, phAsset, originalFilename); } + static FileResult PickerResultsToMediaFile(PHPickerResult[] results) + { + throw new NotImplementedException(); + } + class PhotoPickerDelegate : UIImagePickerControllerDelegate { public Action CompletedHandler { get; set; } @@ -144,5 +172,13 @@ public override void FinishedPickingMedia(UIImagePickerController picker, NSDict public override void Canceled(UIImagePickerController picker) => CompletedHandler?.Invoke(null); } + + class PPD : PHPickerViewControllerDelegate + { + public Action CompletedHandler { get; set; } + + public override void DidFinishPicking(PHPickerViewController picker, PHPickerResult[] results) => + CompletedHandler?.Invoke(results.Length == 0 ? null : results); + } } } From 5fea901846ed9f8801348be5ae6d7ebade2fed54 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Tue, 27 Oct 2020 16:49:08 +0200 Subject: [PATCH 2/2] Better check --- Xamarin.Essentials/MediaPicker/MediaPicker.ios.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Xamarin.Essentials/MediaPicker/MediaPicker.ios.cs b/Xamarin.Essentials/MediaPicker/MediaPicker.ios.cs index 9d320e8fd..f181c1102 100644 --- a/Xamarin.Essentials/MediaPicker/MediaPicker.ios.cs +++ b/Xamarin.Essentials/MediaPicker/MediaPicker.ios.cs @@ -178,7 +178,7 @@ class PPD : PHPickerViewControllerDelegate public Action CompletedHandler { get; set; } public override void DidFinishPicking(PHPickerViewController picker, PHPickerResult[] results) => - CompletedHandler?.Invoke(results.Length == 0 ? null : results); + CompletedHandler?.Invoke(results?.Length > 0 ? results : null); } } }