Linux and mac upgrade notification

This commit is contained in:
Michael Bucari-Tovo 2023-01-03 14:55:58 -07:00
parent 9ec877999e
commit b89b4e0af4
4 changed files with 218 additions and 112 deletions

View File

@ -0,0 +1,54 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="350" d:DesignHeight="200"
x:Class="LibationAvalonia.Dialogs.UpgradeNotification"
xmlns:controls="clr-namespace:LibationAvalonia.Controls"
MinWidth="350" MinHeight="200"
MaxWidth="350" MaxHeight="200"
WindowStartupLocation="CenterOwner"
Title="Upgrade Available"
Icon="/Assets/libation.ico">
<Grid Margin="6" RowDefinitions="Auto,Auto,Auto,*,Auto">
<TextBlock Grid.Row="0" FontSize="16" Text="{Binding VersionText}" />
<controls:LinkLabel
Grid.Row="1"
Margin="0,10,0,0"
Text="{Binding DownloadLinkText}"
Tapped="Download_Tapped" />
<controls:LinkLabel
Grid.Row="2"
Margin="0,10,0,0"
Text="Go to the Libation website"
Tapped="Website_Tapped" />
<controls:LinkLabel
Grid.Row="3"
Margin="0,10,0,0"
Text="View the source code on GitHub"
Tapped="Github_Tapped" />
<Grid Grid.Row="4" ColumnDefinitions="*,Auto">
<Button
Grid.Column="0"
HorizontalAlignment="Left"
Content="Don't remind me&#x0a;about this release"
Click="DontRemind_Click" />
<Button
Grid.Column="1"
TabIndex="0"
Padding="20,0,20,0"
VerticalAlignment="Stretch"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"
Content="OK"
Click="OK_Click" />
</Grid>
</Grid>
</Window>

View File

@ -0,0 +1,41 @@
using Avalonia.Controls;
using Dinah.Core;
using System;
namespace LibationAvalonia.Dialogs
{
public partial class UpgradeNotification : Window
{
public string VersionText { get; }
public string DownloadLinkText { get; }
private string PackageUrl { get; }
public UpgradeNotification()
{
if (Design.IsDesignMode)
{
VersionText = "Libation version 8.7.0 is now available.";
DownloadLinkText = "Download Libation.8.7.0-macos-chardonnay.tar.gz";
DataContext = this;
}
InitializeComponent();
}
public void OK_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) => Close(DialogResult.OK);
public void DontRemind_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) => Close(DialogResult.Ignore);
public void Download_Tapped(object sender, Avalonia.Input.TappedEventArgs e)
=> Go.To.Url(PackageUrl);
public void Website_Tapped(object sender, Avalonia.Input.TappedEventArgs e)
=> Go.To.Url("ht" + "tps://getlibation.com");
public void Github_Tapped(object sender, Avalonia.Input.TappedEventArgs e)
=> Go.To.Url("ht" + "tps://github.com/rmcrackan/Libation");
public UpgradeNotification(Version version, string packageUrl, string zipFileName) : this()
{
VersionText = $"Libation version {version.ToString(3)} is now available.";
PackageUrl = packageUrl;
DownloadLinkText = $"Download {zipFileName}";
DataContext = this;
}
}
}

View File

@ -0,0 +1,120 @@
using AppScaffolding;
using LibationAvalonia.Dialogs;
using LibationFileManager;
using System;
using System.Threading.Tasks;
namespace LibationAvalonia.Views
{
public partial class MainWindow
{
private void Configure_Update()
{
Opened += async (_, _) => await checkForUpdates();
}
private async Task checkForUpdates()
{
async Task<string> downloadUpdate(UpgradeProperties upgradeProperties)
{
if (upgradeProperties.ZipUrl is null)
{
Serilog.Log.Logger.Information("Download link for new version not found");
return null;
}
//Silently download the update in the background, save it to a temp file.
var zipFile = System.IO.Path.GetTempFileName();
try
{
System.Net.Http.HttpClient cli = new();
using var fs = System.IO.File.OpenWrite(zipFile);
using var dlStream = await cli.GetStreamAsync(new Uri(upgradeProperties.ZipUrl));
await dlStream.CopyToAsync(fs);
}
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, "Failed to download the update: {pdate}", upgradeProperties.ZipUrl);
return null;
}
return zipFile;
}
void runWindowsUpgrader(string zipFile)
{
var thisExe = Environment.ProcessPath;
var thisDir = System.IO.Path.GetDirectoryName(thisExe);
var zipExtractor = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "ZipExtractor.exe");
System.IO.File.Copy("ZipExtractor.exe", zipExtractor, overwrite: true);
var psi = new System.Diagnostics.ProcessStartInfo()
{
FileName = zipExtractor,
UseShellExecute = true,
Verb = "runas",
WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal,
CreateNoWindow = true,
ArgumentList =
{
"--input",
zipFile,
"--output",
thisDir,
"--executable",
thisExe
}
};
System.Diagnostics.Process.Start(psi);
Environment.Exit(0);
}
try
{
var upgradeProperties = await Task.Run(LibationScaffolding.GetLatestRelease);
if (upgradeProperties is null) return;
if (Configuration.IsWindows)
{
string zipFile = await downloadUpdate(upgradeProperties);
if (string.IsNullOrEmpty(zipFile) || !System.IO.File.Exists(zipFile))
return;
var result = await MessageBox.Show(this, $"{upgradeProperties.HtmlUrl}\r\n\r\nWould you like to upgrade now?", "New version available", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
if (result == DialogResult.Yes)
runWindowsUpgrader(zipFile);
}
else
{
//We're not going to have a solution for in-place upgrade on
//linux/mac, so just notify that an update is available.
const string ignoreUpdate = "IgnoreUpdate";
var config = Configuration.Instance;
if (config.GetObject(ignoreUpdate)?.ToString() == upgradeProperties.LatestRelease.ToString())
return;
var notificationResult =
await new UpgradeNotification(
upgradeProperties.LatestRelease,
upgradeProperties.ZipUrl,
upgradeProperties.ZipName)
.ShowDialog<DialogResult>(this);
if (notificationResult == DialogResult.Ignore)
config.SetObject(ignoreUpdate, upgradeProperties.LatestRelease.ToString());
}
}
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, "An error occured while checking for app updates.");
}
}
}
}

View File

@ -45,6 +45,9 @@ namespace LibationAvalonia.Views
Configure_Export();
Configure_Settings();
Configure_ProcessQueue();
#if DEBUG
Configure_Update();
#endif
Configure_Filter();
// misc which belongs in winforms app but doesn't have a UI element
Configure_NonUI();
@ -58,7 +61,6 @@ namespace LibationAvalonia.Views
LibraryCommands.LibrarySizeChanged += async (_, _) => await _viewModel.ProductsDisplay.DisplayBooksAsync(DbContexts.GetLibrary_Flat_NoTracking(includeParents: true));
Closing += (_, _) => this.SaveSizeAndLocation(Configuration.Instance);
}
Opened += MainWindow_Opened;
Closing += MainWindow_Closing;
}
@ -67,117 +69,6 @@ namespace LibationAvalonia.Views
productsDisplay?.CloseImageDisplay();
}
private async void MainWindow_Opened(object sender, EventArgs e)
{
#if !DEBUG
//This is temporaty until we have a solution for linux/mac so that
//Libation doesn't download a zip every time it runs.
if (!Configuration.IsWindows)
return;
try
{
(string zipFile, UpgradeProperties upgradeProperties) = await Task.Run(downloadUpdate);
if (string.IsNullOrEmpty(zipFile) || !System.IO.File.Exists(zipFile))
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 (Configuration.IsWindows)
{
runWindowsUpgrader(zipFile);
}
else if (Configuration.IsLinux)
{
}
else if (Configuration.IsMacOs)
{
}
}
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, "An error occured while checking for app updates.");
return;
}
#endif
}
private async Task<(string zipFile, UpgradeProperties release)> downloadUpdate()
{
UpgradeProperties upgradeProperties;
try
{
upgradeProperties = LibationScaffolding.GetLatestRelease();
if (upgradeProperties is null)
return (null,null);
}
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, "Failed to check for update");
return (null, null);
}
if (upgradeProperties.ZipUrl is null)
{
Serilog.Log.Logger.Information("Download link for new version not found");
return (null, null);
}
//Silently download the update in the background, save it to a temp file.
var zipFile = System.IO.Path.GetTempFileName();
try
{
System.Net.Http.HttpClient cli = new();
using var fs = System.IO.File.OpenWrite(zipFile);
using var dlStream = await cli.GetStreamAsync(new Uri(upgradeProperties.ZipUrl));
await dlStream.CopyToAsync(fs);
}
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, "Failed to download the update: {pdate}", upgradeProperties.ZipUrl);
return (null, null);
}
return (zipFile, upgradeProperties);
}
private void runWindowsUpgrader(string zipFile)
{
var thisExe = Environment.ProcessPath;
var thisDir = System.IO.Path.GetDirectoryName(thisExe);
var zipExtractor = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "ZipExtractor.exe");
System.IO.File.Copy("ZipExtractor.exe", zipExtractor, overwrite: true);
var psi = new System.Diagnostics.ProcessStartInfo()
{
FileName = zipExtractor,
UseShellExecute = true,
Verb = "runas",
WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal,
CreateNoWindow = true,
ArgumentList =
{
"--input",
zipFile,
"--output",
thisDir,
"--executable",
thisExe
}
};
System.Diagnostics.Process.Start(psi);
Environment.Exit(0);
}
private async void MainWindow_LibraryLoaded(object sender, List<LibraryBook> dbBooks)
{
if (QuickFilters.UseDefault)