diff --git a/src/Essentials/src/FilePicker/FilePicker.android.cs b/src/Essentials/src/FilePicker/FilePicker.android.cs index 093bff802c96..7b21c5ecfe01 100644 --- a/src/Essentials/src/FilePicker/FilePicker.android.cs +++ b/src/Essentials/src/FilePicker/FilePicker.android.cs @@ -5,11 +5,11 @@ using System.Threading.Tasks; using Android.Content; -namespace Microsoft.Maui.Essentials +namespace Microsoft.Maui.Essentials.Implementations { - public static partial class FilePicker + public partial class FilePickerImplementation : IFilePicker { - static async Task> PlatformPickAsync(PickOptions options, bool allowMultiple = false) + public async Task> PickAsync(PickOptions options, bool allowMultiple = false) { // we only need the permission when accessing the file, but it's more natural // to ask the user first, then show the picker. @@ -62,36 +62,46 @@ void OnResult(Intent intent) return null; } } + + public async Task> PickMultipleAsync(PickOptions options) + { + return await PickAsync(options, true); + } } - public partial class FilePickerFileType + public partial class FilePickerFileTypeImplementation : IFilePickerFileType { - static FilePickerFileType PlatformImageFileType() => - new FilePickerFileType(new Dictionary> + readonly IDictionary> fileTypes; + + public FilePickerFileTypeImplementation(IDictionary> fileTypes) => + this.fileTypes = fileTypes; + + public IFilePickerFileType ImageFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.Android, new[] { FileSystem.MimeTypes.ImagePng, FileSystem.MimeTypes.ImageJpg } } }); - static FilePickerFileType PlatformPngFileType() => - new FilePickerFileType(new Dictionary> + public IFilePickerFileType PngFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.Android, new[] { FileSystem.MimeTypes.ImagePng } } }); - static FilePickerFileType PlatformJpegFileType() => - new FilePickerFileType(new Dictionary> + public IFilePickerFileType JpegFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.Android, new[] { FileSystem.MimeTypes.ImageJpg } } }); - static FilePickerFileType PlatformVideoFileType() => - new FilePickerFileType(new Dictionary> + public IFilePickerFileType VideoFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.Android, new[] { FileSystem.MimeTypes.VideoAll } } }); - static FilePickerFileType PlatformPdfFileType() => - new FilePickerFileType(new Dictionary> + public IFilePickerFileType PdfFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.Android, new[] { FileSystem.MimeTypes.Pdf } } }); diff --git a/src/Essentials/src/FilePicker/FilePicker.ios.cs b/src/Essentials/src/FilePicker/FilePicker.ios.cs index f71957b659a3..aa2bf6358d8e 100644 --- a/src/Essentials/src/FilePicker/FilePicker.ios.cs +++ b/src/Essentials/src/FilePicker/FilePicker.ios.cs @@ -8,11 +8,11 @@ using ObjCRuntime; using UIKit; -namespace Microsoft.Maui.Essentials +namespace Microsoft.Maui.Essentials.Implementations { - public static partial class FilePicker + public partial class FilePickerImplementation : IFilePicker { - static async Task> PlatformPickAsync(PickOptions options, bool allowMultiple = false) + public async Task> PickAsync(PickOptions options, bool allowMultiple = false) { var allowedUtis = options?.FileTypes?.Value?.ToArray() ?? new string[] { @@ -46,6 +46,11 @@ static async Task> PlatformPickAsync(PickOptions options return await tcs.Task; } + public async Task> PickMultipleAsync(PickOptions options) + { + return await PickAsync(options, true); + } + static async void GetFileResults(NSUrl[] urls, TaskCompletionSource> tcs) { try @@ -76,34 +81,39 @@ public override void DidPickDocument(UIDocumentPickerViewController controller, } - public partial class FilePickerFileType + public partial class FilePickerFileTypeImplementation : IFilePickerFileType { - static FilePickerFileType PlatformImageFileType() => - new FilePickerFileType(new Dictionary> + readonly IDictionary> fileTypes; + + public FilePickerFileTypeImplementation(IDictionary> fileTypes) => + this.fileTypes = fileTypes; + + public IFilePickerFileType ImageFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.iOS, new[] { (string)UTType.Image } } }); - static FilePickerFileType PlatformPngFileType() => - new FilePickerFileType(new Dictionary> + public IFilePickerFileType PngFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.iOS, new[] { (string)UTType.PNG } } }); - static FilePickerFileType PlatformJpegFileType() => - new FilePickerFileType(new Dictionary> + public IFilePickerFileType JpegFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.iOS, new[] { (string)UTType.JPEG } } }); - static FilePickerFileType PlatformVideoFileType() => - new FilePickerFileType(new Dictionary> + public IFilePickerFileType VideoFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.iOS, new string[] { UTType.MPEG4, UTType.Video, UTType.AVIMovie, UTType.AppleProtectedMPEG4Video, "mp4", "m4v", "mpg", "mpeg", "mp2", "mov", "avi", "mkv", "flv", "gifv", "qt" } } }); - static FilePickerFileType PlatformPdfFileType() => - new FilePickerFileType(new Dictionary> + public IFilePickerFileType PdfFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.iOS, new[] { (string)UTType.PDF } } }); diff --git a/src/Essentials/src/FilePicker/FilePicker.macos.cs b/src/Essentials/src/FilePicker/FilePicker.macos.cs index e4fded76386b..a101b0a6ab8d 100644 --- a/src/Essentials/src/FilePicker/FilePicker.macos.cs +++ b/src/Essentials/src/FilePicker/FilePicker.macos.cs @@ -4,11 +4,11 @@ using AppKit; using MobileCoreServices; -namespace Microsoft.Maui.Essentials +namespace Microsoft.Maui.Essentials.Implementations { - public static partial class FilePicker + public partial class FilePickerImplementation : IFilePicker { - static Task> PlatformPickAsync(PickOptions options, bool allowMultiple = false) + public Task> PickAsync(PickOptions options, bool allowMultiple = false) { var openPanel = new NSOpenPanel { @@ -33,7 +33,12 @@ static Task> PlatformPickAsync(PickOptions options, bool return Task.FromResult>(resultList); } - static void SetFileTypes(PickOptions options, NSOpenPanel panel) + public async Task> PickMultipleAsync(PickOptions options) + { + return await PickAsync(options, true); + } + + void SetFileTypes(PickOptions options, NSOpenPanel panel) { var allowedFileTypes = new List(); @@ -49,34 +54,34 @@ static void SetFileTypes(PickOptions options, NSOpenPanel panel) } } - public partial class FilePickerFileType + public partial class FilePickerFileTypeImplementation : IFilePickerFileType { - static FilePickerFileType PlatformImageFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation ImageFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.macOS, new string[] { UTType.PNG, UTType.JPEG, "jpeg" } } }); - static FilePickerFileType PlatformPngFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation PngFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.macOS, new string[] { UTType.PNG } } }); - static FilePickerFileType PlatformJpegFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation JpegFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.macOS, new string[] { UTType.JPEG } } }); - static FilePickerFileType PlatformVideoFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation VideoFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.macOS, new string[] { UTType.MPEG4, UTType.Video, UTType.AVIMovie, UTType.AppleProtectedMPEG4Video, "mp4", "m4v", "mpg", "mpeg", "mp2", "mov", "avi", "mkv", "flv", "gifv", "qt" } } }); - static FilePickerFileType PlatformPdfFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation PdfFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.macOS, new string[] { UTType.PDF } } }); diff --git a/src/Essentials/src/FilePicker/FilePicker.netstandard.watchos.tvos.cs b/src/Essentials/src/FilePicker/FilePicker.netstandard.watchos.tvos.cs index 5388649041e3..16e8a2dff0c0 100644 --- a/src/Essentials/src/FilePicker/FilePicker.netstandard.watchos.tvos.cs +++ b/src/Essentials/src/FilePicker/FilePicker.netstandard.watchos.tvos.cs @@ -2,31 +2,34 @@ using System.IO; using System.Threading.Tasks; -namespace Microsoft.Maui.Essentials +namespace Microsoft.Maui.Essentials.Implementations { + public partial class FilePickerImplementation : IFilePicker /// - public static partial class FilePicker { - static Task> PlatformPickAsync(PickOptions options, bool allowMultiple = false) + public Task> PickAsync(PickOptions options, bool allowMultiple = false) + => throw new NotImplementedInReferenceAssemblyException(); + + public Task> PickMultipleAsync(PickOptions options) => throw new NotImplementedInReferenceAssemblyException(); } /// - public partial class FilePickerFileType + public partial class FilePickerFileTypeImplementation : IFilePickerFileType { - static FilePickerFileType PlatformImageFileType() + public IFilePickerFileType ImageFileType() => throw new NotImplementedInReferenceAssemblyException(); - static FilePickerFileType PlatformPngFileType() + public IFilePickerFileType PngFileType() => throw new NotImplementedInReferenceAssemblyException(); - static FilePickerFileType PlatformJpegFileType() + public IFilePickerFileType JpegFileType() => throw new NotImplementedInReferenceAssemblyException(); - static FilePickerFileType PlatformVideoFileType() + public IFilePickerFileType VideoFileType() => throw new NotImplementedInReferenceAssemblyException(); - static FilePickerFileType PlatformPdfFileType() + public IFilePickerFileType PdfFileType() => throw new NotImplementedInReferenceAssemblyException(); } } diff --git a/src/Essentials/src/FilePicker/FilePicker.shared.cs b/src/Essentials/src/FilePicker/FilePicker.shared.cs index d5914da90b45..1f9f4f876b91 100644 --- a/src/Essentials/src/FilePicker/FilePicker.shared.cs +++ b/src/Essentials/src/FilePicker/FilePicker.shared.cs @@ -3,34 +3,71 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using System.ComponentModel; +using Microsoft.Maui.Essentials; +using Microsoft.Maui.Essentials.Implementations; namespace Microsoft.Maui.Essentials { + public interface IFilePicker + { + Task> PickAsync(PickOptions options, bool allowMultiple); + + Task> PickMultipleAsync(PickOptions options); + } + /// public static partial class FilePicker { /// public static async Task PickAsync(PickOptions options = null) => - (await PlatformPickAsync(options))?.FirstOrDefault(); + (await Current.PickAsync(options, false))?.FirstOrDefault(); /// public static Task> PickMultipleAsync(PickOptions options = null) => - PlatformPickAsync(options ?? PickOptions.Default, true); + Current.PickAsync(options ?? PickOptions.Default, true); + +#nullable enable + static IFilePicker? currentImplementation; +#nullable disable + + [EditorBrowsable(EditorBrowsableState.Never)] + public static IFilePicker Current => + currentImplementation ??= new FilePickerImplementation(); + + [EditorBrowsable(EditorBrowsableState.Never)] +#nullable enable + public static void SetCurrent(IFilePicker? implementation) => + currentImplementation = implementation; +#nullable disable + } + + public interface IFilePickerFileType + { + IFilePickerFileType ImageFileType(); + + IFilePickerFileType PngFileType(); + + IFilePickerFileType JpegFileType(); + + IFilePickerFileType VideoFileType(); + + IFilePickerFileType PdfFileType(); } /// public partial class FilePickerFileType { /// - public static readonly FilePickerFileType Images = PlatformImageFileType(); + public static readonly IFilePickerFileType Images = Current.ImageFileType(); /// - public static readonly FilePickerFileType Png = PlatformPngFileType(); + public static readonly IFilePickerFileType Png = Current.PngFileType(); /// - public static readonly FilePickerFileType Jpeg = PlatformJpegFileType(); + public static readonly IFilePickerFileType Jpeg = Current.JpegFileType(); /// - public static readonly FilePickerFileType Videos = PlatformVideoFileType(); + public static readonly IFilePickerFileType Videos = Current.VideoFileType(); /// - public static readonly FilePickerFileType Pdf = PlatformPdfFileType(); + public static readonly IFilePickerFileType Pdf = Current.PdfFileType(); readonly IDictionary> fileTypes; @@ -52,6 +89,20 @@ protected virtual IEnumerable GetPlatformFileType(DevicePlatform platfor throw new PlatformNotSupportedException("This platform does not support this file type."); } + +#nullable enable + static IFilePickerFileType? currentImplementation; +#nullable disable + + [EditorBrowsable(EditorBrowsableState.Never)] + public static IFilePickerFileType Current => + currentImplementation ??= new FilePickerFileTypeImplementation(); + + [EditorBrowsable(EditorBrowsableState.Never)] +#nullable enable + public static void SetCurrent(IFilePickerFileType? implementation) => + currentImplementation = implementation; +#nullable disable } /// @@ -75,6 +126,6 @@ public class PickOptions public string PickerTitle { get; set; } /// - public FilePickerFileType FileTypes { get; set; } + public IFilePickerFileType FileTypes { get; set; } } } diff --git a/src/Essentials/src/FilePicker/FilePicker.tizen.cs b/src/Essentials/src/FilePicker/FilePicker.tizen.cs index a25b2d9cae7b..4eb212937903 100644 --- a/src/Essentials/src/FilePicker/FilePicker.tizen.cs +++ b/src/Essentials/src/FilePicker/FilePicker.tizen.cs @@ -7,11 +7,11 @@ using Tizen; using Tizen.Applications; -namespace Microsoft.Maui.Essentials +namespace Microsoft.Maui.Essentials.Implementations { - public static partial class FilePicker + public partial class FilePickerImplementation : IFilePicker { - static async Task> PlatformPickAsync(PickOptions options, bool allowMultiple = false) + public async Task> PickAsync(PickOptions options, bool allowMultiple = false) { Permissions.EnsureDeclared(); await Permissions.EnsureGrantedAsync(); @@ -44,36 +44,41 @@ static async Task> PlatformPickAsync(PickOptions options return await tcs.Task; } + + public async Task> PickMultipleAsync(PickOptions options) + { + return await PickAsync(options, true); + } } - public partial class FilePickerFileType + public partial class FilePickerFileTypeImplementation : IFilePickerFileType { - static FilePickerFileType PlatformImageFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation ImageFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.Tizen, new[] { FileSystem.MimeTypes.ImageAll } }, }); - static FilePickerFileType PlatformPngFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation PngFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.Tizen, new[] { FileSystem.MimeTypes.ImagePng } } }); - static FilePickerFileType PlatformJpegFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation JpegFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.Tizen, new[] { FileSystem.MimeTypes.ImageJpg } } }); - static FilePickerFileType PlatformVideoFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation VideoFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.Tizen, new[] { FileSystem.MimeTypes.VideoAll } } }); - static FilePickerFileType PlatformPdfFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation PdfFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.Tizen, new[] { FileSystem.MimeTypes.Pdf } } }); diff --git a/src/Essentials/src/FilePicker/FilePicker.uwp.cs b/src/Essentials/src/FilePicker/FilePicker.uwp.cs index 8ff9b0186f9a..3d1db1f5eccf 100644 --- a/src/Essentials/src/FilePicker/FilePicker.uwp.cs +++ b/src/Essentials/src/FilePicker/FilePicker.uwp.cs @@ -6,11 +6,11 @@ using Windows.Storage.AccessCache; using Windows.Storage.Pickers; -namespace Microsoft.Maui.Essentials +namespace Microsoft.Maui.Essentials.Implementations { - public static partial class FilePicker + public partial class FilePickerImplementation : IFilePicker { - static async Task> PlatformPickAsync(PickOptions options, bool allowMultiple = false) + public async Task> PickAsync(PickOptions options, bool allowMultiple = false) { var picker = new FileOpenPicker { @@ -44,7 +44,12 @@ static async Task> PlatformPickAsync(PickOptions options return resultList.Select(storageFile => new FileResult(storageFile)); } - static void SetFileTypes(PickOptions options, FileOpenPicker picker) + public async Task> PickMultipleAsync(PickOptions options) + { + return await PickAsync(options, allowMultiple = true); + } + + void SetFileTypes(PickOptions options, FileOpenPicker picker) { var hasAtLeastOneType = false; @@ -66,34 +71,34 @@ static void SetFileTypes(PickOptions options, FileOpenPicker picker) } } - public partial class FilePickerFileType + public partial class FilePickerFileTypeImplementation : IFilePickerFileType { - static FilePickerFileType PlatformImageFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation ImageFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.UWP, FileSystem.Extensions.AllImage } }); - static FilePickerFileType PlatformPngFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation PngFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.UWP, new[] { FileSystem.Extensions.Png } } }); - static FilePickerFileType PlatformJpegFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation JpegFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.UWP, FileSystem.Extensions.AllJpeg } }); - static FilePickerFileType PlatformVideoFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation VideoFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.UWP, FileSystem.Extensions.AllVideo } }); - static FilePickerFileType PlatformPdfFileType() => - new FilePickerFileType(new Dictionary> + static FilePickerFileTypeImplementation PdfFileType() => + new FilePickerFileTypeImplementation(new Dictionary> { { DevicePlatform.UWP, new[] { FileSystem.Extensions.Pdf } } });