Skip to content

Commit

Permalink
feat: Support for CachedFileManager
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Jul 7, 2021
1 parent 3a23e4d commit 1673873
Show file tree
Hide file tree
Showing 13 changed files with 156 additions and 50 deletions.
7 changes: 5 additions & 2 deletions src/Uno.UI/Resources/Strings/cs-CZ/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,10 @@
<data name="StorageProviderLocalDisplayName" xml:space="preserve">
<value>Tento počítač</value>
</data>
<data name="StorageProviderNativeWasmDisplayName" xml:space="preserve">
<data name="StorageProviderWasmDownloadPickerName" xml:space="preserve">
<value>WASM dialog pro stažení</value>
</data>
<data name="StorageProviderWasmNativeDisplayName" xml:space="preserve">
<value>JS File Access API</value>
</data>
</root>
</root>
5 changes: 4 additions & 1 deletion src/Uno.UI/Resources/Strings/en/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
<data name="StorageProviderLocalDisplayName" xml:space="preserve">
<value>This PC</value>
</data>
<data name="StorageProviderNativeWasmDisplayName" xml:space="preserve">
<data name="StorageProviderWasmNativeDisplayName" xml:space="preserve">
<value>JS File Access API</value>
</data>
<data name="TEXT_CALENDARDATEPICKER_DEFAULT_PLACEHOLDER_TEXT" xml:space="preserve">
Expand All @@ -141,4 +141,7 @@
<data name="UIA_FLIPVIEW_NEXT" xml:space="preserve">
<value>Next</value>
</data>
<data name="StorageProviderWasmDownloadPickerName" xml:space="preserve">
<value>WASM Download picker</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,28 @@
#pragma warning disable 114 // new keyword hiding
namespace Windows.Storage.Provider
{
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if __ANDROID__ || __IOS__ || NET461 || false || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
#if false
[global::Uno.NotImplemented]
#endif
public enum FileUpdateStatus
{
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
Incomplete,
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
Complete,
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
UserInputNeeded,
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
CurrentlyUnavailable,
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
Failed,
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
CompleteAndRenamed,
#endif
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
#pragma warning disable 114 // new keyword hiding
namespace Windows.Storage
{
#if __ANDROID__ || __IOS__ || NET461 || false || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented]
#endif
public partial class CachedFileManager
public partial class CachedFileManager
{
#if __ANDROID__ || __IOS__ || NET461 || false || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public static void DeferUpdates( global::Windows.Storage.IStorageFile file)
{
global::Windows.Foundation.Metadata.ApiInformation.TryRaiseNotImplemented("Windows.Storage.CachedFileManager", "void CachedFileManager.DeferUpdates(IStorageFile file)");
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || false || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461","__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public static global::Windows.Foundation.IAsyncOperation<global::Windows.Storage.Provider.FileUpdateStatus> CompleteUpdatesAsync( global::Windows.Storage.IStorageFile file)
{
Expand Down
41 changes: 41 additions & 0 deletions src/Uno.UWP/Storage/CachedFileManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Storage.Provider;

namespace Windows.Storage
{
/// <summary>
/// Lets apps manage real-time updates to files.
/// </summary>
public static partial class CachedFileManager
{
/// <summary>
/// Lets apps defer real-time updates for a specified file.
/// </summary>
/// <param name="file">The file to defer updates for.</param>
/// <remarks>
/// In case of Uno Platform, this method currently
/// does not have any impact.
/// </remarks>
public static void DeferUpdates(IStorageFile file)
{
}

/// <summary>
/// Initiates updates for the specified file. This method contacts the app that provided the file to perform the updates.
/// </summary>
/// <param name="file">The file to update.</param>
/// <returns>
/// When this method completes, it returns a FileUpdateStatus
/// enum value that describes the status of the updates to the file.
/// </returns>
/// <remarks>
/// On most Uno Platform targets, this method immediately returns
/// success, as the file is already updated. In case of WASM using
/// the download file picker, this triggers the download file dialog.
/// </remarks>
public static IAsyncOperation<FileUpdateStatus> CompleteUpdatesAsync(IStorageFile file) =>
AsyncOperation.FromTask(ct => CompleteUpdatesTaskAsync(file, ct));
}
}
14 changes: 14 additions & 0 deletions src/Uno.UWP/Storage/CachedFileManager.other.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#if !__WASM__
using System.Threading;
using System.Threading.Tasks;
using Windows.Storage.Provider;

namespace Windows.Storage
{
public static partial class CachedFileManager
{
private static Task<FileUpdateStatus> CompleteUpdatesTaskAsync(IStorageFile file, CancellationToken token) =>
Task.FromResult(FileUpdateStatus.Complete);
}
}
#endif
55 changes: 24 additions & 31 deletions src/Uno.UWP/Storage/CachedFileManager.wasm.cs
Original file line number Diff line number Diff line change
@@ -1,45 +1,38 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Uno.Foundation;
using Windows.Foundation;
using Windows.Foundation.Metadata;
using Uno.Storage.Internal;
using Windows.Storage.Provider;

namespace Windows.Storage
{
public partial class CachedFileManager
public static partial class CachedFileManager
{
public static void DeferUpdates(IStorageFile file)
private static async Task<FileUpdateStatus> CompleteUpdatesTaskAsync(IStorageFile file, CancellationToken token)
{
// The method does nothing in wasm since we don't really acces the filesystem.
}


public static IAsyncOperation<FileUpdateStatus> CompleteUpdatesAsync(IStorageFile file) => DownloadFile(file).AsAsyncOperation();

private async static Task<FileUpdateStatus> DownloadFile(IStorageFile file)
{
var stream = await file.OpenStreamForReadAsync();
byte[] data;

using (var reader = new BinaryReader(stream))
{
data = reader.ReadBytes((int)stream.Length);
}

var gch = GCHandle.Alloc(data, GCHandleType.Pinned);
var pinnedData = gch.AddrOfPinnedObject();

try
{
WebAssemblyRuntime.InvokeJS($"Windows.Storage.Pickers.FileSavePicker.SaveAs('{file.Name}', {pinnedData}, {data.Length})");
}
finally
if (file is StorageFile storageFile && storageFile.Provider == StorageProviders.WasmDownloadPicker)
{
gch.Free();
var stream = await file.OpenStreamForReadAsync();
byte[] data;

using (var reader = new BinaryReader(stream))
{
data = reader.ReadBytes((int)stream.Length);
}

var gch = GCHandle.Alloc(data, GCHandleType.Pinned);
var pinnedData = gch.AddrOfPinnedObject();

try
{
WebAssemblyRuntime.InvokeJS($"Windows.Storage.Pickers.FileSavePicker.SaveAs('{file.Name}', {pinnedData}, {data.Length})");
}
finally
{
gch.Free();
}
}

return FileUpdateStatus.Complete;
Expand Down
4 changes: 3 additions & 1 deletion src/Uno.UWP/Storage/Internal/StorageProviders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ internal static class StorageProviders
public static StorageProvider Local { get; } = new StorageProvider("computer", "StorageProviderLocalDisplayName");

#if __WASM__
public static StorageProvider NativeWasm { get; } = new StorageProvider("jsfileaccessapi", "StorageProviderNativeWasmDisplayName");
public static StorageProvider WasmDownloadPicker { get; } = new StorageProvider("wasmdownloadpicker", "StorageProviderWasmDownloadPickerName");

public static StorageProvider WasmNative { get; } = new StorageProvider("jsfileaccessapi", "StorageProviderWasmNativeDisplayName");
#endif

#if __ANDROID__
Expand Down
1 change: 1 addition & 0 deletions src/Uno.UWP/Storage/Pickers/FileSavePicker.wasm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ private NativeFilePickerAcceptType[] BuildFileTypesMap()
// The mime type is chosen by the extension, and we cannot reliably send multiple mime type in the browser
var fileName = SuggestedFileName + extension;
SuggestedSaveFile = await temporaryFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
SuggestedSaveFile.ProviderOverride = StorageProviders.WasmDownloadPicker;
}
return SuggestedSaveFile;
}
Expand Down
44 changes: 44 additions & 0 deletions src/Uno.UWP/Storage/Provider/FileUpdateStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
namespace Windows.Storage.Provider
{
/// <summary>
/// Describes the status of a file update request.
/// </summary>
public enum FileUpdateStatus
{
/// <summary>
/// The file update was not fully completed and should be retried.
/// </summary>
Incomplete,

/// <summary>
/// The file update was completed successfully.
/// </summary>
Complete,

/// <summary>
/// User input (like credentials) is needed to update the file.
/// </summary>
UserInputNeeded,

/// <summary>
/// The remote version of the file was not updated because the storage location
/// wasn't available. The file remains valid and subsequent updates
/// to the file may succeed.
/// </summary>
CurrentlyUnavailable,

/// <summary>
/// The file is now invalid and can't be updated now or in the future. For example,
/// this could occur if the remote version of the file was deleted.
/// </summary>
Failed,

/// <summary>
/// The file update was completed successfully and the file has been renamed.
/// For example, this could occur if the user chose to save their changes under
/// a different file name because of conflicting changes made to the remote
/// version of the file.
/// </summary>
CompleteAndRenamed,
}
}
7 changes: 6 additions & 1 deletion src/Uno.UWP/Storage/StorageFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@ private StorageFile(ImplementationBase implementation)

internal ImplementationBase Implementation { get; }

public StorageProvider Provider => Implementation.Provider;
/// <summary>
/// Allows internal Uno implementations to override the storage provider.
/// </summary>
internal StorageProvider? ProviderOverride { get; set; }

public StorageProvider Provider => ProviderOverride ?? Implementation.Provider;

public string Path => Implementation.Path;

Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UWP/Storage/StorageFile.native.wasm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public NativeStorageFile(NativeStorageItemInfo nativeStorageItem, StorageFolder?
_parent = parent;
}

public override StorageProvider Provider => StorageProviders.NativeWasm;
public override StorageProvider Provider => StorageProviders.WasmNative;

public override string Name => _fileName;

Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UWP/Storage/StorageFolder.native.wasm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public NativeStorageFolder(NativeStorageItemInfo info, StorageFolder? parent)
_parent = parent;
}

public override StorageProvider Provider => StorageProviders.NativeWasm;
public override StorageProvider Provider => StorageProviders.WasmNative;

public static async Task<StorageFolder?> GetPrivateRootAsync()
{
Expand Down

0 comments on commit 1673873

Please sign in to comment.