mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-05-29 05:55:21 -04:00
Implement auto-update via Onova
This commit is contained in:
parent
7bfd645e8e
commit
63c835df88
11 changed files with 187 additions and 22 deletions
|
@ -14,7 +14,8 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
|
||||||
|
<PackageReference Include="Onova" Version="1.0.0" />
|
||||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.5.0" />
|
<PackageReference Include="Tyrrrz.Extensions" Version="1.5.0" />
|
||||||
<PackageReference Include="Tyrrrz.Settings" Version="1.3.2" />
|
<PackageReference Include="Tyrrrz.Settings" Version="1.3.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
14
DiscordChatExporter.Core/Services/IUpdateService.cs
Normal file
14
DiscordChatExporter.Core/Services/IUpdateService.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Services
|
||||||
|
{
|
||||||
|
public interface IUpdateService
|
||||||
|
{
|
||||||
|
Task<Version> CheckForUpdatesAsync();
|
||||||
|
|
||||||
|
Task PrepareUpdateAsync();
|
||||||
|
|
||||||
|
Task ApplyUpdateAsync(bool restart = true);
|
||||||
|
}
|
||||||
|
}
|
61
DiscordChatExporter.Core/Services/UpdateService.cs
Normal file
61
DiscordChatExporter.Core/Services/UpdateService.cs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Onova;
|
||||||
|
using Onova.Services;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Services
|
||||||
|
{
|
||||||
|
public class UpdateService : IUpdateService
|
||||||
|
{
|
||||||
|
private readonly UpdateManager _updateManager;
|
||||||
|
|
||||||
|
private Version _lastVersion;
|
||||||
|
private bool _applied;
|
||||||
|
|
||||||
|
public UpdateService()
|
||||||
|
{
|
||||||
|
_updateManager = new UpdateManager(
|
||||||
|
new GithubPackageResolver("Tyrrrz", "DiscordChatExporter", "DiscordChatExporter.zip"),
|
||||||
|
new ZipPackageExtractor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Version> CheckForUpdatesAsync()
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
// Never update in DEBUG mode
|
||||||
|
return null;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Remove some junk left over from last update
|
||||||
|
_updateManager.Cleanup();
|
||||||
|
|
||||||
|
// Check for updates
|
||||||
|
var check = await _updateManager.CheckForUpdatesAsync();
|
||||||
|
|
||||||
|
// Return latest version or null if running latest version already
|
||||||
|
return check.CanUpdate ? _lastVersion = check.LastVersion : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task PrepareUpdateAsync()
|
||||||
|
{
|
||||||
|
if (_lastVersion == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Download and prepare update
|
||||||
|
await _updateManager.PreparePackageAsync(_lastVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ApplyUpdateAsync(bool restart = true)
|
||||||
|
{
|
||||||
|
if (_lastVersion == null)
|
||||||
|
return;
|
||||||
|
if (_applied)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Enqueue an update
|
||||||
|
await _updateManager.EnqueueApplyPackageAsync(_lastVersion, restart);
|
||||||
|
|
||||||
|
_applied = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,9 +28,7 @@ namespace DiscordChatExporter.Gui
|
||||||
SimpleIoc.Default.Register<IExportService, ExportService>();
|
SimpleIoc.Default.Register<IExportService, ExportService>();
|
||||||
SimpleIoc.Default.Register<IMessageGroupService, MessageGroupService>();
|
SimpleIoc.Default.Register<IMessageGroupService, MessageGroupService>();
|
||||||
SimpleIoc.Default.Register<ISettingsService, SettingsService>();
|
SimpleIoc.Default.Register<ISettingsService, SettingsService>();
|
||||||
|
SimpleIoc.Default.Register<IUpdateService, UpdateService>();
|
||||||
// Load settings
|
|
||||||
Resolve<ISettingsService>().Load();
|
|
||||||
|
|
||||||
// View models
|
// View models
|
||||||
SimpleIoc.Default.Register<IErrorViewModel, ErrorViewModel>(true);
|
SimpleIoc.Default.Register<IErrorViewModel, ErrorViewModel>(true);
|
||||||
|
@ -42,8 +40,6 @@ namespace DiscordChatExporter.Gui
|
||||||
|
|
||||||
public void Cleanup()
|
public void Cleanup()
|
||||||
{
|
{
|
||||||
// Save settings
|
|
||||||
ServiceLocator.Current.GetInstance<ISettingsService>().Save();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -65,14 +65,12 @@
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\MvvmLightLibs.5.3.0.0\lib\net45\System.Windows.Interactivity.dll</HintPath>
|
<HintPath>..\packages\MvvmLightLibs.5.3.0.0\lib\net45\System.Windows.Interactivity.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Xaml">
|
<Reference Include="System.Xaml">
|
||||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
<Reference Include="Tyrrrz.Extensions, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Tyrrrz.Extensions, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Tyrrrz.Extensions.1.5.0\lib\net45\Tyrrrz.Extensions.dll</HintPath>
|
<HintPath>..\packages\Tyrrrz.Extensions.1.5.0\lib\net45\Tyrrrz.Extensions.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -84,6 +82,7 @@
|
||||||
<Compile Include="Messages\ShowErrorMessage.cs" />
|
<Compile Include="Messages\ShowErrorMessage.cs" />
|
||||||
<Compile Include="Messages\ShowExportDoneMessage.cs" />
|
<Compile Include="Messages\ShowExportDoneMessage.cs" />
|
||||||
<Compile Include="Messages\ShowExportSetupMessage.cs" />
|
<Compile Include="Messages\ShowExportSetupMessage.cs" />
|
||||||
|
<Compile Include="Messages\ShowNotificationMessage.cs" />
|
||||||
<Compile Include="Messages\ShowSettingsMessage.cs" />
|
<Compile Include="Messages\ShowSettingsMessage.cs" />
|
||||||
<Compile Include="Messages\StartExportMessage.cs" />
|
<Compile Include="Messages\StartExportMessage.cs" />
|
||||||
<Compile Include="ViewModels\ErrorViewModel.cs" />
|
<Compile Include="ViewModels\ErrorViewModel.cs" />
|
||||||
|
|
25
DiscordChatExporter.Gui/Messages/ShowNotificationMessage.cs
Normal file
25
DiscordChatExporter.Gui/Messages/ShowNotificationMessage.cs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Gui.Messages
|
||||||
|
{
|
||||||
|
public class ShowNotificationMessage
|
||||||
|
{
|
||||||
|
public string Message { get; }
|
||||||
|
|
||||||
|
public string CallbackCaption { get; }
|
||||||
|
|
||||||
|
public Action Callback { get; }
|
||||||
|
|
||||||
|
public ShowNotificationMessage(string message)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShowNotificationMessage(string message, string callbackCaption, Action callback)
|
||||||
|
: this(message)
|
||||||
|
{
|
||||||
|
CallbackCaption = callbackCaption;
|
||||||
|
Callback = callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,8 @@ namespace DiscordChatExporter.Gui.ViewModels
|
||||||
Guild SelectedGuild { get; set; }
|
Guild SelectedGuild { get; set; }
|
||||||
IReadOnlyList<Channel> AvailableChannels { get; }
|
IReadOnlyList<Channel> AvailableChannels { get; }
|
||||||
|
|
||||||
|
RelayCommand ViewLoadedCommand { get; }
|
||||||
|
RelayCommand ViewClosedCommand { get; }
|
||||||
RelayCommand PullDataCommand { get; }
|
RelayCommand PullDataCommand { get; }
|
||||||
RelayCommand ShowSettingsCommand { get; }
|
RelayCommand ShowSettingsCommand { get; }
|
||||||
RelayCommand ShowAboutCommand { get; }
|
RelayCommand ShowAboutCommand { get; }
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Windows;
|
||||||
using DiscordChatExporter.Core.Exceptions;
|
using DiscordChatExporter.Core.Exceptions;
|
||||||
using DiscordChatExporter.Core.Models;
|
using DiscordChatExporter.Core.Models;
|
||||||
using DiscordChatExporter.Core.Services;
|
using DiscordChatExporter.Core.Services;
|
||||||
|
@ -16,6 +17,7 @@ namespace DiscordChatExporter.Gui.ViewModels
|
||||||
public class MainViewModel : ViewModelBase, IMainViewModel
|
public class MainViewModel : ViewModelBase, IMainViewModel
|
||||||
{
|
{
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
|
private readonly IUpdateService _updateService;
|
||||||
private readonly IDataService _dataService;
|
private readonly IDataService _dataService;
|
||||||
private readonly IMessageGroupService _messageGroupService;
|
private readonly IMessageGroupService _messageGroupService;
|
||||||
private readonly IExportService _exportService;
|
private readonly IExportService _exportService;
|
||||||
|
@ -81,15 +83,18 @@ namespace DiscordChatExporter.Gui.ViewModels
|
||||||
private set => Set(ref _availableChannels, value);
|
private set => Set(ref _availableChannels, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RelayCommand ViewLoadedCommand { get; }
|
||||||
|
public RelayCommand ViewClosedCommand { get; }
|
||||||
public RelayCommand PullDataCommand { get; }
|
public RelayCommand PullDataCommand { get; }
|
||||||
public RelayCommand ShowSettingsCommand { get; }
|
public RelayCommand ShowSettingsCommand { get; }
|
||||||
public RelayCommand ShowAboutCommand { get; }
|
public RelayCommand ShowAboutCommand { get; }
|
||||||
public RelayCommand<Channel> ShowExportSetupCommand { get; }
|
public RelayCommand<Channel> ShowExportSetupCommand { get; }
|
||||||
|
|
||||||
public MainViewModel(ISettingsService settingsService, IDataService dataService,
|
public MainViewModel(ISettingsService settingsService, IUpdateService updateService, IDataService dataService,
|
||||||
IMessageGroupService messageGroupService, IExportService exportService)
|
IMessageGroupService messageGroupService, IExportService exportService)
|
||||||
{
|
{
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
|
_updateService = updateService;
|
||||||
_dataService = dataService;
|
_dataService = dataService;
|
||||||
_messageGroupService = messageGroupService;
|
_messageGroupService = messageGroupService;
|
||||||
_exportService = exportService;
|
_exportService = exportService;
|
||||||
|
@ -97,19 +102,54 @@ namespace DiscordChatExporter.Gui.ViewModels
|
||||||
_guildChannelsMap = new Dictionary<Guild, IReadOnlyList<Channel>>();
|
_guildChannelsMap = new Dictionary<Guild, IReadOnlyList<Channel>>();
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
|
ViewLoadedCommand = new RelayCommand(ViewLoaded);
|
||||||
|
ViewClosedCommand = new RelayCommand(ViewClosed);
|
||||||
PullDataCommand = new RelayCommand(PullData, () => Token.IsNotBlank() && !IsBusy);
|
PullDataCommand = new RelayCommand(PullData, () => Token.IsNotBlank() && !IsBusy);
|
||||||
ShowSettingsCommand = new RelayCommand(ShowSettings);
|
ShowSettingsCommand = new RelayCommand(ShowSettings);
|
||||||
ShowAboutCommand = new RelayCommand(ShowAbout);
|
ShowAboutCommand = new RelayCommand(ShowAbout);
|
||||||
ShowExportSetupCommand = new RelayCommand<Channel>(ShowExportSetup, _ => !IsBusy);
|
ShowExportSetupCommand = new RelayCommand<Channel>(ShowExportSetup, _ => !IsBusy);
|
||||||
|
|
||||||
// Messages
|
// Messages
|
||||||
MessengerInstance.Register<StartExportMessage>(this, m =>
|
MessengerInstance.Register<StartExportMessage>(this,
|
||||||
{
|
m => { Export(m.Channel, m.FilePath, m.Format, m.From, m.To); });
|
||||||
Export(m.Channel, m.FilePath, m.Format, m.From, m.To);
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Defaults
|
private async void ViewLoaded()
|
||||||
_token = _settingsService.LastToken;
|
{
|
||||||
|
// Load settings
|
||||||
|
_settingsService.Load();
|
||||||
|
|
||||||
|
// Set last token
|
||||||
|
Token = _settingsService.LastToken;
|
||||||
|
|
||||||
|
// Check for updates
|
||||||
|
var lastVersion = await _updateService.CheckForUpdatesAsync();
|
||||||
|
if (lastVersion != null)
|
||||||
|
{
|
||||||
|
// Download updates
|
||||||
|
await _updateService.PrepareUpdateAsync();
|
||||||
|
|
||||||
|
// Notify user
|
||||||
|
MessengerInstance.Send(
|
||||||
|
new ShowNotificationMessage(
|
||||||
|
$"DiscordChatExporter v{lastVersion} has been downloaded. " +
|
||||||
|
"It will be installed once you exit.",
|
||||||
|
"INSTALL NOW",
|
||||||
|
async () =>
|
||||||
|
{
|
||||||
|
await _updateService.ApplyUpdateAsync();
|
||||||
|
Application.Current.Shutdown();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ViewClosed()
|
||||||
|
{
|
||||||
|
// Save settings
|
||||||
|
_settingsService.Save();
|
||||||
|
|
||||||
|
// Apply updates if available
|
||||||
|
_updateService.ApplyUpdateAsync(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void PullData()
|
private async void PullData()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using MaterialDesignThemes.Wpf
|
using System.Windows.Interactivity;
|
||||||
|
using MaterialDesignThemes.Wpf
|
||||||
using MaterialDesignThemes.Wpf.Transitions
|
using MaterialDesignThemes.Wpf.Transitions
|
||||||
|
|
||||||
Window "DiscordChatExporter.Gui.Views.MainWindow" {
|
Window "DiscordChatExporter.Gui.Views.MainWindow" {
|
||||||
|
@ -19,15 +20,27 @@ Window "DiscordChatExporter.Gui.Views.MainWindow" {
|
||||||
UseLayoutRounding: true
|
UseLayoutRounding: true
|
||||||
WindowStartupLocation: CenterScreen
|
WindowStartupLocation: CenterScreen
|
||||||
|
|
||||||
DialogHost {
|
Interaction.Triggers: [
|
||||||
DockPanel {
|
Interactivity.EventTrigger {
|
||||||
IsEnabled: bind IsBusy
|
EventName: "Loaded"
|
||||||
convert (bool b) => b ? false : true
|
InvokeCommandAction { Command: bind ViewLoadedCommand }
|
||||||
|
},
|
||||||
|
Interactivity.EventTrigger {
|
||||||
|
EventName: "Closed"
|
||||||
|
InvokeCommandAction { Command: bind ViewClosedCommand }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
DialogHost {
|
||||||
|
SnackbarMessageQueue: bind MessageQueue from "Snackbar"
|
||||||
|
|
||||||
|
DockPanel {
|
||||||
// Toolbar
|
// Toolbar
|
||||||
Border {
|
Border {
|
||||||
DockPanel.Dock: Top
|
DockPanel.Dock: Top
|
||||||
Background: resource dyn "PrimaryHueMidBrush"
|
Background: resource dyn "PrimaryHueMidBrush"
|
||||||
|
IsEnabled: bind IsBusy
|
||||||
|
convert (bool b) => b ? false : true
|
||||||
TextElement.Foreground: resource dyn "SecondaryInverseTextBrush"
|
TextElement.Foreground: resource dyn "SecondaryInverseTextBrush"
|
||||||
StackPanel {
|
StackPanel {
|
||||||
Grid {
|
Grid {
|
||||||
|
@ -104,6 +117,8 @@ Window "DiscordChatExporter.Gui.Views.MainWindow" {
|
||||||
Grid {
|
Grid {
|
||||||
DockPanel {
|
DockPanel {
|
||||||
Background: resource dyn "MaterialDesignCardBackground"
|
Background: resource dyn "MaterialDesignCardBackground"
|
||||||
|
IsEnabled: bind IsBusy
|
||||||
|
convert (bool b) => b ? false : true
|
||||||
Visibility: bind IsDataAvailable
|
Visibility: bind IsDataAvailable
|
||||||
convert (bool b) => b ? Visibility.Visible : Visibility.Hidden
|
convert (bool b) => b ? Visibility.Visible : Visibility.Hidden
|
||||||
|
|
||||||
|
@ -265,6 +280,10 @@ Window "DiscordChatExporter.Gui.Views.MainWindow" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Snackbar
|
||||||
|
Snackbar "Snackbar" {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Reflection;
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
using DiscordChatExporter.Gui.Messages;
|
using DiscordChatExporter.Gui.Messages;
|
||||||
using GalaSoft.MvvmLight.Messaging;
|
using GalaSoft.MvvmLight.Messaging;
|
||||||
using MaterialDesignThemes.Wpf;
|
using MaterialDesignThemes.Wpf;
|
||||||
|
@ -13,7 +14,13 @@ namespace DiscordChatExporter.Gui.Views
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
Title += $" v{Assembly.GetExecutingAssembly().GetName().Version}";
|
Title += $" v{Assembly.GetExecutingAssembly().GetName().Version}";
|
||||||
|
|
||||||
// Dialogs
|
Snackbar.MessageQueue = new SnackbarMessageQueue(TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
|
// Notification messages
|
||||||
|
Messenger.Default.Register<ShowNotificationMessage>(this,
|
||||||
|
m => Snackbar.MessageQueue.Enqueue(m.Message, m.CallbackCaption, m.Callback));
|
||||||
|
|
||||||
|
// Dialog messages
|
||||||
Messenger.Default.Register<ShowErrorMessage>(this,
|
Messenger.Default.Register<ShowErrorMessage>(this,
|
||||||
m => DialogHost.Show(new ErrorDialog()).Forget());
|
m => DialogHost.Show(new ErrorDialog()).Forget());
|
||||||
Messenger.Default.Register<ShowExportDoneMessage>(this,
|
Messenger.Default.Register<ShowExportDoneMessage>(this,
|
||||||
|
|
|
@ -39,6 +39,7 @@ DiscordChatExporter can be used to export message history from a [Discord](https
|
||||||
- [GalaSoft.MVVMLight](http://www.mvvmlight.net)
|
- [GalaSoft.MVVMLight](http://www.mvvmlight.net)
|
||||||
- [MaterialDesignInXamlToolkit](https://github.com/ButchersBoy/MaterialDesignInXamlToolkit)
|
- [MaterialDesignInXamlToolkit](https://github.com/ButchersBoy/MaterialDesignInXamlToolkit)
|
||||||
- [Newtonsoft.Json](http://www.newtonsoft.com/json)
|
- [Newtonsoft.Json](http://www.newtonsoft.com/json)
|
||||||
|
- [Onova](https://github.com/Tyrrrz/Onova)
|
||||||
- [FluentCommandLineParser](https://github.com/fclp/fluent-command-line-parser)
|
- [FluentCommandLineParser](https://github.com/fclp/fluent-command-line-parser)
|
||||||
- [Tyrrrz.Extensions](https://github.com/Tyrrrz/Extensions)
|
- [Tyrrrz.Extensions](https://github.com/Tyrrrz/Extensions)
|
||||||
- [Tyrrrz.Settings](https://github.com/Tyrrrz/Settings)
|
- [Tyrrrz.Settings](https://github.com/Tyrrrz/Settings)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue