From 610516de1fe6da84b4054c59a72706504036806f Mon Sep 17 00:00:00 2001 From: chylex Date: Mon, 17 Jul 2023 22:24:58 +0200 Subject: [PATCH] Update file dialogs and hide overwrite prompt when opening database files Closes #198 --- app/Desktop/Common/DatabaseGui.cs | 32 +++++++++-------- app/Desktop/Dialogs/File/FileDialogs.cs | 36 +++++++++++++++++++ app/Desktop/Main/Pages/DatabasePageModel.cs | 21 +++++------ app/Desktop/Main/Pages/ViewerPageModel.cs | 21 +++++------ .../Main/Screens/WelcomeScreenModel.cs | 7 ++-- 5 files changed, 72 insertions(+), 45 deletions(-) create mode 100644 app/Desktop/Dialogs/File/FileDialogs.cs diff --git a/app/Desktop/Common/DatabaseGui.cs b/app/Desktop/Common/DatabaseGui.cs index 7aded31..abf3c1f 100644 --- a/app/Desktop/Common/DatabaseGui.cs +++ b/app/Desktop/Common/DatabaseGui.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Avalonia.Controls; +using Avalonia.Platform.Storage; +using DHT.Desktop.Dialogs.File; using DHT.Desktop.Dialogs.Message; using DHT.Server.Database; using DHT.Server.Database.Exceptions; @@ -15,27 +17,27 @@ namespace DHT.Desktop.Common { private const string DatabaseFileInitialName = "archive.dht"; - private static readonly List DatabaseFileDialogFilter = new() { - new FileDialogFilter { - Name = "Discord History Tracker Database", - Extensions = { "dht" } - } + private static readonly IReadOnlyList DatabaseFileDialogFilter = new List { + FileDialogs.CreateFilter("Discord History Tracker Database", new [] { "dht" }) }; - public static OpenFileDialog NewOpenDatabaseFileDialog() { - return new OpenFileDialog { + public static async Task NewOpenDatabaseFilesDialog(Window window, string? suggestedDirectory) { + return await window.StorageProvider.OpenFiles(new FilePickerOpenOptions { Title = "Open Database File", - InitialFileName = DatabaseFileInitialName, - Filters = DatabaseFileDialogFilter - }; + FileTypeFilter = DatabaseFileDialogFilter, + SuggestedStartLocation = await FileDialogs.GetSuggestedStartLocation(window, suggestedDirectory), + AllowMultiple = true + }); } - public static SaveFileDialog NewOpenOrCreateDatabaseFileDialog() { - return new SaveFileDialog { + public static async Task NewOpenOrCreateDatabaseFileDialog(Window window, string? suggestedDirectory) { + return await window.StorageProvider.SaveFile(new FilePickerSaveOptions { Title = "Open or Create Database File", - InitialFileName = DatabaseFileInitialName, - Filters = DatabaseFileDialogFilter - }; + FileTypeChoices = DatabaseFileDialogFilter, + SuggestedFileName = DatabaseFileInitialName, + SuggestedStartLocation = await FileDialogs.GetSuggestedStartLocation(window, suggestedDirectory), + ShowOverwritePrompt = false + }); } public static async Task TryOpenOrCreateDatabaseFromPath(string path, Window window, Func> checkCanUpgradeDatabase) { diff --git a/app/Desktop/Dialogs/File/FileDialogs.cs b/app/Desktop/Dialogs/File/FileDialogs.cs new file mode 100644 index 0000000..f3739ff --- /dev/null +++ b/app/Desktop/Dialogs/File/FileDialogs.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Avalonia.Controls; +using Avalonia.Platform.Storage; + +namespace DHT.Desktop.Dialogs.File { + static class FileDialogs { + public static async Task OpenFiles(this IStorageProvider storageProvider, FilePickerOpenOptions options) { + return (await storageProvider.OpenFilePickerAsync(options)).ToLocalPaths(); + } + + public static async Task SaveFile(this IStorageProvider storageProvider, FilePickerSaveOptions options) { + return (await storageProvider.SaveFilePickerAsync(options))?.ToLocalPath(); + } + + public static FilePickerFileType CreateFilter(string name, string[] extensions) { + return new FilePickerFileType(name) { + Patterns = extensions.Select(static ext => "*." + ext).ToArray() + }; + } + + public static Task GetSuggestedStartLocation(Window window, string? suggestedDirectory) { + return suggestedDirectory == null ? Task.FromResult(null) : window.StorageProvider.TryGetFolderFromPathAsync(suggestedDirectory); + } + + private static string ToLocalPath(this IStorageFile file) { + return file.TryGetLocalPath() ?? throw new NotSupportedException("Local filesystem is not supported."); + } + + private static string[] ToLocalPaths(this IReadOnlyList files) { + return files.Select(ToLocalPath).ToArray(); + } + } +} diff --git a/app/Desktop/Main/Pages/DatabasePageModel.cs b/app/Desktop/Main/Pages/DatabasePageModel.cs index d31e1f5..77f1be7 100644 --- a/app/Desktop/Main/Pages/DatabasePageModel.cs +++ b/app/Desktop/Main/Pages/DatabasePageModel.cs @@ -7,8 +7,10 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using Avalonia.Controls; +using Avalonia.Platform.Storage; using Avalonia.Threading; using DHT.Desktop.Common; +using DHT.Desktop.Dialogs.File; using DHT.Desktop.Dialogs.Message; using DHT.Desktop.Dialogs.Progress; using DHT.Desktop.Dialogs.TextBox; @@ -68,12 +70,8 @@ namespace DHT.Desktop.Main.Pages { } public async void MergeWithDatabase() { - var fileDialog = DatabaseGui.NewOpenDatabaseFileDialog(); - fileDialog.Directory = Path.GetDirectoryName(Db.Path); - fileDialog.AllowMultiple = true; - - string[]? paths = await fileDialog.ShowAsync(window); - if (paths == null || paths.Length == 0) { + var paths = await DatabaseGui.NewOpenDatabaseFilesDialog(window, Path.GetDirectoryName(Db.Path)); + if (paths.Length == 0) { return; } @@ -118,14 +116,13 @@ namespace DHT.Desktop.Main.Pages { } public async void ImportLegacyArchive() { - var fileDialog = new OpenFileDialog { + var paths = await window.StorageProvider.OpenFiles(new FilePickerOpenOptions { Title = "Open Legacy DHT Archive", - Directory = Path.GetDirectoryName(Db.Path), + SuggestedStartLocation = await FileDialogs.GetSuggestedStartLocation(window, Path.GetDirectoryName(Db.Path)), AllowMultiple = true - }; - - string[]? paths = await fileDialog.ShowAsync(window); - if (paths == null || paths.Length == 0) { + }); + + if (paths.Length == 0) { return; } diff --git a/app/Desktop/Main/Pages/ViewerPageModel.cs b/app/Desktop/Main/Pages/ViewerPageModel.cs index b022f88..c34e6e2 100644 --- a/app/Desktop/Main/Pages/ViewerPageModel.cs +++ b/app/Desktop/Main/Pages/ViewerPageModel.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; @@ -8,7 +7,9 @@ using System.Text; using System.Threading.Tasks; using System.Web; using Avalonia.Controls; +using Avalonia.Platform.Storage; using DHT.Desktop.Common; +using DHT.Desktop.Dialogs.File; using DHT.Desktop.Dialogs.Message; using DHT.Desktop.Main.Controls; using DHT.Desktop.Server; @@ -114,20 +115,14 @@ namespace DHT.Desktop.Main.Pages { } public async void OnClickSaveViewer() { - var dialog = new SaveFileDialog { + string? path = await window.StorageProvider.SaveFile(new FilePickerSaveOptions { Title = "Save Viewer", - InitialFileName = Path.GetFileNameWithoutExtension(db.Path) + ".html", - Directory = Path.GetDirectoryName(db.Path), - Filters = new List { - new() { - Name = "Discord History Viewer", - Extensions = { "html" } - } - } - }.ShowAsync(window); + FileTypeChoices = new [] { FileDialogs.CreateFilter("Discord History Viewer", new string[] { "html" }) }, + SuggestedFileName = Path.GetFileNameWithoutExtension(db.Path) + ".html", + SuggestedStartLocation = await FileDialogs.GetSuggestedStartLocation(window, Path.GetDirectoryName(db.Path)), + }); - string? path = await dialog; - if (!string.IsNullOrEmpty(path)) { + if (path != null) { await WriteViewerFile(path, StandaloneViewerExportStrategy.Instance); } } diff --git a/app/Desktop/Main/Screens/WelcomeScreenModel.cs b/app/Desktop/Main/Screens/WelcomeScreenModel.cs index fd799de..514f442 100644 --- a/app/Desktop/Main/Screens/WelcomeScreenModel.cs +++ b/app/Desktop/Main/Screens/WelcomeScreenModel.cs @@ -26,11 +26,8 @@ namespace DHT.Desktop.Main.Screens { } public async void OpenOrCreateDatabase() { - var dialog = DatabaseGui.NewOpenOrCreateDatabaseFileDialog(); - dialog.Directory = Path.GetDirectoryName(dbFilePath); - - string? path = await dialog.ShowAsync(window); - if (!string.IsNullOrWhiteSpace(path)) { + var path = await DatabaseGui.NewOpenOrCreateDatabaseFileDialog(window, Path.GetDirectoryName(dbFilePath)); + if (path != null) { await OpenOrCreateDatabaseFromPath(path); } }