misc: chore: Multi/Single file/folder picker extensions (for convenience)

The result of these extensions is an empty Optional when the user hits Cancel on the shown file picker.
This commit is contained in:
Evan Husted 2025-01-21 18:59:19 -06:00
parent fe9d8d05bd
commit 9089c4ffe5
2 changed files with 58 additions and 18 deletions

View File

@ -1,6 +1,6 @@
using Avalonia.Controls.Notifications;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using Gommon;
using LibHac; using LibHac;
using LibHac.Account; using LibHac.Account;
using LibHac.Common; using LibHac.Common;
@ -15,6 +15,7 @@ using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.Configuration; using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common.Helper; using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
@ -418,35 +419,27 @@ namespace Ryujinx.Ava.Common
public static async Task ExtractAoc(IStorageProvider storageProvider, string updateFilePath, string updateName) public static async Task ExtractAoc(IStorageProvider storageProvider, string updateFilePath, string updateName)
{ {
var result = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions Optional<IStorageFolder> result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions
{ {
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
AllowMultiple = false,
}); });
if (result.Count == 0) if (!result.HasValue) return;
{
return;
}
ExtractAoc(result[0].Path.LocalPath, updateFilePath, updateName); ExtractAoc(result.Value.Path.LocalPath, updateFilePath, updateName);
} }
public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0)
{ {
var result = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions Optional<IStorageFolder> result = await storageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions
{ {
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
AllowMultiple = false,
}); });
if (result.Count == 0) if (!result.HasValue) return;
{
return;
}
ExtractSection(result[0].Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex); ExtractSection(result.Value.Path.LocalPath, ncaSectionType, titleFilePath, titleName, programIndex);
} }
public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token) public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token)

View File

@ -0,0 +1,47 @@
using Avalonia.Platform.Storage;
using Gommon;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Utilities
{
public static class StorageProviderExtensions
{
public static async Task<Optional<IStorageFolder>> OpenSingleFolderPickerAsync(this IStorageProvider storageProvider, FolderPickerOpenOptions openOptions = null) =>
await storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, false))
.Then(folders => folders.FindFirst());
public static async Task<Optional<IStorageFile>> OpenSingleFilePickerAsync(this IStorageProvider storageProvider, FilePickerOpenOptions openOptions = null) =>
await storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, false))
.Then(files => files.FindFirst());
public static async Task<Optional<IReadOnlyList<IStorageFolder>>> OpenMultiFolderPickerAsync(this IStorageProvider storageProvider, FolderPickerOpenOptions openOptions = null) =>
await storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, true))
.Then(folders => folders.Count > 0 ? Optional.Of(folders) : default);
public static async Task<Optional<IReadOnlyList<IStorageFile>>> OpenMultiFilePickerAsync(this IStorageProvider storageProvider, FilePickerOpenOptions openOptions = null) =>
await storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, true))
.Then(files => files.Count > 0 ? Optional.Of(files) : default);
private static FilePickerOpenOptions FixOpenOptions(this FilePickerOpenOptions openOptions, bool allowMultiple)
{
if (openOptions is null)
return new FilePickerOpenOptions { AllowMultiple = allowMultiple };
openOptions.AllowMultiple = allowMultiple;
return openOptions;
}
private static FolderPickerOpenOptions FixOpenOptions(this FolderPickerOpenOptions openOptions, bool allowMultiple)
{
if (openOptions is null)
return new FolderPickerOpenOptions { AllowMultiple = allowMultiple };
openOptions.AllowMultiple = allowMultiple;
return openOptions;
}
}
}