mirror of
https://github.com/RedWizardsLab/EchoHub.git
synced 2026-09-04 00:26:07 +02:00
190 lines
5.9 KiB
C#
190 lines
5.9 KiB
C#
using AlwaysUpToDate;
|
|
|
|
using EchoHub.Client.UI.Dialogs;
|
|
|
|
using Serilog;
|
|
|
|
using Terminal.Gui.App;
|
|
using Terminal.Gui.Views;
|
|
|
|
namespace EchoHub.Client.Services;
|
|
|
|
public sealed class UpdateChecker : IDisposable
|
|
{
|
|
private const string ManifestUrl = "https://echohub.voidcube.cloud/api/app/version";
|
|
|
|
private readonly Updater _updater;
|
|
private readonly IApplication _app;
|
|
private UpdateProgressDialog? _progressDialog;
|
|
private bool _manualCheck;
|
|
|
|
|
|
public static string CurrentVersion => typeof(UpdateChecker).Assembly.GetName().Version?.ToString(3) ?? "0.0.0";
|
|
|
|
public UpdateChecker(IApplication app)
|
|
{
|
|
_app = app;
|
|
_updater = new Updater(TimeSpan.FromHours(1), ManifestUrl, false);
|
|
|
|
_updater.UpdateAvailable += OnUpdateAvailable;
|
|
_updater.ProgressChanged += OnProgressChanged;
|
|
_updater.UpdateStarted += OnUpdateStarted;
|
|
_updater.NoUpdateAvailable += OnNoUpdateAvailable;
|
|
_updater.OnException += OnException;
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
#if RELEASE
|
|
_updater.Start();
|
|
#endif
|
|
}
|
|
|
|
|
|
public async Task CheckNowAsync()
|
|
{
|
|
_manualCheck = true;
|
|
try
|
|
{
|
|
await _updater.CheckForUpdateAsync();
|
|
}
|
|
finally
|
|
{
|
|
_manualCheck = false;
|
|
}
|
|
}
|
|
|
|
private async void OnUpdateAvailable(string version, string changelogUrl)
|
|
{
|
|
Log.Information("Update available: v{Version}", version);
|
|
|
|
_app.Invoke(() =>
|
|
{
|
|
var confirmed = UpdateConfirmDialog.Show(_app, CurrentVersion, version);
|
|
|
|
if (confirmed)
|
|
{
|
|
_progressDialog = new UpdateProgressDialog(_app, version);
|
|
|
|
_ = Task.Run(async () =>
|
|
{
|
|
// Create backup before the update starts
|
|
try
|
|
{
|
|
_app.Invoke(() => _progressDialog?.UpdateProgress(0f, "Creating backup..."));
|
|
UpdateBackupService.CreateBackup();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Failed to create pre-update backup");
|
|
|
|
var proceed = false;
|
|
_app.Invoke(() =>
|
|
{
|
|
proceed = MessageBox.Query(
|
|
_app,
|
|
"Backup Warning",
|
|
$"Could not create backup: {ex.Message}\n\nContinue update without backup?",
|
|
"Continue", "Cancel") == 0;
|
|
});
|
|
|
|
if (!proceed)
|
|
{
|
|
_app.Invoke(() =>
|
|
{
|
|
_progressDialog?.Close();
|
|
_progressDialog = null;
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
_app.Invoke(() => _progressDialog?.UpdateProgress(0f, "Downloading update..."));
|
|
await _updater.UpdateAsync();
|
|
});
|
|
|
|
_progressDialog.Show();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void OnProgressChanged(UpdateStep step, long itemsProcessed, long? totalItems, double? progressPercentage)
|
|
{
|
|
var fraction = progressPercentage.HasValue ? (float)(progressPercentage.Value / 100.0) : 0f;
|
|
var statusText = $"{step}: {itemsProcessed}/{totalItems ?? 0} ({progressPercentage ?? 0:F0}%)";
|
|
|
|
if (!progressPercentage.HasValue)
|
|
{
|
|
statusText = $"{step}...";
|
|
}
|
|
|
|
_progressDialog?.UpdateProgress(fraction, statusText);
|
|
}
|
|
|
|
private void OnUpdateStarted(string version)
|
|
{
|
|
Log.Information("Update started: v{Version}", version);
|
|
}
|
|
|
|
private void OnNoUpdateAvailable()
|
|
{
|
|
Log.Debug("No update available");
|
|
if (_manualCheck)
|
|
{
|
|
_app.Invoke(() =>
|
|
{
|
|
MessageBox.Query(_app, "Check for Updates", $"You are already on the latest version (v{CurrentVersion}).", "OK");
|
|
});
|
|
}
|
|
}
|
|
|
|
private void OnException(Exception exception)
|
|
{
|
|
Log.Error(exception, "Update failed");
|
|
_app.Invoke(() =>
|
|
{
|
|
_progressDialog?.Close();
|
|
_progressDialog = null;
|
|
|
|
if (UpdateBackupService.BackupExists())
|
|
{
|
|
var restore = MessageBox.Query(
|
|
_app,
|
|
"Update Failed",
|
|
$"The update failed: {exception.Message}\n\n"
|
|
+ "A backup of the previous version is available.\nRestore now? (The app will restart.)",
|
|
"Restore", "Cancel");
|
|
|
|
if (restore == 0)
|
|
{
|
|
try
|
|
{
|
|
UpdateBackupService.RestoreBackup();
|
|
// RestoreBackup calls Environment.Exit(0)
|
|
}
|
|
catch (Exception restoreEx)
|
|
{
|
|
Log.Error(restoreEx, "Backup restoration failed");
|
|
MessageBox.ErrorQuery(_app, "Restore Failed",
|
|
$"Could not restore backup: {restoreEx.Message}\n\nYou may need to re-download the application.", "OK");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.ErrorQuery(_app, "Update Failed",
|
|
$"The update failed: {exception.Message}\n\nYou may need to re-download the application.", "OK");
|
|
}
|
|
});
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_updater.UpdateAvailable -= OnUpdateAvailable;
|
|
_updater.ProgressChanged -= OnProgressChanged;
|
|
_updater.UpdateStarted -= OnUpdateStarted;
|
|
_updater.NoUpdateAvailable -= OnNoUpdateAvailable;
|
|
_updater.OnException -= OnException;
|
|
}
|
|
}
|