From 003b66ecb1dc1b386e79f050dc8a69e973fc8714 Mon Sep 17 00:00:00 2001 From: KristofferStrube Date: Sun, 21 May 2023 02:06:20 +0200 Subject: [PATCH 1/3] Started implementing exceptions for directory/file picker methods. --- .../Program.cs | 3 + .../Pages/OpenFile.razor | 38 ++++++++- .../Program.cs | 7 +- .../BaseFileSystemAccessService.cs | 11 ++- .../IServiceCollectionExtensions.cs | 10 ++- .../FileSystemAccessService.InProcess.cs | 3 +- .../FileSystemAccessService.cs | 3 +- .../IFileSystemAccessService.cs | 79 ++++++++++++++++++- ...offerStrube.Blazor.FileSystemAccess.csproj | 1 + 9 files changed, 140 insertions(+), 15 deletions(-) diff --git a/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Program.cs b/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Program.cs index 7c4ec3b..f05bb69 100644 --- a/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Program.cs +++ b/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Program.cs @@ -1,6 +1,7 @@ using KristofferStrube.Blazor.FileAPI; using KristofferStrube.Blazor.FileSystem; using KristofferStrube.Blazor.FileSystemAccess; +using KristofferStrube.Blazor.WebIDL; using TG.Blazor.IndexedDB; WebApplicationBuilder builder = WebApplication.CreateBuilder(args); @@ -46,4 +47,6 @@ app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); +await app.Services.SetupErrorHandlingJSInterop(); + app.Run(); diff --git a/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Pages/OpenFile.razor b/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Pages/OpenFile.razor index a58b053..8d9da09 100644 --- a/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Pages/OpenFile.razor +++ b/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Pages/OpenFile.razor @@ -1,10 +1,26 @@ @page "/OpenFile" +@using KristofferStrube.Blazor.WebIDL.Exceptions; @inject IFileSystemAccessServiceInProcess FileSystemAccessService File System Access - Read File + +@if (errorMessage is not null) +{ +
@errorMessage
+} @if (fileHandle is null) { +

+ The browser can remember a set of previously used folders given an id. If a prompt has never been opened with this id then it falls back to using the well-known directory and the folder that is used this time is remembered for the next time the id is used. The id must only contain alphanumeric sumbols or "_" or "-" and cannot be longer than 32 characters. +
+ You can specify an id below here or leave it blank. You can try to give it some illegal characters or make it too long to see that we can handle errors of this type. +
+ We can likewise detect if the user aborts the prompt which you can also test here by canceling or closing the prompt. +

+ +
+
} else if (readPermissionState is PermissionState.Denied) @@ -25,9 +41,10 @@ else } - @code { private string? fileText; + private string? errorMessage; + private string? id; private FileSystemFileHandleInProcess? fileHandle; private PermissionState readPermissionState; private PermissionState writePermissionState; @@ -36,18 +53,31 @@ else { try { - var options = new OpenFilePickerOptionsStartInWellKnownDirectory() { Multiple = false, StartIn = WellKnownDirectory.Downloads }; + var options = new OpenFilePickerOptionsStartInWellKnownDirectory() { Multiple = false, StartIn = WellKnownDirectory.Downloads, Id = id }; var fileHandles = await FileSystemAccessService.ShowOpenFilePickerAsync(options); fileHandle = fileHandles.Single(); } - catch (JSException ex) + catch (AbortErrorException) + { + errorMessage = $"The user aborted the prompt."; + } + catch (DOMException ex) + { + errorMessage = $"A user interaction error of type {ex.Name} occurred: \"{ex.Message}\""; + } + catch (TypeErrorException ex) + { + errorMessage = $"We parsed an invalid argument to the function: \"{ex.Message}\""; + } + catch (Exception ex) { - Console.WriteLine(ex); + errorMessage = $"Some other unexpected exception of type {ex.GetType().Name} occurred: \"{ex.Message}\""; } finally { if (fileHandle != null) { + errorMessage = null; readPermissionState = await fileHandle.QueryPermissionAsync(new() { Mode = FileSystemPermissionMode.Read }); } } diff --git a/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Program.cs b/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Program.cs index 59167f0..6561241 100644 --- a/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Program.cs +++ b/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Program.cs @@ -2,6 +2,7 @@ using KristofferStrube.Blazor.FileSystem; using KristofferStrube.Blazor.FileSystemAccess; using KristofferStrube.Blazor.FileSystemAccess.WasmExample; +using KristofferStrube.Blazor.WebIDL; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using TG.Blazor.IndexedDB; @@ -35,4 +36,8 @@ }); }); -await builder.Build().RunAsync(); +var app = builder.Build(); + +await app.Services.SetupErrorHandlingJSInterop(); + +await app.RunAsync(); diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs b/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs index 7b0dd89..b3cd92e 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs +++ b/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs @@ -1,5 +1,6 @@ using KristofferStrube.Blazor.FileSystem; using KristofferStrube.Blazor.FileSystemAccess.Extensions; +using KristofferStrube.Blazor.WebIDL; using Microsoft.JSInterop; namespace KristofferStrube.Blazor.FileSystemAccess; @@ -10,10 +11,12 @@ public abstract class BaseFileSystemAccessService> helperTask; protected readonly IJSRuntime jSRuntime; + protected readonly IErrorHandlingJSRuntime errorHandlingJSRuntime; - public BaseFileSystemAccessService(IJSRuntime jSRuntime) + public BaseFileSystemAccessService(IErrorHandlingJSRuntime errorHandlingJSRuntime, IJSRuntime jSRuntime) { helperTask = new(() => jSRuntime.GetHelperAsync(FileSystemAccessOptions.DefaultInstance)); + this.errorHandlingJSRuntime = errorHandlingJSRuntime; this.jSRuntime = jSRuntime; } @@ -87,8 +90,8 @@ protected async Task InternalShowOpenFilePickerAsync(object? op protected async Task InternalShowOpenFilePickerAsync(object? options, FileSystemOptions fsOptions) { IJSObjectReference helper = await helperTask.Value; - TObjReference jSFileHandles = await jSRuntime.InvokeAsync("window.showOpenFilePicker", options); - int length = await helper.InvokeAsync("size", jSFileHandles); + IErrorHandlingJSObjectReference jSFileHandles = await errorHandlingJSRuntime.InvokeAsync("window.showOpenFilePicker", options); + int length = await helper.InvokeAsync("size", jSFileHandles.JSReference); return await Task.WhenAll( Enumerable @@ -96,7 +99,7 @@ protected async Task InternalShowOpenFilePickerAsync(object? op .Select(async i => await this.CreateFileHandleAsync( jSRuntime, - await jSFileHandles.InvokeAsync("at", i), + (TObjReference)(await jSFileHandles.InvokeAsync("at", i)).JSReference, fsOptions) ) .ToArray() diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/Extensions/IServiceCollectionExtensions.cs b/src/KristofferStrube.Blazor.FileSystemAccess/Extensions/IServiceCollectionExtensions.cs index a8394fb..9ce1a40 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/Extensions/IServiceCollectionExtensions.cs +++ b/src/KristofferStrube.Blazor.FileSystemAccess/Extensions/IServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.DependencyInjection; +using KristofferStrube.Blazor.WebIDL; +using Microsoft.Extensions.DependencyInjection; namespace KristofferStrube.Blazor.FileSystemAccess; @@ -13,7 +14,9 @@ public static IServiceCollection AddFileSystemAccessService(this IServiceCollect { ConfigureFsaOptions(serviceCollection, configure); - return serviceCollection.AddScoped(); + return serviceCollection + .AddScoped() + .AddErrorHandlingJSRuntime(); } public static IServiceCollection AddFileSystemAccessServiceInProcess(this IServiceCollection serviceCollection) @@ -31,7 +34,8 @@ public static IServiceCollection AddFileSystemAccessServiceInProcess(this IServi { IFileSystemAccessServiceInProcess service = sp.GetRequiredService(); return (IFileSystemAccessService)service; - }); + }) + .AddErrorHandlingJSRuntime(); } private static void ConfigureFsaOptions(IServiceCollection services, Action? configure) diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.InProcess.cs b/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.InProcess.cs index 6935734..5b127fe 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.InProcess.cs +++ b/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.InProcess.cs @@ -1,4 +1,5 @@ using KristofferStrube.Blazor.FileSystem; +using KristofferStrube.Blazor.WebIDL; using Microsoft.JSInterop; namespace KristofferStrube.Blazor.FileSystemAccess; @@ -10,7 +11,7 @@ public class FileSystemAccessServiceInProcess : IJSInProcessObjectReference>, IFileSystemAccessServiceInProcess, IFileSystemAccessService { - public FileSystemAccessServiceInProcess(IJSRuntime jSRuntime) : base(jSRuntime) + public FileSystemAccessServiceInProcess(IErrorHandlingJSRuntime errorHandlingJSRuntime, IJSRuntime jSRuntime) : base(errorHandlingJSRuntime, jSRuntime) { } diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.cs b/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.cs index 024d248..df16f0c 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.cs +++ b/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.cs @@ -1,4 +1,5 @@ using KristofferStrube.Blazor.FileSystem; +using KristofferStrube.Blazor.WebIDL; using Microsoft.JSInterop; namespace KristofferStrube.Blazor.FileSystemAccess; @@ -10,7 +11,7 @@ public class FileSystemAccessService : IJSObjectReference>, IFileSystemAccessService { - public FileSystemAccessService(IJSRuntime jSRuntime) : base(jSRuntime) + public FileSystemAccessService(IErrorHandlingJSRuntime errorHandlingJSRuntime, IJSRuntime jSRuntime) : base(errorHandlingJSRuntime, jSRuntime) { } diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/IFileSystemAccessService.cs b/src/KristofferStrube.Blazor.FileSystemAccess/IFileSystemAccessService.cs index 4eec869..f98ba93 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/IFileSystemAccessService.cs +++ b/src/KristofferStrube.Blazor.FileSystemAccess/IFileSystemAccessService.cs @@ -1,4 +1,5 @@ using KristofferStrube.Blazor.FileSystem; +using KristofferStrube.Blazor.WebIDL.Exceptions; using Microsoft.JSInterop; namespace KristofferStrube.Blazor.FileSystemAccess @@ -11,15 +12,91 @@ public interface IFileSystemAccessService IsSupportedAsync(); + /// + /// Shows a directory picker that lets the user select a single directory, returning a handle for the selected directory if the user grants read permission. + /// + /// + /// + /// A new Task ShowDirectoryPickerAsync(); + + /// + /// Shows a directory picker that lets the user select a single directory, returning a handle for the selected directory if the user grants read permission. If the argument specified that it should have write access as well this needs to be confirmed by the user as well. + /// + /// A directory picker options for selecting to start in the position of an existing . + /// + /// + /// + /// A new Task ShowDirectoryPickerAsync(DirectoryPickerOptionsStartInFileSystemHandle? directoryPickerOptions); + + /// + /// Shows a directory picker that lets the user select a single directory, returning a handle for the selected directory if the user grants read permission. If the argument specified that it should have write access as well this needs to be confirmed by the user as well. + /// + /// A directory picker options for selecting to start in one of the cross-browser well-known directories. + /// + /// + /// + /// A new Task ShowDirectoryPickerAsync(DirectoryPickerOptionsStartInWellKnownDirectory? directoryPickerOptions); - Task ShowDirectoryPickerAsync(FileSystemOptions fasOptions); + + /// + /// Shows a directory picker that lets the user select a single directory, returning a handle for the selected directory if the user grants read permission. + /// + /// An option that can be used to define the path of the helper script used in this library. + /// + /// + /// A new + Task ShowDirectoryPickerAsync(FileSystemOptions fsOptions); + + /// + /// Shows a directory picker that lets the user select a single directory, returning a handle for the selected directory if the user grants read permission. If the argument specified that it should have write access as well this needs to be confirmed by the user as well. + /// + /// A directory picker options for selecting to start in the position of an existing . + /// An option that can be used to define the path of the helper script used in this library. + /// + /// + /// + /// A new Task ShowDirectoryPickerAsync(DirectoryPickerOptionsStartInFileSystemHandle? directoryPickerOptions, FileSystemOptions fsOptions); + + /// + /// Shows a directory picker that lets the user select a single directory, returning a handle for the selected directory if the user grants read permission. If the argument specified that it should have write access as well this needs to be confirmed by the user as well. + /// + /// A directory picker options for selecting to start in one of the cross-browser well-known directories. + /// An option that can be used to define the path of the helper script used in this library. + /// + /// + /// + /// A new Task ShowDirectoryPickerAsync(DirectoryPickerOptionsStartInWellKnownDirectory? directoryPickerOptions, FileSystemOptions fsOptions); + /// + /// Shows a file picker that lets a user select a single existing file, returning a handle for the selected file. + /// + /// + /// + /// A new Task ShowOpenFilePickerAsync(); + + /// + /// Shows a file picker that lets a user select a single existing file, if the parsed argument had multiple set to , returning a handle for the selected file. If the argument specified that the user could pick multiple files then there might be more than a single handle returned. + /// + /// A file picker options for selecting to start in the position of an existing . + /// + /// + /// + /// A new Task ShowOpenFilePickerAsync(OpenFilePickerOptionsStartInFileSystemHandle? openFilePickerOptions); + + /// + /// Shows a file picker that lets a user select a single existing file, if the parsed argument had multiple set to , returning a handle for the selected file. If the argument specified that the user could pick multiple files then there might be more than a single handle returned. + /// + /// A file picker options for selecting to start in one of the cross-browser well-known directories. + /// + /// + /// + /// A new Task ShowOpenFilePickerAsync(OpenFilePickerOptionsStartInWellKnownDirectory? openFilePickerOptions); Task ShowOpenFilePickerAsync(FileSystemOptions fasOptions); Task ShowOpenFilePickerAsync(OpenFilePickerOptionsStartInFileSystemHandle? openFilePickerOptions, FileSystemOptions fsOptions); diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj b/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj index 68e2802..620d947 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj +++ b/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj @@ -35,6 +35,7 @@ + From 06ef6853faeb2a86581b51812cff76d9b7ce9fd3 Mon Sep 17 00:00:00 2001 From: KristofferStrube Date: Thu, 8 Jun 2023 21:02:43 +0200 Subject: [PATCH 2/3] Better handling. --- .../Pages/OpenFile.razor | 2 +- .../BaseFileSystemAccessService.cs | 54 ++++++------------- .../FileSystemAccessService.InProcess.cs | 2 +- .../FileSystemAccessService.cs | 2 +- .../IFileSystemAccessService.InProcess.cs | 14 +++++ ...offerStrube.Blazor.FileSystemAccess.csproj | 2 +- 6 files changed, 35 insertions(+), 41 deletions(-) diff --git a/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Pages/OpenFile.razor b/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Pages/OpenFile.razor index 8d9da09..0a76d2c 100644 --- a/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Pages/OpenFile.razor +++ b/samples/KristofferStrube.Blazor.FileSystemAccess.WasmExample/Pages/OpenFile.razor @@ -12,7 +12,7 @@ @if (fileHandle is null) {

- The browser can remember a set of previously used folders given an id. If a prompt has never been opened with this id then it falls back to using the well-known directory and the folder that is used this time is remembered for the next time the id is used. The id must only contain alphanumeric sumbols or "_" or "-" and cannot be longer than 32 characters. + The browser can remember a set of previously used folders given an id. If a prompt has never been opened with this id then it falls back to using the well-known directory and the folder that is used this time is remembered for the next time the id is used. The id must only contain alphanumeric symbols or "_" or "-" and cannot be longer than 32 characters.
You can specify an id below here or leave it blank. You can try to give it some illegal characters or make it too long to see that we can handle errors of this type.
diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs b/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs index b3cd92e..f0dd2cc 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs +++ b/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs @@ -11,72 +11,52 @@ public abstract class BaseFileSystemAccessService> helperTask; protected readonly IJSRuntime jSRuntime; - protected readonly IErrorHandlingJSRuntime errorHandlingJSRuntime; + protected readonly IErrorHandlingJSRuntime? errorHandlingJSRuntime; - public BaseFileSystemAccessService(IErrorHandlingJSRuntime errorHandlingJSRuntime, IJSRuntime jSRuntime) + public BaseFileSystemAccessService(IJSRuntime jSRuntime) { helperTask = new(() => jSRuntime.GetHelperAsync(FileSystemAccessOptions.DefaultInstance)); - this.errorHandlingJSRuntime = errorHandlingJSRuntime; + + if (ErrorHandlingJSInterop.ErrorHandlingJSInteropHasBeenSetup) + { + errorHandlingJSRuntime = new ErrorHandlingJSRuntime(); + } this.jSRuntime = jSRuntime; } #region ShowOpenFilePickerAsync - ///

- /// showOpenFilePicker() browser specs - /// - /// - /// + /// public async Task ShowOpenFilePickerAsync(OpenFilePickerOptionsStartInWellKnownDirectory? openFilePickerOptions) { return await this.InternalShowOpenFilePickerAsync(openFilePickerOptions?.Serializable()); } - /// - /// showOpenFilePicker() browser specs - /// - /// - /// - /// + /// public async Task ShowOpenFilePickerAsync(OpenFilePickerOptionsStartInWellKnownDirectory? openFilePickerOptions, FileSystemOptions fsOptions) { return await InternalShowOpenFilePickerAsync(openFilePickerOptions?.Serializable(), fsOptions); } - /// - /// showOpenFilePicker() browser specs - /// - /// - /// + /// public async Task ShowOpenFilePickerAsync(OpenFilePickerOptionsStartInFileSystemHandle? openFilePickerOptions) { return await this.InternalShowOpenFilePickerAsync(openFilePickerOptions?.Serializable()); } - /// - /// showOpenFilePicker() browser specs - /// - /// - /// - /// + /// public async Task ShowOpenFilePickerAsync(OpenFilePickerOptionsStartInFileSystemHandle? openFilePickerOptions, FileSystemOptions fsOptions) { return await this.InternalShowOpenFilePickerAsync(openFilePickerOptions?.Serializable(), fsOptions); } - /// - /// showOpenFilePicker() browser specs - /// - /// + /// public async Task ShowOpenFilePickerAsync() { return await InternalShowOpenFilePickerAsync(null); } - /// - /// showOpenFilePicker() browser specs - /// - /// + /// public async Task ShowOpenFilePickerAsync(FileSystemOptions fsOptions) { return await InternalShowOpenFilePickerAsync(null, fsOptions); @@ -90,16 +70,16 @@ protected async Task InternalShowOpenFilePickerAsync(object? op protected async Task InternalShowOpenFilePickerAsync(object? options, FileSystemOptions fsOptions) { IJSObjectReference helper = await helperTask.Value; - IErrorHandlingJSObjectReference jSFileHandles = await errorHandlingJSRuntime.InvokeAsync("window.showOpenFilePicker", options); - int length = await helper.InvokeAsync("size", jSFileHandles.JSReference); + IJSObjectReference jSFileHandles = await (errorHandlingJSRuntime ?? jSRuntime).InvokeAsync("window.showOpenFilePicker", options); + int length = await helper.InvokeAsync("size", jSFileHandles); return await Task.WhenAll( Enumerable .Range(0, length) .Select(async i => - await this.CreateFileHandleAsync( + await CreateFileHandleAsync( jSRuntime, - (TObjReference)(await jSFileHandles.InvokeAsync("at", i)).JSReference, + await jSFileHandles.InvokeAsync("at", i), fsOptions) ) .ToArray() diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.InProcess.cs b/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.InProcess.cs index 5b127fe..5514f6d 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.InProcess.cs +++ b/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.InProcess.cs @@ -11,7 +11,7 @@ public class FileSystemAccessServiceInProcess : IJSInProcessObjectReference>, IFileSystemAccessServiceInProcess, IFileSystemAccessService { - public FileSystemAccessServiceInProcess(IErrorHandlingJSRuntime errorHandlingJSRuntime, IJSRuntime jSRuntime) : base(errorHandlingJSRuntime, jSRuntime) + public FileSystemAccessServiceInProcess(IJSRuntime jSRuntime) : base(jSRuntime) { } diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.cs b/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.cs index df16f0c..c63df44 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.cs +++ b/src/KristofferStrube.Blazor.FileSystemAccess/FileSystemAccessService.cs @@ -11,7 +11,7 @@ public class FileSystemAccessService : IJSObjectReference>, IFileSystemAccessService { - public FileSystemAccessService(IErrorHandlingJSRuntime errorHandlingJSRuntime, IJSRuntime jSRuntime) : base(errorHandlingJSRuntime, jSRuntime) + public FileSystemAccessService(IJSRuntime jSRuntime) : base(jSRuntime) { } diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/IFileSystemAccessService.InProcess.cs b/src/KristofferStrube.Blazor.FileSystemAccess/IFileSystemAccessService.InProcess.cs index 4a3e18e..917cbbe 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/IFileSystemAccessService.InProcess.cs +++ b/src/KristofferStrube.Blazor.FileSystemAccess/IFileSystemAccessService.InProcess.cs @@ -13,8 +13,22 @@ public interface IFileSystemAccessServiceInProcess : new Task ShowDirectoryPickerAsync(); new Task ShowDirectoryPickerAsync(DirectoryPickerOptionsStartInFileSystemHandle? directoryPickerOptions); new Task ShowDirectoryPickerAsync(DirectoryPickerOptionsStartInWellKnownDirectory? directoryPickerOptions); + + /// + /// + /// A new . new Task ShowOpenFilePickerAsync(); + + /// + /// + /// + /// A new array of . new Task ShowOpenFilePickerAsync(OpenFilePickerOptionsStartInFileSystemHandle? openFilePickerOptions); + + /// + /// + /// + /// A new array of . new Task ShowOpenFilePickerAsync(OpenFilePickerOptionsStartInWellKnownDirectory? openFilePickerOptions); new Task ShowSaveFilePickerAsync(); new Task ShowSaveFilePickerAsync(SaveFilePickerOptionsStartInFileSystemHandle? saveFilePickerOptions); diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj b/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj index 620d947..ad37515 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj +++ b/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj @@ -35,7 +35,7 @@ - + From 679d08a6e35e51be8f23f4d0f97af0c9cf2746a7 Mon Sep 17 00:00:00 2001 From: KristofferStrube Date: Thu, 8 Jun 2023 22:36:01 +0200 Subject: [PATCH 3/3] Updated Blazor Server Example. --- .../Pages/OpenFile.razor | 43 ++++++++++++++++--- .../Program.cs | 2 - .../BaseFileSystemAccessService.cs | 8 +++- ...offerStrube.Blazor.FileSystemAccess.csproj | 2 +- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Pages/OpenFile.razor b/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Pages/OpenFile.razor index 43b114b..0aa5733 100644 --- a/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Pages/OpenFile.razor +++ b/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Pages/OpenFile.razor @@ -1,10 +1,27 @@ @page "/OpenFile" +@using KristofferStrube.Blazor.WebIDL.Exceptions; @inject IFileSystemAccessService FileSystemAccessService File System Access - Read File + +@if (errorMessage is not null) +{ +
@errorMessage
+} @if (fileHandle is null) { +

+ The browser can remember a set of previously used folders given an id. If a prompt has never been opened with this id then it falls back to using the well-known directory and the folder that is used this time is remembered for the next time the id is used. The id must only contain alphanumeric symbols or "_" or "-" and cannot be longer than 32 characters. +
+ You can specify an id below here or leave it blank. You can try to give it some illegal characters or make it too long to see that we can handle errors of this type. +
+ We can likewise detect if the user aborts the prompt which you can also test here by canceling or closing the prompt. +

+ + +
+
} else if (readPermissionState is PermissionState.Denied) @@ -18,16 +35,17 @@ else if (fileText is null) else if (writePermissionState is PermissionState.Denied or PermissionState.Prompt) { - + } else { - + } - @code { private string? fileText; + private string? errorMessage; + private string? id; private FileSystemFileHandle? fileHandle; private string fileHandleName = ""; private PermissionState readPermissionState; @@ -37,18 +55,31 @@ else { try { - var options = new OpenFilePickerOptionsStartInWellKnownDirectory() { Multiple = false, StartIn = WellKnownDirectory.Downloads }; + var options = new OpenFilePickerOptionsStartInWellKnownDirectory() { Multiple = false, StartIn = WellKnownDirectory.Downloads, Id = id }; var fileHandles = await FileSystemAccessService.ShowOpenFilePickerAsync(options); fileHandle = fileHandles.Single(); } - catch (JSException ex) + catch (AbortErrorException) + { + errorMessage = $"The user aborted the prompt."; + } + catch (DOMException ex) + { + errorMessage = $"A user interaction error of type {ex.Name} occurred: \"{ex.Message}\""; + } + catch (TypeErrorException ex) + { + errorMessage = $"We parsed an invalid argument to the function: \"{ex.Message}\""; + } + catch (Exception ex) { - Console.WriteLine(ex); + errorMessage = $"Some other unexpected exception of type {ex.GetType().Name} occurred: \"{ex.Message}\""; } finally { if (fileHandle != null) { + errorMessage = null; fileHandleName = await fileHandle.GetNameAsync(); readPermissionState = await fileHandle.QueryPermissionAsync(new() { Mode = FileSystemPermissionMode.Read }); } diff --git a/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Program.cs b/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Program.cs index f05bb69..1920f0d 100644 --- a/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Program.cs +++ b/samples/KristofferStrube.Blazor.FileSystemAccess.ServerExample/Program.cs @@ -47,6 +47,4 @@ app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); -await app.Services.SetupErrorHandlingJSInterop(); - app.Run(); diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs b/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs index f0dd2cc..2100d32 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs +++ b/src/KristofferStrube.Blazor.FileSystemAccess/BaseFileSystemAccessService.cs @@ -19,7 +19,11 @@ public BaseFileSystemAccessService(IJSRuntime jSRuntime) if (ErrorHandlingJSInterop.ErrorHandlingJSInteropHasBeenSetup) { - errorHandlingJSRuntime = new ErrorHandlingJSRuntime(); + errorHandlingJSRuntime = new ErrorHandlingJSInProcessRuntime(); + } + else if (jSRuntime is not IJSInProcessRuntime) + { + errorHandlingJSRuntime = new ErrorHandlingJSRuntime(jSRuntime); } this.jSRuntime = jSRuntime; } @@ -29,7 +33,7 @@ public BaseFileSystemAccessService(IJSRuntime jSRuntime) /// public async Task ShowOpenFilePickerAsync(OpenFilePickerOptionsStartInWellKnownDirectory? openFilePickerOptions) { - return await this.InternalShowOpenFilePickerAsync(openFilePickerOptions?.Serializable()); + return await InternalShowOpenFilePickerAsync(openFilePickerOptions?.Serializable()); } /// diff --git a/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj b/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj index ad37515..be51f7c 100644 --- a/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj +++ b/src/KristofferStrube.Blazor.FileSystemAccess/KristofferStrube.Blazor.FileSystemAccess.csproj @@ -35,7 +35,7 @@ - +