Browse Source

Add wasm and ios implementations

pull/10607/head
Max Katz 3 years ago
parent
commit
d19e3cd898
  1. 12
      src/Browser/Avalonia.Browser/Interop/StorageHelper.cs
  2. 63
      src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs
  3. 43
      src/Browser/Avalonia.Browser/webapp/modules/storage/storageItem.ts
  4. 62
      src/iOS/Avalonia.iOS/Storage/IOSStorageItem.cs

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

@ -52,4 +52,16 @@ internal static partial class StorageHelper
[JSImport("StorageProvider.createAcceptType", AvaloniaModule.StorageModuleName)]
public static partial JSObject CreateAcceptType(string description, string[] mimeTypes, string[]? extensions);
[JSImport("StorageProvider.deleteAsync", AvaloniaModule.StorageModuleName)]
public static partial Task DeleteAsync(JSObject fileHandle);
[JSImport("StorageProvider.moveAsync", AvaloniaModule.StorageModuleName)]
public static partial Task<JSObject?> MoveAsync(JSObject fileHandle, JSObject destinationFolder);
[JSImport("StorageProvider.createFile", AvaloniaModule.StorageModuleName)]
public static partial Task<JSObject?> CreateFile(JSObject folderHandle, string name);
[JSImport("StorageProvider.createFolder", AvaloniaModule.StorageModuleName)]
public static partial Task<JSObject?> CreateFolder(JSObject folderHandle, string name);
}

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

@ -199,6 +199,33 @@ internal abstract class JSStorageItem : IStorageBookmarkItem
return Task.FromResult<IStorageFolder?>(null);
}
public Task DeleteAsync()
{
return StorageHelper.DeleteAsync(FileHandle);
}
public async Task<IStorageItem?> MoveAsync(IStorageFolder destination)
{
if (destination is not JSStorageFolder folder)
{
throw new InvalidOperationException("Destination folder must be initialized the StorageProvider API.");
}
var storageItem = await StorageHelper.MoveAsync(FileHandle, folder.FileHandle);
if (storageItem is null)
{
return null;
}
var kind = storageItem.GetPropertyAsString("kind");
return kind switch
{
"directory" => new JSStorageFolder(storageItem),
"file" => new JSStorageFile(storageItem),
_ => this
};
}
public Task ReleaseBookmarkAsync()
{
if (!CanBookmark)
@ -299,4 +326,40 @@ internal class JSStorageFolder : JSStorageItem, IStorageBookmarkFolder
}
}
}
public async Task<IStorageFile?> CreateFileAsync(string name)
{
try
{
var storageFile = await StorageHelper.CreateFile(FileHandle, name);
if (storageFile is null)
{
return null;
}
return new JSStorageFile(storageFile);
}
catch (JSException ex) when (ex.Message == BrowserStorageProvider.NoPermissionsMessage)
{
throw new UnauthorizedAccessException("User denied permissions to open the file", ex);
}
}
public async Task<IStorageFolder?> CreateFolderAsync(string name)
{
try
{
var storageFile = await StorageHelper.CreateFolder(FileHandle, name);
if (storageFile is null)
{
return null;
}
return new JSStorageFolder(storageFile);
}
catch (JSException ex) when (ex.Message == BrowserStorageProvider.NoPermissionsMessage)
{
throw new UnauthorizedAccessException("User denied permissions to open the file", ex);
}
}
}

43
src/Browser/Avalonia.Browser/webapp/modules/storage/storageItem.ts

@ -97,6 +97,49 @@ export class StorageItem {
return (item.handle as any).entries();
}
public static async createFile(item: StorageItem, name: string) : Promise<any | null> {
if (item.kind !== "directory" || !item.handle) {
throw new TypeError("Unable to create item in the requested directory");
}
await item.verityPermissions("readwrite");
return await (item.handle as any).getFileHandle(name, { create: true });
}
public static async createFolder(item: StorageItem, name: string) : Promise<any | null> {
if (item.kind !== "directory" || !item.handle) {
throw new TypeError("Unable to create item in the requested directory");
}
await item.verityPermissions("readwrite");
return await (item.handle as any).getDirectoryHandle(name, { create: true });
}
public static async deleteAsync(item: StorageItem) : Promise<any | null> {
if (!item.handle) {
return null;
}
await item.verityPermissions("readwrite");
return await (item.handle as any).remove({recursive: true});
}
public static async moveAsync(item: StorageItem, destination: StorageItem) : Promise<any | null> {
if (!item.handle) {
return null;
}
if (destination.kind !== "directory" || !destination.handle) {
throw new TypeError("Unable to move item to the requested directory");
}
await item.verityPermissions("readwrite");
return await (item.handle as any).move(destination /*, newName */);
}
private async verityPermissions(mode: "read" | "readwrite"): Promise<void | never> {
if (!this.handle) {
return;

62
src/iOS/Avalonia.iOS/Storage/IOSStorageItem.cs

@ -32,6 +32,7 @@ internal abstract class IOSStorageItem : IStorageBookmarkItem
}
internal NSUrl Url { get; }
internal string FilePath => _filePath;
public bool CanBookmark => true;
@ -54,6 +55,38 @@ internal abstract class IOSStorageItem : IStorageBookmarkItem
return Task.FromResult<IStorageFolder?>(new IOSStorageFolder(Url.RemoveLastPathComponent()));
}
public Task DeleteAsync()
{
return NSFileManager.DefaultManager.Remove(Url, out var error)
? Task.CompletedTask
: Task.FromException(new NSErrorException(error));
}
public async Task<IStorageItem?> MoveAsync(IStorageFolder destination)
{
if (destination is not IOSStorageFolder folder)
{
throw new InvalidOperationException("Destination folder must be initialized the StorageProvider API.");
}
var isDir = this is IStorageFolder;
var newPath = new NSUrl(System.IO.Path.Combine(folder.FilePath, Name), isDir);
if (NSFileManager.DefaultManager.Move(folder.Url, newPath, out var error))
{
return isDir
? new IOSStorageFolder(newPath)
: new IOSStorageFile(newPath);
}
if (error is not null)
{
throw new NSErrorException(error);
}
return null;
}
public Task ReleaseBookmarkAsync()
{
// no-op
@ -149,4 +182,33 @@ internal sealed class IOSStorageFolder : IOSStorageItem, IStorageBookmarkFolder
yield return item;
}
}
public Task<IStorageFile?> CreateFileAsync(string name)
{
var path = System.IO.Path.Combine(FilePath, name);
NSFileAttributes? attributes = null;
if (NSFileManager.DefaultManager.CreateFile(path, null, attributes))
{
return Task.FromResult<IStorageFile?>(new IOSStorageFile(new NSUrl(path, false)));
}
return Task.FromResult<IStorageFile?>(null);
}
public Task<IStorageFolder?> CreateFolderAsync(string name)
{
var path = System.IO.Path.Combine(FilePath, name);
NSFileAttributes? attributes = null;
if (NSFileManager.DefaultManager.CreateDirectory(path, false, attributes, out var error))
{
return Task.FromResult<IStorageFolder?>(new IOSStorageFolder(new NSUrl(path, true)));
}
if (error is not null)
{
throw new NSErrorException(error);
}
return Task.FromResult<IStorageFolder?>(null);
}
}

Loading…
Cancel
Save