Browse Source

Add PreferFileDialogPolyfill option

pull/11085/head
Max Katz 3 years ago
parent
commit
01a4ba5aa2
  1. 7
      src/Browser/Avalonia.Browser/BrowserAppBuilder.cs
  2. 6
      src/Browser/Avalonia.Browser/Interop/StorageHelper.cs
  3. 9
      src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs
  4. 18
      src/Browser/Avalonia.Browser/webapp/modules/storage/storageProvider.ts

7
src/Browser/Avalonia.Browser/BrowserAppBuilder.cs

@ -11,6 +11,13 @@ public class BrowserPlatformOptions
/// If null, default path resolved depending on the backend (browser or blazor) is used.
/// </summary>
public Func<string, string>? FrameworkAssetPathResolver { get; set; }
/// <summary>
/// Avalonia uses "native-file-system-adapter" polyfill for the file dialogs.
/// If native implementation is available, by default it is used.
/// This property forces polyfill to be always used.
/// </summary>
public bool PreferFileDialogPolyfill { get; set; }
}
public static class BrowserAppBuilder

6
src/Browser/Avalonia.Browser/Interop/StorageHelper.cs

@ -9,15 +9,15 @@ internal static partial class StorageHelper
public static partial bool HasNativeFilePicker();
[JSImport("StorageProvider.selectFolderDialog", AvaloniaModule.StorageModuleName)]
public static partial Task<JSObject?> SelectFolderDialog(JSObject? startIn);
public static partial Task<JSObject?> SelectFolderDialog(JSObject? startIn, bool preferPolyfill);
[JSImport("StorageProvider.openFileDialog", AvaloniaModule.StorageModuleName)]
public static partial Task<JSObject?> OpenFileDialog(JSObject? startIn, bool multiple,
[JSMarshalAs<JSType.Array<JSType.Any>>] object[]? types, bool excludeAcceptAllOption);
[JSMarshalAs<JSType.Array<JSType.Any>>] object[]? types, bool excludeAcceptAllOption, bool preferPolyfill);
[JSImport("StorageProvider.saveFileDialog", AvaloniaModule.StorageModuleName)]
public static partial Task<JSObject?> SaveFileDialog(JSObject? startIn, string? suggestedName,
[JSMarshalAs<JSType.Array<JSType.Any>>] object[]? types, bool excludeAcceptAllOption);
[JSMarshalAs<JSType.Array<JSType.Any>>] object[]? types, bool excludeAcceptAllOption, bool preferPolyfill);
[JSImport("StorageItem.createWellKnownDirectory", AvaloniaModule.StorageModuleName)]
public static partial JSObject CreateWellKnownDirectory(string wellKnownDirectory);

9
src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs

@ -20,6 +20,9 @@ internal class BrowserStorageProvider : IStorageProvider
public bool CanSave => StorageHelper.HasNativeFilePicker();
public bool CanPickFolder => true;
private bool PreferPolyfill =>
AvaloniaLocator.Current.GetService<BrowserPlatformOptions>()?.PreferFileDialogPolyfill ?? false;
public async Task<IReadOnlyList<IStorageFile>> OpenFilePickerAsync(FilePickerOpenOptions options)
{
await AvaloniaModule.ImportStorage();
@ -29,7 +32,7 @@ internal class BrowserStorageProvider : IStorageProvider
try
{
using var items = await StorageHelper.OpenFileDialog(startIn, options.AllowMultiple, types, excludeAll);
using var items = await StorageHelper.OpenFileDialog(startIn, options.AllowMultiple, types, excludeAll, PreferPolyfill);
if (items is null)
{
return Array.Empty<IStorageFile>();
@ -63,7 +66,7 @@ internal class BrowserStorageProvider : IStorageProvider
try
{
var item = await StorageHelper.SaveFileDialog(startIn, options.SuggestedFileName, types, excludeAll);
var item = await StorageHelper.SaveFileDialog(startIn, options.SuggestedFileName, types, excludeAll, PreferPolyfill);
return item is not null ? new JSStorageFile(item) : null;
}
catch (JSException ex) when (ex.Message.Contains(PickerCancelMessage, StringComparison.Ordinal))
@ -89,7 +92,7 @@ internal class BrowserStorageProvider : IStorageProvider
try
{
var item = await StorageHelper.SelectFolderDialog(startIn);
var item = await StorageHelper.SelectFolderDialog(startIn, PreferPolyfill);
return item is not null ? new[] { new JSStorageFolder(item) } : Array.Empty<IStorageFolder>();
}
catch (JSException ex) when (ex.Message.Contains(PickerCancelMessage, StringComparison.Ordinal))

18
src/Browser/Avalonia.Browser/webapp/modules/storage/storageProvider.ts

@ -12,10 +12,12 @@ declare global {
export class StorageProvider {
public static async selectFolderDialog(
startIn: StorageItem | null): Promise<StorageItem> {
startIn: StorageItem | null,
preferPolyfill: boolean): Promise<StorageItem> {
// 'Picker' API doesn't accept "null" as a parameter, so it should be set to undefined.
const options = {
startIn: (startIn?.wellKnownType ?? startIn?.handle ?? undefined)
startIn: (startIn?.wellKnownType ?? startIn?.handle ?? undefined),
_preferPolyfill: preferPolyfill
};
const handle = await showDirectoryPicker(options as any);
@ -24,12 +26,14 @@ export class StorageProvider {
public static async openFileDialog(
startIn: StorageItem | null, multiple: boolean,
types: FilePickerAcceptType[] | null, excludeAcceptAllOption: boolean): Promise<StorageItems> {
types: FilePickerAcceptType[] | null, excludeAcceptAllOption: boolean,
preferPolyfill: boolean): Promise<StorageItems> {
const options = {
startIn: (startIn?.wellKnownType ?? startIn?.handle ?? undefined),
multiple,
excludeAcceptAllOption,
types: (types ?? undefined)
types: (types ?? undefined),
_preferPolyfill: preferPolyfill
};
const handles = await showOpenFilePicker(options);
@ -38,12 +42,14 @@ export class StorageProvider {
public static async saveFileDialog(
startIn: StorageItem | null, suggestedName: string | null,
types: FilePickerAcceptType[] | null, excludeAcceptAllOption: boolean): Promise<StorageItem> {
types: FilePickerAcceptType[] | null, excludeAcceptAllOption: boolean,
preferPolyfill: boolean): Promise<StorageItem> {
const options = {
startIn: (startIn?.wellKnownType ?? startIn?.handle ?? undefined),
suggestedName: (suggestedName ?? undefined),
excludeAcceptAllOption,
types: (types ?? undefined)
types: (types ?? undefined),
_preferPolyfill: preferPolyfill
};
const handle = await showSaveFilePicker(options);

Loading…
Cancel
Save