Streamline auto-update process and refactor

This commit is contained in:
Alexey Golub 2019-09-15 14:11:06 +03:00
parent 82af36c90d
commit 12a5091d73
4 changed files with 56 additions and 59 deletions

View file

@ -9,8 +9,6 @@ namespace DiscordChatExporter.Gui.Services
{ {
public class UpdateService : IDisposable public class UpdateService : IDisposable
{ {
private readonly SettingsService _settingsService;
private readonly IUpdateManager _updateManager = new UpdateManager( private readonly IUpdateManager _updateManager = new UpdateManager(
new GithubPackageResolver("Tyrrrz", "DiscordChatExporter", "DiscordChatExporter.zip"), new GithubPackageResolver("Tyrrrz", "DiscordChatExporter", "DiscordChatExporter.zip"),
new ZipPackageExtractor()); new ZipPackageExtractor());
@ -18,36 +16,25 @@ namespace DiscordChatExporter.Gui.Services
private Version _updateVersion; private Version _updateVersion;
private bool _updaterLaunched; private bool _updaterLaunched;
public UpdateService(SettingsService settingsService) public async Task<Version> CheckForUpdatesAsync()
{ {
_settingsService = settingsService; var check = await _updateManager.CheckForUpdatesAsync();
return check.CanUpdate ? check.LastVersion : null;
} }
public async Task<Version> CheckPrepareUpdateAsync() public async Task PrepareUpdateAsync(Version version)
{ {
try try
{ {
// If auto-update is disabled - don't check for updates await _updateManager.PrepareUpdateAsync(_updateVersion = version);
if (!_settingsService.IsAutoUpdateEnabled)
return null;
// Check for updates
var check = await _updateManager.CheckForUpdatesAsync();
if (!check.CanUpdate)
return null;
// Prepare the update
await _updateManager.PrepareUpdateAsync(check.LastVersion);
return _updateVersion = check.LastVersion;
} }
catch (UpdaterAlreadyLaunchedException) catch (UpdaterAlreadyLaunchedException)
{ {
return null; // Ignore race conditions
} }
catch (LockFileNotAcquiredException) catch (LockFileNotAcquiredException)
{ {
return null; // Ignore race conditions
} }
} }
@ -55,23 +42,20 @@ namespace DiscordChatExporter.Gui.Services
{ {
try try
{ {
// Check if an update is pending if (_updateVersion == null || _updaterLaunched)
if (_updateVersion == null)
return; return;
// Check if the updater has already been launched
if (_updaterLaunched)
return;
// Launch the updater
_updateManager.LaunchUpdater(_updateVersion, needRestart); _updateManager.LaunchUpdater(_updateVersion, needRestart);
_updaterLaunched = true; _updaterLaunched = true;
} }
catch (UpdaterAlreadyLaunchedException) catch (UpdaterAlreadyLaunchedException)
{ {
// Ignore race conditions
} }
catch (LockFileNotAcquiredException) catch (LockFileNotAcquiredException)
{ {
// Ignore race conditions
} }
} }

View file

@ -22,46 +22,46 @@ namespace DiscordChatExporter.Gui.ViewModels.Framework
var view = _viewManager.CreateAndBindViewForModelIfNecessary(dialogScreen); var view = _viewManager.CreateAndBindViewForModelIfNecessary(dialogScreen);
// Set up event routing that will close the view when called from viewmodel // Set up event routing that will close the view when called from viewmodel
DialogOpenedEventHandler onDialogOpened = (sender, e) => void OnDialogOpened(object sender, DialogOpenedEventArgs openArgs)
{ {
// Delegate to close the dialog and unregister event handler // Delegate to close the dialog and unregister event handler
void OnScreenClosed(object o, CloseEventArgs args) void OnScreenClosed(object o, CloseEventArgs closeArgs)
{ {
e.Session.Close(); openArgs.Session.Close();
dialogScreen.Closed -= OnScreenClosed; dialogScreen.Closed -= OnScreenClosed;
} }
dialogScreen.Closed += OnScreenClosed; dialogScreen.Closed += OnScreenClosed;
}; }
// Show view // Show view
await DialogHost.Show(view, onDialogOpened); await DialogHost.Show(view, OnDialogOpened);
// Return the result // Return the result
return dialogScreen.DialogResult; return dialogScreen.DialogResult;
} }
public string PromptSaveFilePath(string filter = "All files|*.*", string initialFilePath = "") public string PromptSaveFilePath(string filter = "All files|*.*", string defaultFilePath = "")
{ {
// Create dialog // Create dialog
var dialog = new SaveFileDialog var dialog = new SaveFileDialog
{ {
Filter = filter, Filter = filter,
AddExtension = true, AddExtension = true,
FileName = initialFilePath, FileName = defaultFilePath,
DefaultExt = Path.GetExtension(initialFilePath) ?? "" DefaultExt = Path.GetExtension(defaultFilePath) ?? ""
}; };
// Show dialog and return result // Show dialog and return result
return dialog.ShowDialog() == true ? dialog.FileName : null; return dialog.ShowDialog() == true ? dialog.FileName : null;
} }
public string PromptDirectoryPath(string initialDirPath = "") public string PromptDirectoryPath(string defaultDirPath = "")
{ {
// Create dialog // Create dialog
var dialog = new VistaFolderBrowserDialog var dialog = new VistaFolderBrowserDialog
{ {
SelectedPath = initialDirPath SelectedPath = defaultDirPath
}; };
// Show dialog and return result // Show dialog and return result

View file

@ -36,9 +36,5 @@ namespace DiscordChatExporter.Gui.ViewModels.Framework
return viewModel; return viewModel;
} }
public static ExportSetupViewModel CreateExportSetupViewModel(this IViewModelFactory factory,
GuildViewModel guild, ChannelViewModel channel)
=> factory.CreateExportSetupViewModel(guild, new[] { channel });
} }
} }

View file

@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using DiscordChatExporter.Core.Models; using DiscordChatExporter.Core.Models;
using DiscordChatExporter.Core.Services; using DiscordChatExporter.Core.Services;
using DiscordChatExporter.Core.Services.Exceptions; using DiscordChatExporter.Core.Services.Exceptions;
@ -68,6 +69,39 @@ namespace DiscordChatExporter.Gui.ViewModels
(sender, args) => IsProgressIndeterminate = ProgressManager.IsActive && ProgressManager.Progress.IsEither(0, 1)); (sender, args) => IsProgressIndeterminate = ProgressManager.IsActive && ProgressManager.Progress.IsEither(0, 1));
} }
private async Task HandleAutoUpdateAsync()
{
try
{
// Don't check for updates if auto-update is disabled
if (!_settingsService.IsAutoUpdateEnabled)
return;
// Check for updates
var updateVersion = await _updateService.CheckForUpdatesAsync();
if (updateVersion == null)
return;
// Notify user of an update and prepare it
Notifications.Enqueue($"Downloading update to DiscordChatExporter v{updateVersion}...");
await _updateService.PrepareUpdateAsync(updateVersion);
// Prompt user to install update (otherwise install it when application exits)
Notifications.Enqueue(
"Update has been downloaded and will be installed when you exit",
"INSTALL NOW", () =>
{
_updateService.FinalizeUpdate(true);
RequestClose();
});
}
catch
{
// Failure to update shouldn't crash the application
Notifications.Enqueue("Failed to perform application update");
}
}
protected override async void OnViewLoaded() protected override async void OnViewLoaded()
{ {
base.OnViewLoaded(); base.OnViewLoaded();
@ -83,24 +117,7 @@ namespace DiscordChatExporter.Gui.ViewModels
} }
// Check and prepare update // Check and prepare update
try await HandleAutoUpdateAsync();
{
var updateVersion = await _updateService.CheckPrepareUpdateAsync();
if (updateVersion != null)
{
Notifications.Enqueue(
$"Update to DiscordChatExporter v{updateVersion} will be installed when you exit",
"INSTALL NOW", () =>
{
_updateService.FinalizeUpdate(true);
RequestClose();
});
}
}
catch
{
Notifications.Enqueue("Failed to perform application auto-update");
}
} }
protected override void OnClose() protected override void OnClose()