Replace deprecated file dialogs

This commit is contained in:
Michael Bucari-Tovo 2022-12-16 21:07:22 -07:00
parent 03f44b4e9c
commit 36efbcb812
6 changed files with 105 additions and 73 deletions

View File

@ -18,22 +18,6 @@ namespace LibationAvalonia
return defaultBrush; return defaultBrush;
} }
public static Window GetParentWindow(this IControl control) public static Window GetParentWindow(this IControl control) => control.VisualRoot as Window;
{
Window window = null;
var p = control.Parent;
while (p != null)
{
if (p is Window)
{
window = (Window)p;
break;
}
p = p.Parent;
}
return window;
}
} }
} }

View File

@ -5,6 +5,7 @@ using Dinah.Core;
using LibationFileManager; using LibationFileManager;
using System.Collections.Generic; using System.Collections.Generic;
using ReactiveUI; using ReactiveUI;
using System.Linq;
namespace LibationAvalonia.Controls namespace LibationAvalonia.Controls
{ {
@ -16,7 +17,6 @@ namespace LibationAvalonia.Controls
public static readonly StyledProperty<string> SubDirectoryProperty = public static readonly StyledProperty<string> SubDirectoryProperty =
AvaloniaProperty.Register<DirectorySelectControl, string>(nameof(SubDirectory)); AvaloniaProperty.Register<DirectorySelectControl, string>(nameof(SubDirectory));
public static readonly StyledProperty<string> DirectoryProperty = public static readonly StyledProperty<string> DirectoryProperty =
AvaloniaProperty.Register<DirectorySelectControl, string>(nameof(Directory)); AvaloniaProperty.Register<DirectorySelectControl, string>(nameof(Directory));
@ -90,8 +90,19 @@ namespace LibationAvalonia.Controls
private async void CustomDirBrowseBtn_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) private async void CustomDirBrowseBtn_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{ {
OpenFolderDialog ofd = new(); var options = new Avalonia.Platform.Storage.FolderPickerOpenOptions
customStates.CustomDir = await ofd.ShowAsync(VisualRoot as Window); {
AllowMultiple = false
};
var selectedFolders = await (VisualRoot as Window).StorageProvider.OpenFolderPickerAsync(options);
customStates.CustomDir =
selectedFolders
.SingleOrDefault()?.
TryGetUri(out var uri) is true
? uri.LocalPath
: customStates.CustomDir;
} }
private void CheckStates_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) private void CheckStates_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
@ -125,7 +136,6 @@ namespace LibationAvalonia.Controls
Directory = customStates.CustomChecked ? selectedDir : System.IO.Path.Combine(selectedDir, SubDirectory); Directory = customStates.CustomChecked ? selectedDir : System.IO.Path.Combine(selectedDir, SubDirectory);
} }
private void DirectoryOrCustomSelectControl_PropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e) private void DirectoryOrCustomSelectControl_PropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e)
{ {
if (e.Property.Name == nameof(Directory) && e.OldValue is null) if (e.Property.Name == nameof(Directory) && e.OldValue is null)

View File

@ -9,6 +9,9 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using ReactiveUI; using ReactiveUI;
using AudibleApi; using AudibleApi;
using Avalonia.Platform.Storage;
using LibationFileManager;
using Avalonia.Platform.Storage.FileIO;
namespace LibationAvalonia.Dialogs namespace LibationAvalonia.Dialogs
{ {
@ -110,24 +113,29 @@ namespace LibationAvalonia.Dialogs
public async void ImportButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e) public async void ImportButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{ {
var openFileDialogOptions = new FilePickerOpenOptions
OpenFileDialog ofd = new(); {
ofd.Filters.Add(new() { Name = "JSON File", Extensions = new() { "json" } }); Title = $"Select the audible-cli [account].json file",
ofd.Directory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); AllowMultiple = false,
ofd.AllowMultiple = false; SuggestedStartLocation = new BclStorageFolder(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)),
FileTypeFilter = new FilePickerFileType[]
{
new("JSON files (*.json)") { Patterns = new[] { "json" } },
}
};
string audibleAppDataDir = GetAudibleCliAppDataPath(); string audibleAppDataDir = GetAudibleCliAppDataPath();
if (Directory.Exists(audibleAppDataDir)) if (Directory.Exists(audibleAppDataDir))
ofd.Directory = audibleAppDataDir; openFileDialogOptions.SuggestedStartLocation = new BclStorageFolder(audibleAppDataDir);
var filePath = await ofd.ShowAsync(this); var selectedFiles = await StorageProvider.OpenFilePickerAsync(openFileDialogOptions);
var selectedFile = selectedFiles.SingleOrDefault();
if (filePath is null || filePath.Length == 0) return; if (!selectedFile.TryGetUri(out var uri)) return;
try try
{ {
var jsonText = File.ReadAllText(filePath[0]); var jsonText = File.ReadAllText(uri.LocalPath);
var mkbAuth = Mkb79Auth.FromJson(jsonText); var mkbAuth = Mkb79Auth.FromJson(jsonText);
var account = await mkbAuth.ToAccountAsync(); var account = await mkbAuth.ToAccountAsync();
@ -148,7 +156,7 @@ namespace LibationAvalonia.Dialogs
{ {
await MessageBox.ShowAdminAlert( await MessageBox.ShowAdminAlert(
this, this,
$"An error occurred while importing an account from:\r\n{filePath[0]}\r\n\r\nIs the file encrypted?", $"An error occurred while importing an account from:\r\n{uri.LocalPath}\r\n\r\nIs the file encrypted?",
"Error Importing Account", "Error Importing Account",
ex); ex);
} }
@ -263,26 +271,36 @@ namespace LibationAvalonia.Dialogs
return; return;
} }
SaveFileDialog sfd = new(); var options = new FilePickerSaveOptions
sfd.Filters.Add(new() { Name = "JSON File", Extensions = new() { "json" } }); {
Title = $"Save Sover Image",
SuggestedStartLocation = new BclStorageFolder(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)),
SuggestedFileName = $"{acc.AccountId}.json",
DefaultExtension = "json",
ShowOverwritePrompt = true,
FileTypeChoices = new FilePickerFileType[]
{
new("JSON files (*.json)") { Patterns = new[] { "json" } },
}
};
string audibleAppDataDir = GetAudibleCliAppDataPath(); string audibleAppDataDir = GetAudibleCliAppDataPath();
if (Directory.Exists(audibleAppDataDir)) if (Directory.Exists(audibleAppDataDir))
sfd.Directory = audibleAppDataDir; options.SuggestedStartLocation = new BclStorageFolder(audibleAppDataDir);
string fileName = await sfd.ShowAsync(this); var selectedFile = await StorageProvider.SaveFilePickerAsync(options);
if (fileName is null)
return; if (!selectedFile.TryGetUri(out var uri)) return;
try try
{ {
var mkbAuth = Mkb79Auth.FromAccount(account); var mkbAuth = Mkb79Auth.FromAccount(account);
var jsonText = mkbAuth.ToJson(); var jsonText = mkbAuth.ToJson();
File.WriteAllText(fileName, jsonText); File.WriteAllText(uri.LocalPath, jsonText);
await MessageBox.Show(this, $"Successfully exported {account.AccountName} to\r\n\r\n{fileName}", "Success!"); await MessageBox.Show(this, $"Successfully exported {account.AccountName} to\r\n\r\n{uri.LocalPath}", "Success!");
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -7,6 +7,7 @@ using System;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using ReactiveUI; using ReactiveUI;
using Avalonia.Platform.Storage;
namespace LibationAvalonia.Dialogs namespace LibationAvalonia.Dialogs
{ {
@ -46,27 +47,30 @@ namespace LibationAvalonia.Dialogs
public async void SaveImage_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e) public async void SaveImage_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{ {
var options = new FilePickerSaveOptions
{
Title = $"Save Sover Image",
SuggestedStartLocation = new Avalonia.Platform.Storage.FileIO.BclStorageFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)),
SuggestedFileName = $"{PictureFileName}.jpg",
DefaultExtension = "jpg",
ShowOverwritePrompt = true,
FileTypeChoices = new FilePickerFileType[]
{
new("Jpeg (*.jpg)") { Patterns = new[] { "jpg" } }
}
};
SaveFileDialog saveFileDialog = new(); var selectedFile = await StorageProvider.SaveFilePickerAsync(options);
saveFileDialog.Filters.Add(new FileDialogFilter { Name = "Jpeg", Extensions = new System.Collections.Generic.List<string>() { "jpg" } });
saveFileDialog.InitialFileName = PictureFileName;
saveFileDialog.Directory
= !LibationFileManager.Configuration.IsWindows ? null
: Directory.Exists(BookSaveDirectory) ? BookSaveDirectory
: Path.GetDirectoryName(BookSaveDirectory);
var fileName = await saveFileDialog.ShowAsync(this); if (!selectedFile.TryGetUri(out var uri)) return;
if (fileName is null)
return;
try try
{ {
File.WriteAllBytes(fileName, CoverBytes); File.WriteAllBytes(uri.LocalPath, CoverBytes);
} }
catch (Exception ex) catch (Exception ex)
{ {
Serilog.Log.Logger.Error(ex, $"Failed to save picture to {fileName}"); Serilog.Log.Logger.Error(ex, $"Failed to save picture to {uri.LocalPath}");
await MessageBox.Show(this, $"An error was encountered while trying to save the picture\r\n\r\n{ex.Message}", "Failed to save picture", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1); await MessageBox.Show(this, $"An error was encountered while trying to save the picture\r\n\r\n{ex.Message}", "Failed to save picture", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
} }
} }

View File

@ -1,5 +1,7 @@
using ApplicationServices; using ApplicationServices;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Platform.Storage;
using LibationFileManager;
using System; using System;
using System.Linq; using System.Linq;
@ -14,34 +16,42 @@ namespace LibationAvalonia.Views
{ {
try try
{ {
var saveFileDialog = new SaveFileDialog var options = new FilePickerSaveOptions
{ {
Title = "Where to export Library", Title = "Where to export Library",
SuggestedStartLocation = new Avalonia.Platform.Storage.FileIO.BclStorageFolder(Configuration.Instance.Books),
SuggestedFileName = $"Libation Library Export {DateTime.Now:yyyy-MM-dd}.xlsx",
DefaultExtension = "xlsx",
ShowOverwritePrompt = true,
FileTypeChoices = new FilePickerFileType[]
{
new("Excel Workbook (*.xlsx)") { Patterns = new[] { "xlsx" } },
new("CSV files (*.csv)") { Patterns = new[] { "csv" } },
new("JSON files (*.json)") { Patterns = new[] { "json" } },
new("All files (*.*)") { Patterns = new[] { "*" } },
}
}; };
saveFileDialog.Filters.Add(new FileDialogFilter { Name = "Excel Workbook (*.xlsx)", Extensions = new() { "xlsx" } });
saveFileDialog.Filters.Add(new FileDialogFilter { Name = "CSV files (*.csv)", Extensions = new() { "csv" } });
saveFileDialog.Filters.Add(new FileDialogFilter { Name = "JSON files (*.json)", Extensions = new() { "json" } });
saveFileDialog.Filters.Add(new FileDialogFilter { Name = "All files (*.*)", Extensions = new() { "*" } });
var fileName = await saveFileDialog.ShowAsync(this); var selectedFile = await StorageProvider.SaveFilePickerAsync(options);
if (fileName is null) return;
var ext = System.IO.Path.GetExtension(fileName); if (!selectedFile.TryGetUri(out var uri)) return;
var ext = System.IO.Path.GetExtension(uri.LocalPath);
switch (ext) switch (ext)
{ {
case "xlsx": // xlsx case "xlsx": // xlsx
default: default:
LibraryExporter.ToXlsx(fileName); LibraryExporter.ToXlsx(uri.LocalPath);
break; break;
case "csv": // csv case "csv": // csv
LibraryExporter.ToCsv(fileName); LibraryExporter.ToCsv(uri.LocalPath);
break; break;
case "json": // json case "json": // json
LibraryExporter.ToJson(fileName); LibraryExporter.ToJson(uri.LocalPath);
break; break;
} }
await MessageBox.Show("Library exported to:\r\n" + fileName, "Library Exported"); await MessageBox.Show("Library exported to:\r\n" + uri.LocalPath, "Library Exported");
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -6,6 +6,7 @@ using Avalonia;
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage;
using DataLayer; using DataLayer;
using FileLiberator; using FileLiberator;
using LibationAvalonia.Controls; using LibationAvalonia.Controls;
@ -42,7 +43,7 @@ namespace LibationAvalonia.Views
}; };
var pdvm = new ProductsDisplayViewModel(); var pdvm = new ProductsDisplayViewModel();
pdvm.DisplayBooksAsync(sampleEntries); _ = pdvm.DisplayBooksAsync(sampleEntries);
DataContext = pdvm; DataContext = pdvm;
return; return;
@ -106,17 +107,22 @@ namespace LibationAvalonia.Views
{ {
try try
{ {
var openFileDialog = new OpenFileDialog var openFileDialogOptions = new FilePickerOpenOptions
{ {
Title = $"Locate the audio file for '{entry.Book.Title}'", Title = $"Locate the audio file for '{entry.Book.Title}'",
Filters = new() { new() { Name = "All files (*.*)", Extensions = new() { "*" } } }, AllowMultiple = false,
AllowMultiple = false SuggestedStartLocation = new Avalonia.Platform.Storage.FileIO.BclStorageFolder(Configuration.Instance.Books),
FileTypeFilter = new FilePickerFileType[]
{
new("All files (*.*)") { Patterns = new[] { "*" } },
}
}; };
var filePaths = await openFileDialog.ShowAsync(this.GetParentWindow());
var filePath = filePaths.SingleOrDefault();
if (!string.IsNullOrWhiteSpace(filePath)) var selectedFiles = await this.GetParentWindow().StorageProvider.OpenFilePickerAsync(openFileDialogOptions);
FilePathCache.Insert(entry.AudibleProductId, filePath); var selectedFile = selectedFiles.SingleOrDefault();
if (selectedFile.TryGetUri(out var uri))
FilePathCache.Insert(entry.AudibleProductId, uri.LocalPath);
} }
catch (Exception ex) catch (Exception ex)
{ {