From 12a5091d7300f0084eb4182318dd729255efca47 Mon Sep 17 00:00:00 2001 From: Alexey Golub Date: Sun, 15 Sep 2019 14:11:06 +0300 Subject: [PATCH] Streamline auto-update process and refactor --- .../Services/UpdateService.cs | 38 ++++--------- .../ViewModels/Framework/DialogManager.cs | 20 +++---- .../ViewModels/Framework/Extensions.cs | 4 -- .../ViewModels/RootViewModel.cs | 53 ++++++++++++------- 4 files changed, 56 insertions(+), 59 deletions(-) diff --git a/DiscordChatExporter.Gui/Services/UpdateService.cs b/DiscordChatExporter.Gui/Services/UpdateService.cs index cf905d6c..1057a655 100644 --- a/DiscordChatExporter.Gui/Services/UpdateService.cs +++ b/DiscordChatExporter.Gui/Services/UpdateService.cs @@ -9,8 +9,6 @@ namespace DiscordChatExporter.Gui.Services { public class UpdateService : IDisposable { - private readonly SettingsService _settingsService; - private readonly IUpdateManager _updateManager = new UpdateManager( new GithubPackageResolver("Tyrrrz", "DiscordChatExporter", "DiscordChatExporter.zip"), new ZipPackageExtractor()); @@ -18,36 +16,25 @@ namespace DiscordChatExporter.Gui.Services private Version _updateVersion; private bool _updaterLaunched; - public UpdateService(SettingsService settingsService) + public async Task CheckForUpdatesAsync() { - _settingsService = settingsService; + var check = await _updateManager.CheckForUpdatesAsync(); + return check.CanUpdate ? check.LastVersion : null; } - public async Task CheckPrepareUpdateAsync() + public async Task PrepareUpdateAsync(Version version) { try { - // If auto-update is disabled - don't check for updates - 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; + await _updateManager.PrepareUpdateAsync(_updateVersion = version); } catch (UpdaterAlreadyLaunchedException) { - return null; + // Ignore race conditions } catch (LockFileNotAcquiredException) { - return null; + // Ignore race conditions } } @@ -55,23 +42,20 @@ namespace DiscordChatExporter.Gui.Services { try { - // Check if an update is pending - if (_updateVersion == null) + if (_updateVersion == null || _updaterLaunched) return; - // Check if the updater has already been launched - if (_updaterLaunched) - return; - - // Launch the updater _updateManager.LaunchUpdater(_updateVersion, needRestart); + _updaterLaunched = true; } catch (UpdaterAlreadyLaunchedException) { + // Ignore race conditions } catch (LockFileNotAcquiredException) { + // Ignore race conditions } } diff --git a/DiscordChatExporter.Gui/ViewModels/Framework/DialogManager.cs b/DiscordChatExporter.Gui/ViewModels/Framework/DialogManager.cs index 9e5761f4..09d378f6 100644 --- a/DiscordChatExporter.Gui/ViewModels/Framework/DialogManager.cs +++ b/DiscordChatExporter.Gui/ViewModels/Framework/DialogManager.cs @@ -22,46 +22,46 @@ namespace DiscordChatExporter.Gui.ViewModels.Framework var view = _viewManager.CreateAndBindViewForModelIfNecessary(dialogScreen); // 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 - void OnScreenClosed(object o, CloseEventArgs args) + void OnScreenClosed(object o, CloseEventArgs closeArgs) { - e.Session.Close(); + openArgs.Session.Close(); dialogScreen.Closed -= OnScreenClosed; } dialogScreen.Closed += OnScreenClosed; - }; + } // Show view - await DialogHost.Show(view, onDialogOpened); + await DialogHost.Show(view, OnDialogOpened); // Return the result return dialogScreen.DialogResult; } - public string PromptSaveFilePath(string filter = "All files|*.*", string initialFilePath = "") + public string PromptSaveFilePath(string filter = "All files|*.*", string defaultFilePath = "") { // Create dialog var dialog = new SaveFileDialog { Filter = filter, AddExtension = true, - FileName = initialFilePath, - DefaultExt = Path.GetExtension(initialFilePath) ?? "" + FileName = defaultFilePath, + DefaultExt = Path.GetExtension(defaultFilePath) ?? "" }; // Show dialog and return result return dialog.ShowDialog() == true ? dialog.FileName : null; } - public string PromptDirectoryPath(string initialDirPath = "") + public string PromptDirectoryPath(string defaultDirPath = "") { // Create dialog var dialog = new VistaFolderBrowserDialog { - SelectedPath = initialDirPath + SelectedPath = defaultDirPath }; // Show dialog and return result diff --git a/DiscordChatExporter.Gui/ViewModels/Framework/Extensions.cs b/DiscordChatExporter.Gui/ViewModels/Framework/Extensions.cs index 6f6e74d5..edac0c8c 100644 --- a/DiscordChatExporter.Gui/ViewModels/Framework/Extensions.cs +++ b/DiscordChatExporter.Gui/ViewModels/Framework/Extensions.cs @@ -36,9 +36,5 @@ namespace DiscordChatExporter.Gui.ViewModels.Framework return viewModel; } - - public static ExportSetupViewModel CreateExportSetupViewModel(this IViewModelFactory factory, - GuildViewModel guild, ChannelViewModel channel) - => factory.CreateExportSetupViewModel(guild, new[] { channel }); } } \ No newline at end of file diff --git a/DiscordChatExporter.Gui/ViewModels/RootViewModel.cs b/DiscordChatExporter.Gui/ViewModels/RootViewModel.cs index 865c14b9..f147c865 100644 --- a/DiscordChatExporter.Gui/ViewModels/RootViewModel.cs +++ b/DiscordChatExporter.Gui/ViewModels/RootViewModel.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Net; using System.Reflection; +using System.Threading.Tasks; using DiscordChatExporter.Core.Models; using DiscordChatExporter.Core.Services; using DiscordChatExporter.Core.Services.Exceptions; @@ -68,6 +69,39 @@ namespace DiscordChatExporter.Gui.ViewModels (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() { base.OnViewLoaded(); @@ -83,24 +117,7 @@ namespace DiscordChatExporter.Gui.ViewModels } // Check and prepare update - try - { - 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"); - } + await HandleAutoUpdateAsync(); } protected override void OnClose()