Skip to content
This repository was archived by the owner on May 15, 2024. It is now read-only.
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 70 additions & 34 deletions Xamarin.Essentials/MediaPicker/MediaPicker.ios.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -29,53 +30,75 @@ static Task<FileResult> PlatformCaptureVideoAsync(MediaPickerOptions options)

static async Task<FileResult> 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<Permissions.Microphone>();
var tcs = new TaskCompletionSource<FileResult>();

// permission is not required on iOS 11 for the picker
if (!Platform.HasOSVersion(11, 0))
if (Platform.HasOSVersion(14, 0))
{
await Permissions.EnsureGrantedAsync<Permissions.Photos>();
}
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<Permissions.Microphone>();

// permission is not required on iOS 11 for the picker
if (!Platform.HasOSVersion(11, 0))
await Permissions.EnsureGrantedAsync<Permissions.Photos>();

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<FileResult>(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;
}
Expand Down Expand Up @@ -134,6 +157,11 @@ static FileResult DictionaryToMediaFile(NSDictionary info)
return new PHAssetFileResult(assetUrl, phAsset, originalFilename);
}

static FileResult PickerResultsToMediaFile(PHPickerResult[] results)
{
throw new NotImplementedException();
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jamesmontemagno @mattleibow @Redth This is implemented in #1750

}

class PhotoPickerDelegate : UIImagePickerControllerDelegate
{
public Action<NSDictionary> CompletedHandler { get; set; }
Expand All @@ -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<PHPickerResult[]> CompletedHandler { get; set; }

public override void DidFinishPicking(PHPickerViewController picker, PHPickerResult[] results) =>
CompletedHandler?.Invoke(results?.Length > 0 ? results : null);
}
}
}