commit
f4749d703f
@ -11,6 +11,13 @@
|
|||||||
<ProjectReference Include="..\ApplicationServices\ApplicationServices.csproj" />
|
<ProjectReference Include="..\ApplicationServices\ApplicationServices.csproj" />
|
||||||
<ProjectReference Include="..\AudibleUtilities\AudibleUtilities.csproj" />
|
<ProjectReference Include="..\AudibleUtilities\AudibleUtilities.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<DefineConstants Condition=" '$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' ">$(DefineConstants);WINDOWS</DefineConstants>
|
||||||
|
<DefineConstants Condition=" '$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' ">$(DefineConstants);LINUX</DefineConstants>
|
||||||
|
<DefineConstants Condition=" '$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' ">$(DefineConstants);MACOS</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@ -14,8 +14,23 @@ using Serilog;
|
|||||||
|
|
||||||
namespace AppScaffolding
|
namespace AppScaffolding
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public enum ReleaseIdentifier
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
WindowsClassic,
|
||||||
|
WindowsAvalonia,
|
||||||
|
LinuxAvalonia,
|
||||||
|
MacOSAvalonia
|
||||||
|
}
|
||||||
|
|
||||||
public static class LibationScaffolding
|
public static class LibationScaffolding
|
||||||
{
|
{
|
||||||
|
public static ReleaseIdentifier ReleaseIdentifier { get; private set; }
|
||||||
|
|
||||||
|
public static void SetReleaseIdentifier(ReleaseIdentifier releaseID)
|
||||||
|
=> ReleaseIdentifier = releaseID;
|
||||||
|
|
||||||
// AppScaffolding
|
// AppScaffolding
|
||||||
private static Assembly _executingAssembly;
|
private static Assembly _executingAssembly;
|
||||||
private static Assembly ExecutingAssembly
|
private static Assembly ExecutingAssembly
|
||||||
@ -275,12 +290,23 @@ namespace AppScaffolding
|
|||||||
if (System.Diagnostics.Debugger.IsAttached)
|
if (System.Diagnostics.Debugger.IsAttached)
|
||||||
mode += " (Debugger attached)";
|
mode += " (Debugger attached)";
|
||||||
|
|
||||||
|
#if MACOS
|
||||||
|
var os = "MacOS";
|
||||||
|
#elif LINUX
|
||||||
|
var os = "Linux";
|
||||||
|
#else
|
||||||
|
var os = "Windows";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// begin logging session with a form feed
|
// begin logging session with a form feed
|
||||||
Log.Logger.Information("\r\n\f");
|
Log.Logger.Information("\r\n\f");
|
||||||
Log.Logger.Information("Begin. {@DebugInfo}", new
|
Log.Logger.Information("Begin. {@DebugInfo}", new
|
||||||
{
|
{
|
||||||
AppName = EntryAssembly.GetName().Name,
|
AppName = EntryAssembly.GetName().Name,
|
||||||
Version = BuildVersion.ToString(),
|
Version = BuildVersion.ToString(),
|
||||||
|
ReleaseIdentifier = ReleaseIdentifier,
|
||||||
|
OS = os,
|
||||||
Mode = mode,
|
Mode = mode,
|
||||||
LogLevel_Verbose_Enabled = Log.Logger.IsVerboseEnabled(),
|
LogLevel_Verbose_Enabled = Log.Logger.IsVerboseEnabled(),
|
||||||
LogLevel_Debug_Enabled = Log.Logger.IsDebugEnabled(),
|
LogLevel_Debug_Enabled = Log.Logger.IsDebugEnabled(),
|
||||||
@ -309,18 +335,10 @@ namespace AppScaffolding
|
|||||||
LibraryCommands.BookUserDefinedItemCommitted += (_, books) => SearchEngineCommands.UpdateBooks(books);
|
LibraryCommands.BookUserDefinedItemCommitted += (_, books) => SearchEngineCommands.UpdateBooks(books);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ReleaseIdentifier
|
public static UpgradeProperties GetLatestRelease()
|
||||||
{
|
|
||||||
WindowsClassic,
|
|
||||||
WindowsAvalonia,
|
|
||||||
LinuxAvalonia,
|
|
||||||
MacOSAvalonia
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UpgradeProperties GetLatestRelease(ReleaseIdentifier releaseID = ReleaseIdentifier.WindowsClassic)
|
|
||||||
{
|
{
|
||||||
// timed out
|
// timed out
|
||||||
(var latest, var zip) = getLatestRelease(TimeSpan.FromSeconds(10), releaseID);
|
(var latest, var zip) = getLatestRelease(TimeSpan.FromSeconds(10));
|
||||||
|
|
||||||
if (latest is null || zip is null)
|
if (latest is null || zip is null)
|
||||||
return null;
|
return null;
|
||||||
@ -346,11 +364,11 @@ namespace AppScaffolding
|
|||||||
|
|
||||||
return new(zipUrl, latest.HtmlUrl, zip.Name, latestRelease);
|
return new(zipUrl, latest.HtmlUrl, zip.Name, latestRelease);
|
||||||
}
|
}
|
||||||
private static (Octokit.Release, Octokit.ReleaseAsset) getLatestRelease(TimeSpan timeout, ReleaseIdentifier releaseID)
|
private static (Octokit.Release, Octokit.ReleaseAsset) getLatestRelease(TimeSpan timeout)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var task = getLatestRelease(releaseID);
|
var task = getLatestRelease();
|
||||||
if (task.Wait(timeout))
|
if (task.Wait(timeout))
|
||||||
return task.Result;
|
return task.Result;
|
||||||
|
|
||||||
@ -362,7 +380,7 @@ namespace AppScaffolding
|
|||||||
}
|
}
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
private static async System.Threading.Tasks.Task<(Octokit.Release, Octokit.ReleaseAsset)> getLatestRelease(ReleaseIdentifier releaseID)
|
private static async System.Threading.Tasks.Task<(Octokit.Release, Octokit.ReleaseAsset)> getLatestRelease()
|
||||||
{
|
{
|
||||||
var ownerAccount = "rmcrackan";
|
var ownerAccount = "rmcrackan";
|
||||||
var repoName = "Libation";
|
var repoName = "Libation";
|
||||||
@ -372,7 +390,7 @@ namespace AppScaffolding
|
|||||||
//Download the release index
|
//Download the release index
|
||||||
var bts = await gitHubClient.Repository.Content.GetRawContent(ownerAccount, repoName, ".releaseindex.json");
|
var bts = await gitHubClient.Repository.Content.GetRawContent(ownerAccount, repoName, ".releaseindex.json");
|
||||||
var releaseIndex = JObject.Parse(System.Text.Encoding.ASCII.GetString(bts));
|
var releaseIndex = JObject.Parse(System.Text.Encoding.ASCII.GetString(bts));
|
||||||
var regexPattern = releaseIndex.Value<string>(releaseID.ToString());
|
var regexPattern = releaseIndex.Value<string>(ReleaseIdentifier.ToString());
|
||||||
|
|
||||||
// https://octokitnet.readthedocs.io/en/latest/releases/
|
// https://octokitnet.readthedocs.io/en/latest/releases/
|
||||||
var releases = await gitHubClient.Repository.Release.GetAll(ownerAccount, repoName);
|
var releases = await gitHubClient.Repository.Release.GetAll(ownerAccount, repoName);
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<ApplicationIcon>hangover.ico</ApplicationIcon>
|
<ApplicationIcon>hangover.ico</ApplicationIcon>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<IsPublishable>true</IsPublishable>
|
||||||
<PublishReadyToRun>true</PublishReadyToRun>
|
<PublishReadyToRun>true</PublishReadyToRun>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
@ -54,4 +55,11 @@
|
|||||||
</Compile>
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="SpicNSpan" AfterTargets="Clean">
|
||||||
|
<!-- Remove obj folder -->
|
||||||
|
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
|
||||||
|
<!-- Remove bin folder -->
|
||||||
|
<RemoveDir Directories="$(BaseOutputPath)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@ -12,5 +12,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<SelfContained>true</SelfContained>
|
<SelfContained>true</SelfContained>
|
||||||
<PublishSingleFile>false</PublishSingleFile>
|
<PublishSingleFile>false</PublishSingleFile>
|
||||||
|
<PublishTrimmed>false</PublishTrimmed>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -17,10 +17,16 @@ namespace LibationAvalonia
|
|||||||
{
|
{
|
||||||
public class App : Application
|
public class App : Application
|
||||||
{
|
{
|
||||||
public static bool IsWindows => PlatformID is PlatformID.Win32NT;
|
public static readonly bool IsWindows;
|
||||||
public static bool IsUnix => PlatformID is PlatformID.Unix;
|
public static readonly bool IsLinux;
|
||||||
|
public static readonly bool IsMacOs;
|
||||||
|
static App()
|
||||||
|
{
|
||||||
|
IsWindows = OperatingSystem.IsWindows();
|
||||||
|
IsLinux = OperatingSystem.IsLinux();
|
||||||
|
IsMacOs = OperatingSystem.IsMacOS();
|
||||||
|
}
|
||||||
|
|
||||||
public static readonly PlatformID PlatformID = Environment.OSVersion.Platform;
|
|
||||||
public static IBrush ProcessQueueBookFailedBrush { get; private set; }
|
public static IBrush ProcessQueueBookFailedBrush { get; private set; }
|
||||||
public static IBrush ProcessQueueBookCompletedBrush { get; private set; }
|
public static IBrush ProcessQueueBookCompletedBrush { get; private set; }
|
||||||
public static IBrush ProcessQueueBookCancelledBrush { get; private set; }
|
public static IBrush ProcessQueueBookCancelledBrush { get; private set; }
|
||||||
@ -29,20 +35,20 @@ namespace LibationAvalonia
|
|||||||
|
|
||||||
public static IAssetLoader AssetLoader { get; private set; }
|
public static IAssetLoader AssetLoader { get; private set; }
|
||||||
|
|
||||||
public static readonly Uri AssetUriBase = new Uri("avares://Libation/Assets/");
|
public static readonly Uri AssetUriBase = new("avares://Libation/Assets/");
|
||||||
public static Stream OpenAsset(string assetRelativePath)
|
public static Stream OpenAsset(string assetRelativePath)
|
||||||
=> AssetLoader.Open(new Uri(AssetUriBase, assetRelativePath));
|
=> AssetLoader.Open(new Uri(AssetUriBase, assetRelativePath));
|
||||||
|
|
||||||
|
|
||||||
public static bool GoToFile(string path)
|
public static bool GoToFile(string path)
|
||||||
=> PlatformID is PlatformID.Win32NT ? Go.To.File(path)
|
=> IsWindows ? Go.To.File(path)
|
||||||
: GoToFolder(path is null ? string.Empty : Path.GetDirectoryName(path));
|
: GoToFolder(path is null ? string.Empty : Path.GetDirectoryName(path));
|
||||||
|
|
||||||
public static bool GoToFolder(string path)
|
public static bool GoToFolder(string path)
|
||||||
{
|
{
|
||||||
if (PlatformID is PlatformID.Win32NT)
|
if (IsWindows)
|
||||||
return Go.To.Folder(path);
|
return Go.To.Folder(path);
|
||||||
else
|
else if (IsLinux)
|
||||||
{
|
{
|
||||||
var startInfo = new System.Diagnostics.ProcessStartInfo()
|
var startInfo = new System.Diagnostics.ProcessStartInfo()
|
||||||
{
|
{
|
||||||
@ -56,6 +62,8 @@ namespace LibationAvalonia
|
|||||||
System.Diagnostics.Process.Start(startInfo);
|
System.Diagnostics.Process.Start(startInfo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
//Don't know how to do this for mac yet
|
||||||
|
else return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@ -107,7 +115,7 @@ namespace LibationAvalonia
|
|||||||
base.OnFrameworkInitializationCompleted();
|
base.OnFrameworkInitializationCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Setup_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
private async void Setup_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||||
{
|
{
|
||||||
var setupDialog = sender as SetupDialog;
|
var setupDialog = sender as SetupDialog;
|
||||||
var desktop = ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
|
var desktop = ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
|
||||||
@ -120,9 +128,9 @@ namespace LibationAvalonia
|
|||||||
|
|
||||||
if ((!setupDialog.IsNewUser
|
if ((!setupDialog.IsNewUser
|
||||||
&& !setupDialog.IsReturningUser) ||
|
&& !setupDialog.IsReturningUser) ||
|
||||||
!RunInstall(setupDialog))
|
!await RunInstall(setupDialog))
|
||||||
{
|
{
|
||||||
CancelInstallation();
|
await CancelInstallation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +138,7 @@ namespace LibationAvalonia
|
|||||||
// most migrations go in here
|
// most migrations go in here
|
||||||
AppScaffolding.LibationScaffolding.RunPostConfigMigrations(setupDialog.Config);
|
AppScaffolding.LibationScaffolding.RunPostConfigMigrations(setupDialog.Config);
|
||||||
|
|
||||||
MessageBox.VerboseLoggingWarning_ShowIfTrue();
|
await MessageBox.VerboseLoggingWarning_ShowIfTrue();
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
//AutoUpdater.NET only works for WinForms or WPF application projects.
|
//AutoUpdater.NET only works for WinForms or WPF application projects.
|
||||||
@ -146,11 +154,11 @@ namespace LibationAvalonia
|
|||||||
var body = "An unrecoverable error occurred. Since this error happened before logging could be initialized, this error can not be written to the log file.";
|
var body = "An unrecoverable error occurred. Since this error happened before logging could be initialized, this error can not be written to the log file.";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MessageBox.ShowAdminAlert(null, body, title, ex);
|
await MessageBox.ShowAdminAlert(null, body, title, ex);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
MessageBox.Show($"{body}\r\n\r\n{ex.Message}\r\n\r\n{ex.StackTrace}", title, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
await MessageBox.Show($"{body}\r\n\r\n{ex.Message}\r\n\r\n{ex.StackTrace}", title, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -160,7 +168,7 @@ namespace LibationAvalonia
|
|||||||
ShowMainWindow(desktop);
|
ShowMainWindow(desktop);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool RunInstall(SetupDialog setupDialog)
|
private static async Task<bool> RunInstall(SetupDialog setupDialog)
|
||||||
{
|
{
|
||||||
var config = setupDialog.Config;
|
var config = setupDialog.Config;
|
||||||
|
|
||||||
@ -173,7 +181,7 @@ namespace LibationAvalonia
|
|||||||
|
|
||||||
var libationFilesDialog = new LibationFilesDialog();
|
var libationFilesDialog = new LibationFilesDialog();
|
||||||
|
|
||||||
if (libationFilesDialog.ShowDialogSynchronously<DialogResult>(setupDialog) != DialogResult.OK)
|
if (await libationFilesDialog.ShowDialog<DialogResult>(setupDialog) != DialogResult.OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
config.SetLibationFiles(libationFilesDialog.SelectedDirectory);
|
config.SetLibationFiles(libationFilesDialog.SelectedDirectory);
|
||||||
@ -181,7 +189,7 @@ namespace LibationAvalonia
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// path did not result in valid settings
|
// path did not result in valid settings
|
||||||
var continueResult = MessageBox.Show(
|
var continueResult = await MessageBox.Show(
|
||||||
$"No valid settings were found at this location.\r\nWould you like to create a new install settings in this folder?\r\n\r\n{libationFilesDialog.SelectedDirectory}",
|
$"No valid settings were found at this location.\r\nWould you like to create a new install settings in this folder?\r\n\r\n{libationFilesDialog.SelectedDirectory}",
|
||||||
"New install?",
|
"New install?",
|
||||||
MessageBoxButtons.YesNo,
|
MessageBoxButtons.YesNo,
|
||||||
@ -196,13 +204,13 @@ namespace LibationAvalonia
|
|||||||
config.Books ??= Path.Combine(Configuration.UserProfile, "Books");
|
config.Books ??= Path.Combine(Configuration.UserProfile, "Books");
|
||||||
|
|
||||||
AppScaffolding.LibationScaffolding.PopulateMissingConfigValues(config);
|
AppScaffolding.LibationScaffolding.PopulateMissingConfigValues(config);
|
||||||
return new SettingsDialog().ShowDialogSynchronously<DialogResult>(setupDialog) == DialogResult.OK
|
return await new SettingsDialog().ShowDialog<DialogResult>(setupDialog) == DialogResult.OK
|
||||||
&& config.LibationSettingsAreValid;
|
&& config.LibationSettingsAreValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CancelInstallation()
|
static async Task CancelInstallation()
|
||||||
{
|
{
|
||||||
MessageBox.Show("Initial set up cancelled.", "Cancelled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
await MessageBox.Show("Initial set up cancelled.", "Cancelled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Avalonia.Threading
|
|
||||||
{
|
|
||||||
internal static class AvaloniaThreadUtils
|
|
||||||
{
|
|
||||||
public static TResult Invoke<TResult>(this Dispatcher dispatcher, Func<TResult> function, DispatcherPriority dispatcherPriority = DispatcherPriority.Normal)
|
|
||||||
=> WaitOnDispatcherAndGetResult(dispatcher.InvokeAsync(function, dispatcherPriority), dispatcher);
|
|
||||||
|
|
||||||
public static void Invoke(this Dispatcher dispatcher, Action action, DispatcherPriority dispatcherPriority = DispatcherPriority.Normal)
|
|
||||||
=> WaitOnDispatcher(dispatcher.InvokeAsync(action, dispatcherPriority), dispatcher);
|
|
||||||
|
|
||||||
public static TResult WaitOnDispatcherAndGetResult<TResult>(this Task<TResult> task, Dispatcher dispatcher)
|
|
||||||
{
|
|
||||||
using var source = new CancellationTokenSource();
|
|
||||||
task.ContinueWith(t => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext());
|
|
||||||
dispatcher.MainLoop(source.Token);
|
|
||||||
return task.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WaitOnDispatcher(this Task task, Dispatcher dispatcher)
|
|
||||||
{
|
|
||||||
using var source = new CancellationTokenSource();
|
|
||||||
task.ContinueWith(t => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext());
|
|
||||||
dispatcher.MainLoop(source.Token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -16,10 +16,5 @@ namespace LibationAvalonia
|
|||||||
return brush;
|
return brush;
|
||||||
return defaultBrush;
|
return defaultBrush;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T ShowDialogSynchronously<T>(this Avalonia.Controls.Window window, Avalonia.Controls.Window owner)
|
|
||||||
{
|
|
||||||
return window.ShowDialog<T>(owner).WaitOnDispatcherAndGetResult(Dispatcher.UIThread);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,7 @@ namespace LibationAvalonia.Controls
|
|||||||
set => SetValue(SubDirectoryProperty, value);
|
set => SetValue(SubDirectoryProperty, value);
|
||||||
}
|
}
|
||||||
CustomState customStates = new();
|
CustomState customStates = new();
|
||||||
|
|
||||||
public DirectoryOrCustomSelectControl()
|
public DirectoryOrCustomSelectControl()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@ -53,9 +54,8 @@ namespace LibationAvalonia.Controls
|
|||||||
customDirBrowseBtn.Click += CustomDirBrowseBtn_Click;
|
customDirBrowseBtn.Click += CustomDirBrowseBtn_Click;
|
||||||
PropertyChanged += DirectoryOrCustomSelectControl_PropertyChanged;
|
PropertyChanged += DirectoryOrCustomSelectControl_PropertyChanged;
|
||||||
directorySelectControl.PropertyChanged += DirectorySelectControl_PropertyChanged;
|
directorySelectControl.PropertyChanged += DirectorySelectControl_PropertyChanged;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CustomState: ViewModels.ViewModelBase
|
private class CustomState: ViewModels.ViewModelBase
|
||||||
{
|
{
|
||||||
private string _customDir;
|
private string _customDir;
|
||||||
@ -116,12 +116,13 @@ namespace LibationAvalonia.Controls
|
|||||||
|
|
||||||
private void setDirectory()
|
private void setDirectory()
|
||||||
{
|
{
|
||||||
var path1
|
var selectedDir
|
||||||
= customStates.CustomChecked ? customStates.CustomDir
|
= customStates.CustomChecked ? customStates.CustomDir
|
||||||
: directorySelectControl.SelectedDirectory is Configuration.KnownDirectories.AppDir ? Configuration.AppDir_Absolute
|
: directorySelectControl.SelectedDirectory is Configuration.KnownDirectories.AppDir ? Configuration.AppDir_Absolute
|
||||||
: Configuration.GetKnownDirectoryPath(directorySelectControl.SelectedDirectory);
|
: Configuration.GetKnownDirectoryPath(directorySelectControl.SelectedDirectory);
|
||||||
Directory
|
selectedDir ??= string.Empty;
|
||||||
= System.IO.Path.Combine(path1 ?? string.Empty, SubDirectory);
|
|
||||||
|
Directory = customStates.CustomChecked ? selectedDir : System.IO.Path.Combine(selectedDir, SubDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -140,7 +141,7 @@ namespace LibationAvalonia.Controls
|
|||||||
if (known is Configuration.KnownDirectories.None)
|
if (known is Configuration.KnownDirectories.None)
|
||||||
{
|
{
|
||||||
customStates.CustomChecked = true;
|
customStates.CustomChecked = true;
|
||||||
customStates.CustomDir = noSubDir;
|
customStates.CustomDir = directory;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -136,7 +136,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
|
|
||||||
if (persister.AccountsSettings.Accounts.Any(a => a.AccountId == account.AccountId && a.IdentityTokens.Locale.Name == account.Locale.Name))
|
if (persister.AccountsSettings.Accounts.Any(a => a.AccountId == account.AccountId && a.IdentityTokens.Locale.Name == account.Locale.Name))
|
||||||
{
|
{
|
||||||
MessageBox.Show(this, $"An account with that account id and country already exists.\r\n\r\nAccount ID: {account.AccountId}\r\nCountry: {account.Locale.Name}", "Cannot Add Duplicate Account");
|
await MessageBox.Show(this, $"An account with that account id and country already exists.\r\n\r\nAccount ID: {account.AccountId}\r\nCountry: {account.Locale.Name}", "Cannot Add Duplicate Account");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
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{filePath[0]}\r\n\r\nIs the file encrypted?",
|
||||||
"Error Importing Account",
|
"Error Importing Account",
|
||||||
@ -160,11 +160,11 @@ namespace LibationAvalonia.Dialogs
|
|||||||
Export(acc);
|
Export(acc);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SaveAndClose()
|
protected override async Task SaveAndCloseAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!inputIsValid())
|
if (!await inputIsValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// without transaction, accounts persister will write ANY EDIT immediately to file
|
// without transaction, accounts persister will write ANY EDIT immediately to file
|
||||||
@ -178,7 +178,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.ShowAdminAlert(this, "Error attempting to save accounts", "Error saving accounts", ex);
|
await MessageBox.ShowAdminAlert(this, "Error attempting to save accounts", "Error saving accounts", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
: dto.AccountName.Trim();
|
: dto.AccountName.Trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private bool inputIsValid()
|
private async Task<bool> inputIsValid()
|
||||||
{
|
{
|
||||||
foreach (var dto in Accounts.ToList())
|
foreach (var dto in Accounts.ToList())
|
||||||
{
|
{
|
||||||
@ -233,13 +233,13 @@ namespace LibationAvalonia.Dialogs
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(dto.AccountId))
|
if (string.IsNullOrWhiteSpace(dto.AccountId))
|
||||||
{
|
{
|
||||||
MessageBox.Show(this, "Account id cannot be blank. Please enter an account id for all accounts.", "Blank account", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
await MessageBox.Show(this, "Account id cannot be blank. Please enter an account id for all accounts.", "Blank account", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(dto.SelectedLocale?.Name))
|
if (string.IsNullOrWhiteSpace(dto.SelectedLocale?.Name))
|
||||||
{
|
{
|
||||||
MessageBox.Show(this, "Please select a locale (i.e.: country or region) for all accounts.", "Blank region", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
await MessageBox.Show(this, "Please select a locale (i.e.: country or region) for all accounts.", "Blank region", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -259,7 +259,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
|
|
||||||
if (account.IdentityTokens?.IsValid != true)
|
if (account.IdentityTokens?.IsValid != true)
|
||||||
{
|
{
|
||||||
MessageBox.Show(this, "This account hasn't been authenticated yet. First scan your library to log into your account, then try exporting again.", "Account Not Authenticated");
|
await MessageBox.Show(this, "This account hasn't been authenticated yet. First scan your library to log into your account, then try exporting again.", "Account Not Authenticated");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,11 +282,11 @@ namespace LibationAvalonia.Dialogs
|
|||||||
|
|
||||||
File.WriteAllText(fileName, jsonText);
|
File.WriteAllText(fileName, jsonText);
|
||||||
|
|
||||||
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{fileName}", "Success!");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.ShowAdminAlert(
|
await MessageBox.ShowAdminAlert(
|
||||||
this,
|
this,
|
||||||
$"An error occurred while exporting account:\r\n{account.AccountName}",
|
$"An error occurred while exporting account:\r\n{account.AccountName}",
|
||||||
"Error Exporting Account",
|
"Error Exporting Account",
|
||||||
|
|||||||
@ -64,7 +64,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
}
|
}
|
||||||
protected override async Task SaveAndCloseAsync()
|
protected override async Task SaveAndCloseAsync()
|
||||||
{
|
{
|
||||||
if (!_viewModel.Validate())
|
if (!await _viewModel.Validate())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TemplateText = _viewModel.workingTemplateText;
|
TemplateText = _viewModel.workingTemplateText;
|
||||||
@ -115,7 +115,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
|
|
||||||
public void resetTextBox(string value) => workingTemplateText = value;
|
public void resetTextBox(string value) => workingTemplateText = value;
|
||||||
|
|
||||||
public bool Validate()
|
public async Task<bool> Validate()
|
||||||
{
|
{
|
||||||
if (template.IsValid(workingTemplateText))
|
if (template.IsValid(workingTemplateText))
|
||||||
return true;
|
return true;
|
||||||
@ -123,7 +123,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
.GetErrors(workingTemplateText)
|
.GetErrors(workingTemplateText)
|
||||||
.Select(err => $"- {err}")
|
.Select(err => $"- {err}")
|
||||||
.Aggregate((a, b) => $"{a}\r\n{b}");
|
.Aggregate((a, b) => $"{a}\r\n{b}");
|
||||||
MessageBox.Show($"This template text is not valid. Errors:\r\n{errors}", "Invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
await MessageBox.Show($"This template text is not valid. Errors:\r\n{errors}", "Invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -51,7 +51,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
saveFileDialog.Filters.Add(new FileDialogFilter { Name = "Jpeg", Extensions = new System.Collections.Generic.List<string>() { "jpg" } });
|
saveFileDialog.Filters.Add(new FileDialogFilter { Name = "Jpeg", Extensions = new System.Collections.Generic.List<string>() { "jpg" } });
|
||||||
saveFileDialog.InitialFileName = PictureFileName;
|
saveFileDialog.InitialFileName = PictureFileName;
|
||||||
saveFileDialog.Directory
|
saveFileDialog.Directory
|
||||||
= App.IsUnix ? null
|
= !App.IsWindows ? null
|
||||||
: Directory.Exists(BookSaveDirectory) ? BookSaveDirectory
|
: Directory.Exists(BookSaveDirectory) ? BookSaveDirectory
|
||||||
: Path.GetDirectoryName(BookSaveDirectory);
|
: Path.GetDirectoryName(BookSaveDirectory);
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
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 {fileName}");
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,14 +33,14 @@ namespace LibationAvalonia.Dialogs
|
|||||||
DataContext = dirSelectOptions = new();
|
DataContext = dirSelectOptions = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
public async void SaveButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
|
||||||
var libationDir = dirSelectOptions.Directory;
|
var libationDir = dirSelectOptions.Directory;
|
||||||
|
|
||||||
if (!System.IO.Directory.Exists(libationDir))
|
if (!System.IO.Directory.Exists(libationDir))
|
||||||
{
|
{
|
||||||
MessageBox.Show("Not saving change to Libation Files location. This folder does not exist:\r\n" + libationDir, "Folder does not exist", MessageBoxButtons.OK, MessageBoxIcon.Error, saveAndRestorePosition: false);
|
await MessageBox.Show("Not saving change to Libation Files location. This folder does not exist:\r\n" + libationDir, "Folder does not exist", MessageBoxButtons.OK, MessageBoxIcon.Error, saveAndRestorePosition: false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,12 +9,12 @@ namespace LibationAvalonia.Dialogs.Login
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// <returns>True if ShowDialog's DialogResult == OK</returns>
|
/// <returns>True if ShowDialog's DialogResult == OK</returns>
|
||||||
protected static bool ShowDialog(DialogWindow dialog)
|
protected static async Task<bool> ShowDialog(DialogWindow dialog)
|
||||||
{
|
{
|
||||||
if (Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
|
if (Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var result = dialog.ShowDialogSynchronously<DialogResult>(desktop.MainWindow);
|
var result = await dialog.ShowDialog<DialogResult>(desktop.MainWindow);
|
||||||
Serilog.Log.Logger.Debug("{@DebugInfo}", new { DialogResult = result });
|
Serilog.Log.Logger.Debug("{@DebugInfo}", new { DialogResult = result });
|
||||||
return result == DialogResult.OK;
|
return result == DialogResult.OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using AudibleApi;
|
using AudibleApi;
|
||||||
using AudibleUtilities;
|
using AudibleUtilities;
|
||||||
|
|
||||||
@ -13,43 +14,43 @@ namespace LibationAvalonia.Dialogs.Login
|
|||||||
_account = Dinah.Core.ArgumentValidator.EnsureNotNull(account, nameof(account));
|
_account = Dinah.Core.ArgumentValidator.EnsureNotNull(account, nameof(account));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Get2faCode()
|
public async Task<string> Get2faCodeAsync()
|
||||||
{
|
{
|
||||||
var dialog = new _2faCodeDialog();
|
var dialog = new _2faCodeDialog();
|
||||||
if (ShowDialog(dialog))
|
if (await ShowDialog(dialog))
|
||||||
return dialog.Code;
|
return dialog.Code;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetCaptchaAnswer(byte[] captchaImage)
|
public async Task<string> GetCaptchaAnswerAsync(byte[] captchaImage)
|
||||||
{
|
{
|
||||||
var dialog = new CaptchaDialog(captchaImage);
|
var dialog = new CaptchaDialog(captchaImage);
|
||||||
if (ShowDialog(dialog))
|
if (await ShowDialog(dialog))
|
||||||
return dialog.Answer;
|
return dialog.Answer;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public (string name, string value) GetMfaChoice(MfaConfig mfaConfig)
|
public async Task<(string name, string value)> GetMfaChoiceAsync(MfaConfig mfaConfig)
|
||||||
{
|
{
|
||||||
var dialog = new MfaDialog(mfaConfig);
|
var dialog = new MfaDialog(mfaConfig);
|
||||||
if (ShowDialog(dialog))
|
if (await ShowDialog(dialog))
|
||||||
return (dialog.SelectedName, dialog.SelectedValue);
|
return (dialog.SelectedName, dialog.SelectedValue);
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public (string email, string password) GetLogin()
|
public async Task<(string email, string password)> GetLoginAsync()
|
||||||
{
|
{
|
||||||
var dialog = new LoginCallbackDialog(_account);
|
var dialog = new LoginCallbackDialog(_account);
|
||||||
if (ShowDialog(dialog))
|
if (await ShowDialog(dialog))
|
||||||
return (_account.AccountId, dialog.Password);
|
return (_account.AccountId, dialog.Password);
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowApprovalNeeded()
|
public async Task ShowApprovalNeededAsync()
|
||||||
{
|
{
|
||||||
var dialog = new ApprovalNeededDialog();
|
var dialog = new ApprovalNeededDialog();
|
||||||
ShowDialog(dialog);
|
await ShowDialog(dialog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -20,11 +20,11 @@ namespace LibationAvalonia.Dialogs.Login
|
|||||||
LoginCallback = new AvaloniaLoginCallback(_account);
|
LoginCallback = new AvaloniaLoginCallback(_account);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChoiceOut Start(ChoiceIn choiceIn)
|
public async Task<ChoiceOut> StartAsync(ChoiceIn choiceIn)
|
||||||
{
|
{
|
||||||
var dialog = new LoginChoiceEagerDialog(_account);
|
var dialog = new LoginChoiceEagerDialog(_account);
|
||||||
|
|
||||||
if (!ShowDialog(dialog))
|
if (!await ShowDialog(dialog))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|
||||||
@ -33,15 +33,16 @@ namespace LibationAvalonia.Dialogs.Login
|
|||||||
case LoginMethod.Api:
|
case LoginMethod.Api:
|
||||||
return ChoiceOut.WithApi(dialog.Account.AccountId, dialog.Password);
|
return ChoiceOut.WithApi(dialog.Account.AccountId, dialog.Password);
|
||||||
case LoginMethod.External:
|
case LoginMethod.External:
|
||||||
{
|
{
|
||||||
var externalDialog = new LoginExternalDialog(_account, choiceIn.LoginUrl);
|
var externalDialog = new LoginExternalDialog(_account, choiceIn.LoginUrl);
|
||||||
return ShowDialog(externalDialog)
|
return await ShowDialog(externalDialog)
|
||||||
? ChoiceOut.External(externalDialog.ResponseUrl)
|
? ChoiceOut.External(externalDialog.ResponseUrl)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw new Exception($"Unknown {nameof(LoginMethod)} value");
|
throw new Exception($"Unknown {nameof(LoginMethod)} value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,7 +51,7 @@ namespace LibationAvalonia.Dialogs.Login
|
|||||||
Serilog.Log.Logger.Information("Submit button clicked: {@DebugInfo}", new { ResponseUrl });
|
Serilog.Log.Logger.Information("Submit button clicked: {@DebugInfo}", new { ResponseUrl });
|
||||||
if (!Uri.TryCreate(ResponseUrl, UriKind.Absolute, out var result))
|
if (!Uri.TryCreate(ResponseUrl, UriKind.Absolute, out var result))
|
||||||
{
|
{
|
||||||
MessageBox.Show("Invalid response URL");
|
await MessageBox.Show("Invalid response URL");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await base.SaveAndCloseAsync();
|
await base.SaveAndCloseAsync();
|
||||||
|
|||||||
@ -82,7 +82,7 @@ namespace LibationAvalonia.Dialogs.Login
|
|||||||
});
|
});
|
||||||
if (selected is null)
|
if (selected is null)
|
||||||
{
|
{
|
||||||
MessageBox.Show("No MFA option selected", "None selected", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
await MessageBox.Show("No MFA option selected", "None selected", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
DataContext = this;
|
DataContext = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GoToGithub_Tapped(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
private async void GoToGithub_Tapped(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var url = "https://github.com/rmcrackan/Libation/issues";
|
var url = "https://github.com/rmcrackan/Libation/issues";
|
||||||
try
|
try
|
||||||
@ -37,11 +37,11 @@ namespace LibationAvalonia.Dialogs
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
MessageBox.Show($"Error opening url\r\n{url}", "Error opening url", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
await MessageBox.Show($"Error opening url\r\n{url}", "Error opening url", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GoToLogs_Tapped(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
private async void GoToLogs_Tapped(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
LongPath dir = "";
|
LongPath dir = "";
|
||||||
try
|
try
|
||||||
@ -56,7 +56,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
MessageBox.Show($"Error opening folder\r\n{dir}", "Error opening folder", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
await MessageBox.Show($"Error opening folder\r\n{dir}", "Error opening folder", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,10 +33,10 @@ namespace LibationAvalonia.Dialogs
|
|||||||
|
|
||||||
protected override async Task SaveAndCloseAsync()
|
protected override async Task SaveAndCloseAsync()
|
||||||
{
|
{
|
||||||
if (!settingsDisp.SaveSettings(config))
|
if (!await settingsDisp.SaveSettingsAsync(config))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MessageBox.VerboseLoggingWarning_ShowIfTrue();
|
await MessageBox.VerboseLoggingWarning_ShowIfTrue();
|
||||||
await base.SaveAndCloseAsync();
|
await base.SaveAndCloseAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
internal interface ISettingsDisplay
|
internal interface ISettingsDisplay
|
||||||
{
|
{
|
||||||
void LoadSettings(Configuration config);
|
void LoadSettings(Configuration config);
|
||||||
bool SaveSettings(Configuration config);
|
Task<bool> SaveSettingsAsync(Configuration config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SettingsPages : ISettingsDisplay
|
public class SettingsPages : ISettingsDisplay
|
||||||
@ -120,12 +120,12 @@ namespace LibationAvalonia.Dialogs
|
|||||||
AudioSettings = new(config);
|
AudioSettings = new(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SaveSettings(Configuration config)
|
public async Task<bool> SaveSettingsAsync(Configuration config)
|
||||||
{
|
{
|
||||||
var result = ImportantSettings.SaveSettings(config);
|
var result = await ImportantSettings.SaveSettingsAsync(config);
|
||||||
result &= ImportSettings.SaveSettings(config);
|
result &= await ImportSettings.SaveSettingsAsync(config);
|
||||||
result &= DownloadDecryptSettings.SaveSettings(config);
|
result &= await DownloadDecryptSettings.SaveSettingsAsync(config);
|
||||||
result &= AudioSettings.SaveSettings(config);
|
result &= await AudioSettings.SaveSettingsAsync(config);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -146,13 +146,13 @@ namespace LibationAvalonia.Dialogs
|
|||||||
BetaOptIn = config.BetaOptIn;
|
BetaOptIn = config.BetaOptIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SaveSettings(Configuration config)
|
public async Task<bool> SaveSettingsAsync(Configuration config)
|
||||||
{
|
{
|
||||||
#region validation
|
#region validation
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(BooksDirectory))
|
if (string.IsNullOrWhiteSpace(BooksDirectory))
|
||||||
{
|
{
|
||||||
MessageBox.Show("Cannot set Books Location to blank", "Location is blank", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
await MessageBox.Show("Cannot set Books Location to blank", "Location is blank", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,14 +204,14 @@ namespace LibationAvalonia.Dialogs
|
|||||||
AutoDownloadEpisodes = config.AutoDownloadEpisodes;
|
AutoDownloadEpisodes = config.AutoDownloadEpisodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SaveSettings(Configuration config)
|
public Task<bool> SaveSettingsAsync(Configuration config)
|
||||||
{
|
{
|
||||||
config.AutoScan = AutoScan;
|
config.AutoScan = AutoScan;
|
||||||
config.ShowImportedStats = ShowImportedStats;
|
config.ShowImportedStats = ShowImportedStats;
|
||||||
config.ImportEpisodes = ImportEpisodes;
|
config.ImportEpisodes = ImportEpisodes;
|
||||||
config.DownloadEpisodes = DownloadEpisodes;
|
config.DownloadEpisodes = DownloadEpisodes;
|
||||||
config.AutoDownloadEpisodes = AutoDownloadEpisodes;
|
config.AutoDownloadEpisodes = AutoDownloadEpisodes;
|
||||||
return true;
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string AutoScanText { get; } = Configuration.GetDescription(nameof(Configuration.AutoScan));
|
public string AutoScanText { get; } = Configuration.GetDescription(nameof(Configuration.AutoScan));
|
||||||
@ -259,25 +259,25 @@ namespace LibationAvalonia.Dialogs
|
|||||||
: Configuration.GetKnownDirectory(config.InProgress);
|
: Configuration.GetKnownDirectory(config.InProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SaveSettings(Configuration config)
|
public async Task<bool> SaveSettingsAsync(Configuration config)
|
||||||
{
|
{
|
||||||
static void validationError(string text, string caption)
|
static Task validationError(string text, string caption)
|
||||||
=> MessageBox.Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
=> MessageBox.Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
|
||||||
// these 3 should do nothing. Configuration will only init these with a valid value. EditTemplateDialog ensures valid before returning
|
// these 3 should do nothing. Configuration will only init these with a valid value. EditTemplateDialog ensures valid before returning
|
||||||
if (!Templates.Folder.IsValid(FolderTemplate))
|
if (!Templates.Folder.IsValid(FolderTemplate))
|
||||||
{
|
{
|
||||||
validationError($"Not saving change to folder naming template. Invalid format.", "Invalid folder template");
|
await validationError($"Not saving change to folder naming template. Invalid format.", "Invalid folder template");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Templates.File.IsValid(FileTemplate))
|
if (!Templates.File.IsValid(FileTemplate))
|
||||||
{
|
{
|
||||||
validationError($"Not saving change to file naming template. Invalid format.", "Invalid file template");
|
await validationError($"Not saving change to file naming template. Invalid format.", "Invalid file template");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Templates.ChapterFile.IsValid(ChapterFileTemplate))
|
if (!Templates.ChapterFile.IsValid(ChapterFileTemplate))
|
||||||
{
|
{
|
||||||
validationError($"Not saving change to chapter file naming template. Invalid format.", "Invalid chapter file template");
|
await validationError($"Not saving change to chapter file naming template. Invalid format.", "Invalid chapter file template");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,7 +405,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
LameVBRQuality = config.LameVBRQuality;
|
LameVBRQuality = config.LameVBRQuality;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SaveSettings(Configuration config)
|
public Task<bool> SaveSettingsAsync(Configuration config)
|
||||||
{
|
{
|
||||||
config.CreateCueSheet = CreateCueSheet;
|
config.CreateCueSheet = CreateCueSheet;
|
||||||
config.AllowLibationFixup = AllowLibationFixup;
|
config.AllowLibationFixup = AllowLibationFixup;
|
||||||
@ -424,7 +424,7 @@ namespace LibationAvalonia.Dialogs
|
|||||||
config.LameBitrate = LameBitrate;
|
config.LameBitrate = LameBitrate;
|
||||||
config.LameVBRQuality = LameVBRQuality;
|
config.LameVBRQuality = LameVBRQuality;
|
||||||
|
|
||||||
return true;
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string CreateCueSheetText { get; } = Configuration.GetDescription(nameof(Configuration.CreateCueSheet));
|
public string CreateCueSheetText { get; } = Configuration.GetDescription(nameof(Configuration.CreateCueSheet));
|
||||||
|
|||||||
@ -113,7 +113,7 @@ namespace LibationAvalonia
|
|||||||
|
|
||||||
public static void HideMinMaxBtns(this Window form)
|
public static void HideMinMaxBtns(this Window form)
|
||||||
{
|
{
|
||||||
if (Design.IsDesignMode || App.PlatformID is not PlatformID.Win32NT)
|
if (Design.IsDesignMode || !App.IsWindows)
|
||||||
return;
|
return;
|
||||||
var handle = form.PlatformImpl.Handle.Handle;
|
var handle = form.PlatformImpl.Handle.Handle;
|
||||||
var currentStyle = GetWindowLong(handle, GWL_STYLE);
|
var currentStyle = GetWindowLong(handle, GWL_STYLE);
|
||||||
|
|||||||
@ -10,6 +10,8 @@
|
|||||||
<ApplicationIcon>libation.ico</ApplicationIcon>
|
<ApplicationIcon>libation.ico</ApplicationIcon>
|
||||||
<AssemblyName>Libation</AssemblyName>
|
<AssemblyName>Libation</AssemblyName>
|
||||||
|
|
||||||
|
<IsPublishable>true</IsPublishable>
|
||||||
|
|
||||||
<PublishReadyToRun>true</PublishReadyToRun>
|
<PublishReadyToRun>true</PublishReadyToRun>
|
||||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||||
@ -81,8 +83,6 @@
|
|||||||
<None Remove="Assets\SEGOEUI.TTF" />
|
<None Remove="Assets\SEGOEUI.TTF" />
|
||||||
<None Remove="Assets\up.png" />
|
<None Remove="Assets\up.png" />
|
||||||
<None Remove="Assets\WINGDING.TTF" />
|
<None Remove="Assets\WINGDING.TTF" />
|
||||||
<None Remove="MessageBox.cs~RF105afb8d.TMP" />
|
|
||||||
<None Remove="Views\MainWindow\MainWindow.Export.axaml.cs~RF10732d95.TMP" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -144,4 +144,12 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<Target Name="SpicNSpan" AfterTargets="Clean">
|
||||||
|
<!-- Remove obj folder -->
|
||||||
|
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
|
||||||
|
<!-- Remove bin folder -->
|
||||||
|
<RemoveDir Directories="$(BaseOutputPath)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@ -62,34 +62,34 @@ namespace LibationAvalonia
|
|||||||
public class MessageBox
|
public class MessageBox
|
||||||
{
|
{
|
||||||
|
|
||||||
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
|
public static Task<DialogResult> Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
|
||||||
=> ShowCoreAsync(null, text, caption, buttons, icon, defaultButton);
|
=> ShowCoreAsync(null, text, caption, buttons, icon, defaultButton);
|
||||||
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, bool saveAndRestorePosition = true)
|
public static Task<DialogResult> Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, bool saveAndRestorePosition = true)
|
||||||
=> ShowCoreAsync(null, text, caption, buttons, icon, MessageBoxDefaultButton.Button1, saveAndRestorePosition);
|
=> ShowCoreAsync(null, text, caption, buttons, icon, MessageBoxDefaultButton.Button1, saveAndRestorePosition);
|
||||||
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons)
|
public static Task<DialogResult> Show(string text, string caption, MessageBoxButtons buttons)
|
||||||
=> ShowCoreAsync(null, text, caption, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
=> ShowCoreAsync(null, text, caption, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
||||||
public static DialogResult Show(string text, string caption)
|
public static Task<DialogResult> Show(string text, string caption)
|
||||||
=> ShowCoreAsync(null, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
=> ShowCoreAsync(null, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
||||||
public static DialogResult Show(string text)
|
public static Task<DialogResult> Show(string text)
|
||||||
=> ShowCoreAsync(null, text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
=> ShowCoreAsync(null, text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
||||||
public static DialogResult Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
|
public static Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
|
||||||
=> ShowCoreAsync(owner, text, caption, buttons, icon, defaultButton);
|
=> ShowCoreAsync(owner, text, caption, buttons, icon, defaultButton);
|
||||||
|
|
||||||
public static DialogResult Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
|
public static Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
|
||||||
=> ShowCoreAsync(owner, text, caption, buttons, icon, MessageBoxDefaultButton.Button1);
|
=> ShowCoreAsync(owner, text, caption, buttons, icon, MessageBoxDefaultButton.Button1);
|
||||||
public static DialogResult Show(Window owner, string text, string caption, MessageBoxButtons buttons)
|
public static Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons)
|
||||||
=> ShowCoreAsync(owner, text, caption, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
=> ShowCoreAsync(owner, text, caption, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
||||||
public static DialogResult Show(Window owner, string text, string caption)
|
public static Task<DialogResult> Show(Window owner, string text, string caption)
|
||||||
=> ShowCoreAsync(owner, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
=> ShowCoreAsync(owner, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
||||||
public static DialogResult Show(Window owner, string text)
|
public static Task<DialogResult> Show(Window owner, string text)
|
||||||
=> ShowCoreAsync(owner, text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
=> ShowCoreAsync(owner, text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
|
||||||
|
|
||||||
|
|
||||||
public static void VerboseLoggingWarning_ShowIfTrue()
|
public static async Task VerboseLoggingWarning_ShowIfTrue()
|
||||||
{
|
{
|
||||||
// when turning on debug (and especially Verbose) to share logs, some privacy settings may not be obscured
|
// when turning on debug (and especially Verbose) to share logs, some privacy settings may not be obscured
|
||||||
if (Serilog.Log.Logger.IsVerboseEnabled())
|
if (Serilog.Log.Logger.IsVerboseEnabled())
|
||||||
Show(@"
|
await Show(@"
|
||||||
Warning: verbose logging is enabled.
|
Warning: verbose logging is enabled.
|
||||||
|
|
||||||
This should be used for debugging only. It creates many
|
This should be used for debugging only. It creates many
|
||||||
@ -102,7 +102,7 @@ Libation.
|
|||||||
".Trim(), "Verbose logging enabled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
".Trim(), "Verbose logging enabled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DialogResult ShowConfirmationDialog(Window owner, IEnumerable<LibraryBook> libraryBooks, string format, string title, MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1)
|
public static async Task<DialogResult> ShowConfirmationDialog(Window owner, IEnumerable<LibraryBook> libraryBooks, string format, string title, MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1)
|
||||||
{
|
{
|
||||||
if (libraryBooks is null || !libraryBooks.Any())
|
if (libraryBooks is null || !libraryBooks.Any())
|
||||||
return DialogResult.Cancel;
|
return DialogResult.Cancel;
|
||||||
@ -117,7 +117,7 @@ Libation.
|
|||||||
= string.Format(format, $"{thisThese} {count} {bookBooks}")
|
= string.Format(format, $"{thisThese} {count} {bookBooks}")
|
||||||
+ $"\r\n\r\n{titlesAgg}";
|
+ $"\r\n\r\n{titlesAgg}";
|
||||||
|
|
||||||
return ShowCoreAsync(owner,
|
return await ShowCoreAsync(owner,
|
||||||
message,
|
message,
|
||||||
title,
|
title,
|
||||||
MessageBoxButtons.YesNo,
|
MessageBoxButtons.YesNo,
|
||||||
@ -132,7 +132,7 @@ Libation.
|
|||||||
/// <param name="text">The text to display in the message box.</param>
|
/// <param name="text">The text to display in the message box.</param>
|
||||||
/// <param name="caption">The text to display in the title bar of the message box.</param>
|
/// <param name="caption">The text to display in the title bar of the message box.</param>
|
||||||
/// <param name="exception">Exception to log.</param>
|
/// <param name="exception">Exception to log.</param>
|
||||||
public static void ShowAdminAlert(Window owner, string text, string caption, Exception exception)
|
public static async Task ShowAdminAlert(Window owner, string text, string caption, Exception exception)
|
||||||
{
|
{
|
||||||
// for development and debugging, show me what broke!
|
// for development and debugging, show me what broke!
|
||||||
if (System.Diagnostics.Debugger.IsAttached)
|
if (System.Diagnostics.Debugger.IsAttached)
|
||||||
@ -146,14 +146,14 @@ Libation.
|
|||||||
|
|
||||||
var form = new MessageBoxAlertAdminDialog(text, caption, exception);
|
var form = new MessageBoxAlertAdminDialog(text, caption, exception);
|
||||||
|
|
||||||
DisplayWindow(form, owner);
|
await DisplayWindow(form, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DialogResult ShowCoreAsync(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
|
private static async Task<DialogResult> ShowCoreAsync(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
|
||||||
{
|
{
|
||||||
var dialog = Dispatcher.UIThread.Invoke(() => CreateMessageBox(owner, message, caption, buttons, icon, defaultButton, saveAndRestorePosition));
|
var dialog = await Dispatcher.UIThread.InvokeAsync(() => CreateMessageBox(owner, message, caption, buttons, icon, defaultButton, saveAndRestorePosition));
|
||||||
|
|
||||||
return DisplayWindow(dialog, owner);
|
return await DisplayWindow(dialog, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MessageBoxWindow CreateMessageBox(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
|
private static MessageBoxWindow CreateMessageBox(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, bool saveAndRestorePosition = true)
|
||||||
@ -192,13 +192,13 @@ Libation.
|
|||||||
dialog.Width = dialog.MinWidth;
|
dialog.Width = dialog.MinWidth;
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
private static DialogResult DisplayWindow(Window toDisplay, Window owner)
|
private static async Task<DialogResult> DisplayWindow(Window toDisplay, Window owner)
|
||||||
{
|
{
|
||||||
if (owner is null)
|
if (owner is null)
|
||||||
{
|
{
|
||||||
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
{
|
{
|
||||||
return toDisplay.ShowDialogSynchronously<DialogResult>(desktop.MainWindow);
|
return await toDisplay.ShowDialog<DialogResult>(desktop.MainWindow);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -212,7 +212,7 @@ Libation.
|
|||||||
};
|
};
|
||||||
|
|
||||||
window.Show();
|
window.Show();
|
||||||
var result = toDisplay.ShowDialogSynchronously<DialogResult>(window);
|
var result = await toDisplay.ShowDialog<DialogResult>(window);
|
||||||
window.Close();
|
window.Close();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -220,7 +220,7 @@ Libation.
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return toDisplay.ShowDialogSynchronously<DialogResult>(owner);
|
return await toDisplay.ShowDialog<DialogResult>(owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ namespace LibationAvalonia
|
|||||||
{
|
{
|
||||||
private static string EXE_DIR = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
|
private static string EXE_DIR = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
|
||||||
|
|
||||||
static async Task Main()
|
static void Main()
|
||||||
{
|
{
|
||||||
//***********************************************//
|
//***********************************************//
|
||||||
// //
|
// //
|
||||||
@ -30,6 +30,14 @@ namespace LibationAvalonia
|
|||||||
var classicLifetimeTask = Task.Run(() => new ClassicDesktopStyleApplicationLifetime());
|
var classicLifetimeTask = Task.Run(() => new ClassicDesktopStyleApplicationLifetime());
|
||||||
var appBuilderTask = Task.Run(BuildAvaloniaApp);
|
var appBuilderTask = Task.Run(BuildAvaloniaApp);
|
||||||
|
|
||||||
|
if (App.IsWindows)
|
||||||
|
AppScaffolding.LibationScaffolding.SetReleaseIdentifier(AppScaffolding.ReleaseIdentifier.WindowsAvalonia);
|
||||||
|
else if (App.IsLinux)
|
||||||
|
AppScaffolding.LibationScaffolding.SetReleaseIdentifier(AppScaffolding.ReleaseIdentifier.LinuxAvalonia);
|
||||||
|
else if (App.IsMacOs)
|
||||||
|
AppScaffolding.LibationScaffolding.SetReleaseIdentifier(AppScaffolding.ReleaseIdentifier.MacOSAvalonia);
|
||||||
|
else return;
|
||||||
|
|
||||||
|
|
||||||
if (!App.SetupRequired)
|
if (!App.SetupRequired)
|
||||||
{
|
{
|
||||||
@ -39,9 +47,7 @@ namespace LibationAvalonia
|
|||||||
App.LibraryTask = Task.Run(() => DbContexts.GetLibrary_Flat_NoTracking(includeParents: true));
|
App.LibraryTask = Task.Run(() => DbContexts.GetLibrary_Flat_NoTracking(includeParents: true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(appBuilderTask.GetAwaiter().GetResult()).SetupWithLifetime(classicLifetimeTask.GetAwaiter().GetResult());
|
||||||
|
|
||||||
(await appBuilderTask).SetupWithLifetime(await classicLifetimeTask);
|
|
||||||
|
|
||||||
classicLifetimeTask.Result.Start(null);
|
classicLifetimeTask.Result.Start(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration>Release</Configuration>
|
<Configuration>Release</Configuration>
|
||||||
<Platform>Any CPU</Platform>
|
<Platform>Any CPU</Platform>
|
||||||
<PublishDir>..\bin-Avalonia\publish\linux-x64\</PublishDir>
|
<PublishDir>..\bin\Release\linux-chardonnay</PublishDir>
|
||||||
<PublishProtocol>FileSystem</PublishProtocol>
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration>Release</Configuration>
|
<Configuration>Release</Configuration>
|
||||||
<Platform>Any CPU</Platform>
|
<Platform>Any CPU</Platform>
|
||||||
<PublishDir>..\bin-Avalonia\publish\osx-x64\</PublishDir>
|
<PublishDir>..\bin\Release\macos-chardonnay</PublishDir>
|
||||||
<PublishProtocol>FileSystem</PublishProtocol>
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
|
||||||
|
|||||||
@ -6,8 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration>Release</Configuration>
|
<Configuration>Release</Configuration>
|
||||||
<Platform>Any CPU</Platform>
|
<Platform>Any CPU</Platform>
|
||||||
<!-- since Windows Winforms and Avalonia both compile to "Libation.exe", they can't both default to "bin\publish\" or else they'll overwrite each other -->
|
<PublishDir>..\bin\Release\win-chardonnay</PublishDir>
|
||||||
<PublishDir>..\bin\publish\win-avalonia-x64\</PublishDir>
|
|
||||||
<PublishProtocol>FileSystem</PublishProtocol>
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
|
|||||||
@ -152,7 +152,7 @@ namespace LibationAvalonia.ViewModels
|
|||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (Result == ProcessBookResult.None)
|
if (Result == ProcessBookResult.None)
|
||||||
Result = showRetry(LibraryBook);
|
Result = await showRetry(LibraryBook);
|
||||||
|
|
||||||
Status = Result switch
|
Status = Result switch
|
||||||
{
|
{
|
||||||
@ -313,7 +313,7 @@ namespace LibationAvalonia.ViewModels
|
|||||||
|
|
||||||
#region Failure Handler
|
#region Failure Handler
|
||||||
|
|
||||||
private ProcessBookResult showRetry(LibraryBook libraryBook)
|
private async Task<ProcessBookResult> showRetry(LibraryBook libraryBook)
|
||||||
{
|
{
|
||||||
Logger.Error("ERROR. All books have not been processed. Most recent book: processing failed");
|
Logger.Error("ERROR. All books have not been processed. Most recent book: processing failed");
|
||||||
|
|
||||||
@ -346,7 +346,7 @@ $@" Title: {libraryBook.Book.Title}
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if null then ask user
|
// if null then ask user
|
||||||
dialogResult ??= MessageBox.Show(string.Format(SkipDialogText + "\r\n\r\nSee Settings to avoid this box in the future.", details), "Skip importing this book?", SkipDialogButtons, MessageBoxIcon.Question, SkipDialogDefaultButton);
|
dialogResult ??= await MessageBox.Show(string.Format(SkipDialogText + "\r\n\r\nSee Settings to avoid this box in the future.", details), "Skip importing this book?", SkipDialogButtons, MessageBoxIcon.Question, SkipDialogDefaultButton);
|
||||||
|
|
||||||
if (dialogResult == DialogResult.Abort)
|
if (dialogResult == DialogResult.Abort)
|
||||||
return ProcessBookResult.FailedAbort;
|
return ProcessBookResult.FailedAbort;
|
||||||
|
|||||||
@ -244,7 +244,7 @@ namespace LibationAvalonia.ViewModels
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var libraryBooks = selectedBooks.Select(rge => rge.LibraryBook).ToList();
|
var libraryBooks = selectedBooks.Select(rge => rge.LibraryBook).ToList();
|
||||||
var result = MessageBox.ShowConfirmationDialog(
|
var result = await MessageBox.ShowConfirmationDialog(
|
||||||
null,
|
null,
|
||||||
libraryBooks,
|
libraryBooks,
|
||||||
$"Are you sure you want to remove {selectedBooks.Count} books from Libation's library?",
|
$"Are you sure you want to remove {selectedBooks.Count} books from Libation's library?",
|
||||||
@ -317,7 +317,7 @@ namespace LibationAvalonia.ViewModels
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.ShowAdminAlert(
|
await MessageBox.ShowAdminAlert(
|
||||||
null,
|
null,
|
||||||
"Error scanning library. You may still manually select books to remove from Libation's library.",
|
"Error scanning library. You may still manually select books to remove from Libation's library.",
|
||||||
"Error scanning library",
|
"Error scanning library",
|
||||||
|
|||||||
@ -41,11 +41,11 @@ namespace LibationAvalonia.Views
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageBox.Show("Library exported to:\r\n" + fileName, "Library Exported");
|
await MessageBox.Show("Library exported to:\r\n" + fileName, "Library Exported");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.ShowAdminAlert(this, "Error attempting to export your library.", "Error exporting", ex);
|
await MessageBox.ShowAdminAlert(this, "Error attempting to export your library.", "Error exporting", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ namespace LibationAvalonia.Views
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.Show($"Bad filter string:\r\n\r\n{ex.Message}", "Bad filter string", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
await MessageBox.Show($"Bad filter string:\r\n\r\n{ex.Message}", "Bad filter string", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
|
||||||
// re-apply last good filter
|
// re-apply last good filter
|
||||||
await performFilter(lastGoodFilter);
|
await performFilter(lastGoodFilter);
|
||||||
|
|||||||
@ -40,7 +40,7 @@ namespace LibationAvalonia.Views
|
|||||||
|
|
||||||
public async void convertAllM4bToMp3ToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
public async void convertAllM4bToMp3ToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
var result = MessageBox.Show(
|
var result = await MessageBox.Show(
|
||||||
"This converts all m4b titles in your library to mp3 files. Original files are not deleted."
|
"This converts all m4b titles in your library to mp3 files. Original files are not deleted."
|
||||||
+ "\r\nFor large libraries this will take a long time and will take up more disk space."
|
+ "\r\nFor large libraries this will take a long time and will take up more disk space."
|
||||||
+ "\r\n\r\nContinue?"
|
+ "\r\n\r\nContinue?"
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace LibationAvalonia.Views
|
|||||||
SetQueueCollapseState(collapseState);
|
SetQueueCollapseState(collapseState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProductsDisplay_LiberateClicked(object sender, LibraryBook libraryBook)
|
public async void ProductsDisplay_LiberateClicked(object sender, LibraryBook libraryBook)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -39,7 +39,7 @@ namespace LibationAvalonia.Views
|
|||||||
if (!App.GoToFile(filePath?.ShortPathName))
|
if (!App.GoToFile(filePath?.ShortPathName))
|
||||||
{
|
{
|
||||||
var suffix = string.IsNullOrWhiteSpace(filePath) ? "" : $":\r\n{filePath}";
|
var suffix = string.IsNullOrWhiteSpace(filePath) ? "" : $":\r\n{filePath}";
|
||||||
MessageBox.Show($"File not found" + suffix);
|
await MessageBox.Show($"File not found" + suffix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ namespace LibationAvalonia.Views
|
|||||||
|
|
||||||
public async void noAccountsYetAddAccountToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
public async void noAccountsYetAddAccountToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
MessageBox.Show("To load your Audible library, come back here to the Import menu after adding your account");
|
await MessageBox.Show("To load your Audible library, come back here to the Import menu after adding your account");
|
||||||
await new Dialogs.AccountsDialog().ShowDialog(this);
|
await new Dialogs.AccountsDialog().ShowDialog(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,11 +66,11 @@ namespace LibationAvalonia.Views
|
|||||||
|
|
||||||
// this is here instead of ScanEnd so that the following is only possible when it's user-initiated, not automatic loop
|
// this is here instead of ScanEnd so that the following is only possible when it's user-initiated, not automatic loop
|
||||||
if (Configuration.Instance.ShowImportedStats && newAdded > 0)
|
if (Configuration.Instance.ShowImportedStats && newAdded > 0)
|
||||||
MessageBox.Show($"Total processed: {totalProcessed}\r\nNew: {newAdded}");
|
await MessageBox.Show($"Total processed: {totalProcessed}\r\nNew: {newAdded}");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.ShowAdminAlert(
|
await MessageBox.ShowAdminAlert(
|
||||||
this,
|
this,
|
||||||
"Error importing library. Please try again. If this still happens after 2 or 3 tries, stop and contact administrator",
|
"Error importing library. Please try again. If this still happens after 2 or 3 tries, stop and contact administrator",
|
||||||
"Error importing library",
|
"Error importing library",
|
||||||
|
|||||||
@ -8,11 +8,13 @@ namespace LibationAvalonia.Views
|
|||||||
{
|
{
|
||||||
private void Configure_Settings() { }
|
private void Configure_Settings() { }
|
||||||
|
|
||||||
public async void accountsToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) => await new Dialogs.AccountsDialog().ShowDialog(this);
|
public async void accountsToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||||
|
=> await new Dialogs.AccountsDialog().ShowDialog(this);
|
||||||
|
|
||||||
public async void basicSettingsToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) => await new Dialogs.SettingsDialog().ShowDialog(this);
|
public async void basicSettingsToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||||
|
=> await new Dialogs.SettingsDialog().ShowDialog(this);
|
||||||
|
|
||||||
public void aboutToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
public async void aboutToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||||
=> MessageBox.Show($"Running Libation version {AppScaffolding.LibationScaffolding.BuildVersion}", $"Libation v{AppScaffolding.LibationScaffolding.BuildVersion}");
|
=> await MessageBox.Show($"Running Libation version {AppScaffolding.LibationScaffolding.BuildVersion}", $"Libation v{AppScaffolding.LibationScaffolding.BuildVersion}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace LibationAvalonia.Views
|
|||||||
|
|
||||||
var visibleLibraryBooks = _viewModel.ProductsDisplay.GetVisibleBookEntries();
|
var visibleLibraryBooks = _viewModel.ProductsDisplay.GetVisibleBookEntries();
|
||||||
|
|
||||||
var confirmationResult = MessageBox.ShowConfirmationDialog(
|
var confirmationResult = await MessageBox.ShowConfirmationDialog(
|
||||||
this,
|
this,
|
||||||
visibleLibraryBooks,
|
visibleLibraryBooks,
|
||||||
"Are you sure you want to replace tags in {0}?",
|
"Are you sure you want to replace tags in {0}?",
|
||||||
@ -70,7 +70,7 @@ namespace LibationAvalonia.Views
|
|||||||
|
|
||||||
var visibleLibraryBooks = _viewModel.ProductsDisplay.GetVisibleBookEntries();
|
var visibleLibraryBooks = _viewModel.ProductsDisplay.GetVisibleBookEntries();
|
||||||
|
|
||||||
var confirmationResult = MessageBox.ShowConfirmationDialog(
|
var confirmationResult = await MessageBox.ShowConfirmationDialog(
|
||||||
this,
|
this,
|
||||||
visibleLibraryBooks,
|
visibleLibraryBooks,
|
||||||
"Are you sure you want to replace downloaded status in {0}?",
|
"Are you sure you want to replace downloaded status in {0}?",
|
||||||
@ -88,7 +88,7 @@ namespace LibationAvalonia.Views
|
|||||||
{
|
{
|
||||||
var visibleLibraryBooks = _viewModel.ProductsDisplay.GetVisibleBookEntries();
|
var visibleLibraryBooks = _viewModel.ProductsDisplay.GetVisibleBookEntries();
|
||||||
|
|
||||||
var confirmationResult = MessageBox.ShowConfirmationDialog(
|
var confirmationResult = await MessageBox.ShowConfirmationDialog(
|
||||||
this,
|
this,
|
||||||
visibleLibraryBooks,
|
visibleLibraryBooks,
|
||||||
"Are you sure you want to remove {0} from Libation's library?",
|
"Are you sure you want to remove {0} from Libation's library?",
|
||||||
|
|||||||
@ -9,6 +9,7 @@ using LibationFileManager;
|
|||||||
using DataLayer;
|
using DataLayer;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using AppScaffolding;
|
||||||
|
|
||||||
namespace LibationAvalonia.Views
|
namespace LibationAvalonia.Views
|
||||||
{
|
{
|
||||||
@ -53,7 +54,7 @@ namespace LibationAvalonia.Views
|
|||||||
this.LibraryLoaded += MainWindow_LibraryLoaded;
|
this.LibraryLoaded += MainWindow_LibraryLoaded;
|
||||||
|
|
||||||
LibraryCommands.LibrarySizeChanged += async (_, _) => await _viewModel.ProductsDisplay.DisplayBooks(DbContexts.GetLibrary_Flat_NoTracking(includeParents: true));
|
LibraryCommands.LibrarySizeChanged += async (_, _) => await _viewModel.ProductsDisplay.DisplayBooks(DbContexts.GetLibrary_Flat_NoTracking(includeParents: true));
|
||||||
Closing += (_,_) => this.SaveSizeAndLocation(Configuration.Instance);
|
Closing += (_, _) => this.SaveSizeAndLocation(Configuration.Instance);
|
||||||
}
|
}
|
||||||
Opened += MainWindow_Opened;
|
Opened += MainWindow_Opened;
|
||||||
Closing += MainWindow_Closing;
|
Closing += MainWindow_Closing;
|
||||||
@ -67,50 +68,72 @@ namespace LibationAvalonia.Views
|
|||||||
private async void MainWindow_Opened(object sender, EventArgs e)
|
private async void MainWindow_Opened(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (App.IsWindows)
|
//This is temporaty until we have a solution for linux/mac so that
|
||||||
|
//Libation doesn't download a zip every time it runs.
|
||||||
|
if (!App.IsWindows)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
(string zipFile, UpgradeProperties upgradeProperties) = await Task.Run(() => downloadUpdate());
|
||||||
{
|
|
||||||
await Task.Run(checkForAndDownloadUpdate);
|
if (string.IsNullOrEmpty(zipFile) || !System.IO.File.Exists(zipFile))
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
Serilog.Log.Logger.Error(ex, "An error occured while checking for app updates.");
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var result = await MessageBox.Show($"{upgradeProperties.HtmlUrl}\r\n\r\nWould you like to upgrade now?", "New version available", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
|
||||||
|
|
||||||
|
if (result != DialogResult.Yes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (App.IsWindows)
|
||||||
|
{
|
||||||
|
runWindowsUpgrader(zipFile);
|
||||||
}
|
}
|
||||||
|
else if (App.IsLinux)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (App.IsMacOs)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Error(ex, "An error occured while checking for app updates.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task checkForAndDownloadUpdate()
|
private async Task<(string zipFile, UpgradeProperties release)> downloadUpdate()
|
||||||
{
|
{
|
||||||
AppScaffolding.UpgradeProperties upgradeProperties;
|
UpgradeProperties upgradeProperties;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
upgradeProperties = AppScaffolding.LibationScaffolding.GetLatestRelease(AppScaffolding.LibationScaffolding.ReleaseIdentifier.WindowsAvalonia);
|
upgradeProperties = LibationScaffolding.GetLatestRelease();
|
||||||
|
|
||||||
if (upgradeProperties is null)
|
if (upgradeProperties is null)
|
||||||
return;
|
return (null,null);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Serilog.Log.Logger.Error(ex, "Failed to check for update");
|
Serilog.Log.Logger.Error(ex, "Failed to check for update");
|
||||||
return;
|
return (null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upgradeProperties.ZipUrl is null)
|
if (upgradeProperties.ZipUrl is null)
|
||||||
{
|
{
|
||||||
Serilog.Log.Logger.Information("Download link for new version not found");
|
Serilog.Log.Logger.Information("Download link for new version not found");
|
||||||
return;
|
return (null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Silently download the update in the background, save it to a temp file.
|
//Silently download the update in the background, save it to a temp file.
|
||||||
|
|
||||||
var zipPath = System.IO.Path.GetTempFileName();
|
var zipFile = System.IO.Path.GetTempFileName();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
System.Net.Http.HttpClient cli = new();
|
System.Net.Http.HttpClient cli = new();
|
||||||
using (var fs = System.IO.File.OpenWrite(zipPath))
|
using (var fs = System.IO.File.OpenWrite(zipFile))
|
||||||
{
|
{
|
||||||
using (var dlStream = await cli.GetStreamAsync(new Uri(upgradeProperties.ZipUrl)))
|
using (var dlStream = await cli.GetStreamAsync(new Uri(upgradeProperties.ZipUrl)))
|
||||||
await dlStream.CopyToAsync(fs);
|
await dlStream.CopyToAsync(fs);
|
||||||
@ -119,18 +142,18 @@ namespace LibationAvalonia.Views
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Serilog.Log.Logger.Error(ex, "Failed to download the update: {pdate}", upgradeProperties.ZipUrl);
|
Serilog.Log.Logger.Error(ex, "Failed to download the update: {pdate}", upgradeProperties.ZipUrl);
|
||||||
return;
|
return (null, null);
|
||||||
}
|
}
|
||||||
|
return (zipFile, upgradeProperties);
|
||||||
|
}
|
||||||
|
|
||||||
var result = MessageBox.Show($"{upgradeProperties.HtmlUrl}\r\n\r\nWould you like to upgrade now?", "New version available", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
|
private void runWindowsUpgrader(string zipFile)
|
||||||
|
{
|
||||||
if (result != DialogResult.Yes)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var thisExe = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
|
var thisExe = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
|
||||||
var thisDir = System.IO.Path.GetDirectoryName(thisExe);
|
var thisDir = System.IO.Path.GetDirectoryName(thisExe);
|
||||||
|
|
||||||
var args = $"--input {zipPath} --output {thisDir} --executable {thisExe}";
|
var args = $"--input {zipFile} --output {thisDir} --executable {thisExe}";
|
||||||
|
|
||||||
var zipExtractor = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "ZipExtractor.exe");
|
var zipExtractor = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "ZipExtractor.exe");
|
||||||
|
|
||||||
|
|||||||
@ -1,27 +1,26 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<PublishReadyToRun>true</PublishReadyToRun>
|
<PublishReadyToRun>true</PublishReadyToRun>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
<IsPublishable>True</IsPublishable>
|
||||||
<IsPublishable>True</IsPublishable>
|
</PropertyGroup>
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!--
|
<!--
|
||||||
HACK FOR COMPILER BUG 2021-09-14. Hopefully will be fixed in future versions
|
HACK FOR COMPILER BUG 2021-09-14. Hopefully will be fixed in future versions
|
||||||
- Not using SatelliteResourceLanguages will load all language packs: works
|
- Not using SatelliteResourceLanguages will load all language packs: works
|
||||||
- Specifying 'en' semicolon 1 more should load 1 language pack: works
|
- Specifying 'en' semicolon 1 more should load 1 language pack: works
|
||||||
- Specifying only 'en' should load no language packs: broken, still loads all
|
- Specifying only 'en' should load no language packs: broken, still loads all
|
||||||
-->
|
-->
|
||||||
<SatelliteResourceLanguages>en;es</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>en;es</SatelliteResourceLanguages>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
When LibationWinForms and LibationCli output to the same dir, LibationCli must build before LibationWinForms
|
When LibationWinForms and LibationCli output to the same dir, LibationCli must build before LibationWinForms
|
||||||
|
|
||||||
VS > rt-clk solution > Properties
|
VS > rt-clk solution > Properties
|
||||||
@ -31,24 +30,31 @@
|
|||||||
|
|
||||||
edit debug and release output paths
|
edit debug and release output paths
|
||||||
-->
|
-->
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<OutputPath>..\bin\Debug</OutputPath>
|
<OutputPath>..\bin\Debug</OutputPath>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<OutputPath>..\bin\Release</OutputPath>
|
<OutputPath>..\bin\Release</OutputPath>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<Target Name="SpicNSpan" AfterTargets="Clean">
|
||||||
<ProjectReference Include="..\ApplicationServices\ApplicationServices.csproj" />
|
<!-- Remove obj folder -->
|
||||||
<ProjectReference Include="..\AppScaffolding\AppScaffolding.csproj" />
|
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
|
||||||
<ProjectReference Include="..\FileLiberator\FileLiberator.csproj" />
|
<!-- Remove bin folder -->
|
||||||
</ItemGroup>
|
<RemoveDir Directories="$(BaseOutputPath)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ApplicationServices\ApplicationServices.csproj" />
|
||||||
|
<ProjectReference Include="..\AppScaffolding\AppScaffolding.csproj" />
|
||||||
|
<ProjectReference Include="..\FileLiberator\FileLiberator.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration>Release</Configuration>
|
<Configuration>Release</Configuration>
|
||||||
<Platform>Any CPU</Platform>
|
<Platform>Any CPU</Platform>
|
||||||
<PublishDir>..\bin-Avalonia\publish\linux-x64\</PublishDir>
|
<PublishDir>..\bin\Release\linux-chardonnay</PublishDir>
|
||||||
<PublishProtocol>FileSystem</PublishProtocol>
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration>Release</Configuration>
|
<Configuration>Release</Configuration>
|
||||||
<Platform>Any CPU</Platform>
|
<Platform>Any CPU</Platform>
|
||||||
<PublishDir>..\bin-Avalonia\publish\osx-x64\</PublishDir>
|
<PublishDir>..\bin\Release\macos-chardonnay</PublishDir>
|
||||||
<PublishProtocol>FileSystem</PublishProtocol>
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration>Release</Configuration>
|
<Configuration>Release</Configuration>
|
||||||
<Platform>Any CPU</Platform>
|
<Platform>Any CPU</Platform>
|
||||||
<PublishDir>..\bin\publish\</PublishDir>
|
<PublishDir>..\bin\Release\win-chardonnay</PublishDir>
|
||||||
<PublishProtocol>FileSystem</PublishProtocol>
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using AudibleApi;
|
using AudibleApi;
|
||||||
using AudibleUtilities;
|
using AudibleUtilities;
|
||||||
using LibationWinForms.Dialogs.Login;
|
using LibationWinForms.Dialogs.Login;
|
||||||
@ -14,42 +15,43 @@ namespace LibationWinForms.Login
|
|||||||
_account = Dinah.Core.ArgumentValidator.EnsureNotNull(account, nameof(account));
|
_account = Dinah.Core.ArgumentValidator.EnsureNotNull(account, nameof(account));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Get2faCode()
|
public Task<string> Get2faCodeAsync()
|
||||||
{
|
{
|
||||||
using var dialog = new _2faCodeDialog();
|
using var dialog = new _2faCodeDialog();
|
||||||
if (ShowDialog(dialog))
|
if (ShowDialog(dialog))
|
||||||
return dialog.Code;
|
return Task.FromResult(dialog.Code);
|
||||||
return null;
|
return Task.FromResult<string>(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetCaptchaAnswer(byte[] captchaImage)
|
public Task<string> GetCaptchaAnswerAsync(byte[] captchaImage)
|
||||||
{
|
{
|
||||||
using var dialog = new CaptchaDialog(captchaImage);
|
using var dialog = new CaptchaDialog(captchaImage);
|
||||||
if (ShowDialog(dialog))
|
if (ShowDialog(dialog))
|
||||||
return dialog.Answer;
|
return Task.FromResult(dialog.Answer);
|
||||||
return null;
|
return Task.FromResult<string>(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public (string name, string value) GetMfaChoice(MfaConfig mfaConfig)
|
public Task<(string name, string value)> GetMfaChoiceAsync(MfaConfig mfaConfig)
|
||||||
{
|
{
|
||||||
using var dialog = new MfaDialog(mfaConfig);
|
using var dialog = new MfaDialog(mfaConfig);
|
||||||
if (ShowDialog(dialog))
|
if (ShowDialog(dialog))
|
||||||
return (dialog.SelectedName, dialog.SelectedValue);
|
return Task.FromResult((dialog.SelectedName, dialog.SelectedValue));
|
||||||
return (null, null);
|
return Task.FromResult<(string, string)>((null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public (string email, string password) GetLogin()
|
public Task<(string email, string password)> GetLoginAsync()
|
||||||
{
|
{
|
||||||
using var dialog = new LoginCallbackDialog(_account);
|
using var dialog = new LoginCallbackDialog(_account);
|
||||||
if (ShowDialog(dialog))
|
if (ShowDialog(dialog))
|
||||||
return (dialog.Email, dialog.Password);
|
return Task.FromResult((dialog.Email, dialog.Password));
|
||||||
return (null, null);
|
return Task.FromResult<(string, string)>((null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowApprovalNeeded()
|
public Task ShowApprovalNeededAsync()
|
||||||
{
|
{
|
||||||
using var dialog = new ApprovalNeededDialog();
|
using var dialog = new ApprovalNeededDialog();
|
||||||
ShowDialog(dialog);
|
ShowDialog(dialog);
|
||||||
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ namespace LibationWinForms.Login
|
|||||||
LoginCallback = new WinformLoginCallback(_account);
|
LoginCallback = new WinformLoginCallback(_account);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChoiceOut Start(ChoiceIn choiceIn)
|
public Task<ChoiceOut> StartAsync(ChoiceIn choiceIn)
|
||||||
{
|
{
|
||||||
using var dialog = new LoginChoiceEagerDialog(_account);
|
using var dialog = new LoginChoiceEagerDialog(_account);
|
||||||
|
|
||||||
@ -31,13 +31,14 @@ namespace LibationWinForms.Login
|
|||||||
switch (dialog.LoginMethod)
|
switch (dialog.LoginMethod)
|
||||||
{
|
{
|
||||||
case LoginMethod.Api:
|
case LoginMethod.Api:
|
||||||
return ChoiceOut.WithApi(dialog.Email, dialog.Password);
|
return Task.FromResult(ChoiceOut.WithApi(dialog.Email, dialog.Password));
|
||||||
case LoginMethod.External:
|
case LoginMethod.External:
|
||||||
{
|
{
|
||||||
using var externalDialog = new LoginExternalDialog(_account, choiceIn.LoginUrl);
|
using var externalDialog = new LoginExternalDialog(_account, choiceIn.LoginUrl);
|
||||||
return ShowDialog(externalDialog)
|
return Task.FromResult(
|
||||||
? ChoiceOut.External(externalDialog.ResponseUrl)
|
ShowDialog(externalDialog)
|
||||||
: null;
|
? ChoiceOut.External(externalDialog.ResponseUrl)
|
||||||
|
: null);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw new Exception($"Unknown {nameof(LoginMethod)} value");
|
throw new Exception($"Unknown {nameof(LoginMethod)} value");
|
||||||
|
|||||||
@ -1,91 +1,99 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net6.0-windows</TargetFramework>
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<ApplicationIcon>libation.ico</ApplicationIcon>
|
<ApplicationIcon>libation.ico</ApplicationIcon>
|
||||||
<AssemblyName>Libation</AssemblyName>
|
<AssemblyName>Libation</AssemblyName>
|
||||||
|
|
||||||
<PublishReadyToRun>true</PublishReadyToRun>
|
<PublishReadyToRun>true</PublishReadyToRun>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||||
<StartupObject />
|
<StartupObject />
|
||||||
|
<IsPublishable>true</IsPublishable>
|
||||||
|
<!-- Version is now in AppScaffolding.csproj -->
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Version is now in AppScaffolding.csproj -->
|
<PropertyGroup>
|
||||||
</PropertyGroup>
|
<!--
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<!--
|
|
||||||
HACK FOR COMPILER BUG 2021-09-14. Hopefully will be fixed in future versions
|
HACK FOR COMPILER BUG 2021-09-14. Hopefully will be fixed in future versions
|
||||||
- Not using SatelliteResourceLanguages will load all language packs: works
|
- Not using SatelliteResourceLanguages will load all language packs: works
|
||||||
- Specifying 'en' semicolon 1 more should load 1 language pack: works
|
- Specifying 'en' semicolon 1 more should load 1 language pack: works
|
||||||
- Specifying only 'en' should load no language packs: broken, still loads all
|
- Specifying only 'en' should load no language packs: broken, still loads all
|
||||||
-->
|
-->
|
||||||
<SatelliteResourceLanguages>en;es</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>en;es</SatelliteResourceLanguages>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<OutputPath>..\bin\Debug</OutputPath>
|
<OutputPath>..\bin\Debug</OutputPath>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<OutputPath>..\bin\Release</OutputPath>
|
<OutputPath>..\bin\Release</OutputPath>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove=".gitignore" />
|
<None Remove=".gitignore" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Autoupdater.NET.Official" Version="1.7.4" />
|
<PackageReference Include="Autoupdater.NET.Official" Version="1.7.4" />
|
||||||
<PackageReference Include="Dinah.Core.WindowsDesktop" Version="4.2.3.1" />
|
<PackageReference Include="Dinah.Core.WindowsDesktop" Version="4.2.3.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ApplicationServices\ApplicationServices.csproj" />
|
<ProjectReference Include="..\ApplicationServices\ApplicationServices.csproj" />
|
||||||
<ProjectReference Include="..\AppScaffolding\AppScaffolding.csproj" />
|
<ProjectReference Include="..\AppScaffolding\AppScaffolding.csproj" />
|
||||||
<ProjectReference Include="..\FileLiberator\FileLiberator.csproj" />
|
<ProjectReference Include="..\FileLiberator\FileLiberator.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="Form1.*.cs">
|
|
||||||
<DependentUpon>Form1.cs</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Update="Dialogs\SettingsDialog.*.cs">
|
|
||||||
<DependentUpon>SettingsDialog.cs</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Update="Form1.*.cs">
|
|
||||||
<DependentUpon>Form1.cs</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup> <ItemGroup>
|
|
||||||
<Compile Update="Form1.*.cs">
|
<Compile Update="Form1.*.cs">
|
||||||
<DependentUpon>Form1.cs</DependentUpon>
|
<DependentUpon>Form1.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="Properties\Resources.Designer.cs">
|
<Compile Update="Dialogs\SettingsDialog.*.cs">
|
||||||
<DesignTime>True</DesignTime>
|
<DependentUpon>SettingsDialog.cs</DependentUpon>
|
||||||
<AutoGen>True</AutoGen>
|
</Compile>
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
</ItemGroup>
|
||||||
</Compile>
|
<ItemGroup>
|
||||||
</ItemGroup>
|
<Compile Update="Form1.*.cs">
|
||||||
|
<DependentUpon>Form1.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Form1.*.cs">
|
||||||
|
<DependentUpon>Form1.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Update="Properties\Resources.resx">
|
<Compile Update="Properties\Resources.Designer.cs">
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
<DesignTime>True</DesignTime>
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
<AutoGen>True</AutoGen>
|
||||||
</EmbeddedResource>
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
</ItemGroup>
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Update="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="SpicNSpan" AfterTargets="Clean">
|
||||||
|
<!-- Remove obj folder -->
|
||||||
|
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
|
||||||
|
<!-- Remove bin folder -->
|
||||||
|
<RemoveDir Directories="$(BaseOutputPath)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@ -30,6 +30,8 @@ namespace LibationWinForms
|
|||||||
|
|
||||||
ApplicationConfiguration.Initialize();
|
ApplicationConfiguration.Initialize();
|
||||||
|
|
||||||
|
AppScaffolding.LibationScaffolding.SetReleaseIdentifier(AppScaffolding.ReleaseIdentifier.WindowsClassic);
|
||||||
|
|
||||||
//***********************************************//
|
//***********************************************//
|
||||||
// //
|
// //
|
||||||
// do not use Configuration before this line //
|
// do not use Configuration before this line //
|
||||||
@ -170,7 +172,7 @@ namespace LibationWinForms
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
upgradeProperties = AppScaffolding.LibationScaffolding.GetLatestRelease(AppScaffolding.LibationScaffolding.ReleaseIdentifier.WindowsClassic);
|
upgradeProperties = AppScaffolding.LibationScaffolding.GetLatestRelease();
|
||||||
if (upgradeProperties is null)
|
if (upgradeProperties is null)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user