mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Workshop - Auto-updating WIP
This commit is contained in:
parent
99d11e1921
commit
3b2d799bfc
@ -1,17 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Windows.UI.Notifications;
|
using Windows.UI.Notifications;
|
||||||
using Artemis.UI.Screens.Settings;
|
using Artemis.UI.Services.Interfaces;
|
||||||
using Artemis.UI.Services.Updating;
|
using Artemis.UI.Services.Updating;
|
||||||
using Artemis.UI.Shared.Routing;
|
using Artemis.UI.Shared.Routing;
|
||||||
using Artemis.UI.Shared.Services.MainWindow;
|
using Artemis.UI.Shared.Services.MainWindow;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using Microsoft.Toolkit.Uwp.Notifications;
|
using Microsoft.Toolkit.Uwp.Notifications;
|
||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Windows.Providers;
|
namespace Artemis.UI.Windows.Providers;
|
||||||
|
|
||||||
@ -20,18 +18,34 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
|||||||
private readonly Func<Guid, ReleaseInstaller> _getReleaseInstaller;
|
private readonly Func<Guid, ReleaseInstaller> _getReleaseInstaller;
|
||||||
private readonly IMainWindowService _mainWindowService;
|
private readonly IMainWindowService _mainWindowService;
|
||||||
private readonly IUpdateService _updateService;
|
private readonly IUpdateService _updateService;
|
||||||
|
private readonly IWorkshopUpdateService _workshopUpdateService;
|
||||||
private readonly IRouter _router;
|
private readonly IRouter _router;
|
||||||
private CancellationTokenSource? _cancellationTokenSource;
|
private CancellationTokenSource? _cancellationTokenSource;
|
||||||
|
|
||||||
public WindowsUpdateNotificationProvider(IMainWindowService mainWindowService, IUpdateService updateService, IRouter router, Func<Guid, ReleaseInstaller> getReleaseInstaller)
|
public WindowsUpdateNotificationProvider(IMainWindowService mainWindowService,
|
||||||
|
IUpdateService updateService,
|
||||||
|
IWorkshopUpdateService workshopUpdateService,
|
||||||
|
IRouter router, Func<Guid, ReleaseInstaller> getReleaseInstaller)
|
||||||
{
|
{
|
||||||
_mainWindowService = mainWindowService;
|
_mainWindowService = mainWindowService;
|
||||||
_updateService = updateService;
|
_updateService = updateService;
|
||||||
|
_workshopUpdateService = workshopUpdateService;
|
||||||
_router = router;
|
_router = router;
|
||||||
_getReleaseInstaller = getReleaseInstaller;
|
_getReleaseInstaller = getReleaseInstaller;
|
||||||
ToastNotificationManagerCompat.OnActivated += ToastNotificationManagerCompatOnOnActivated;
|
ToastNotificationManagerCompat.OnActivated += ToastNotificationManagerCompatOnOnActivated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void ShowWorkshopNotification(int updatedEntries)
|
||||||
|
{
|
||||||
|
new ToastContentBuilder().AddText(updatedEntries == 1 ? "Workshop update installed" : "Workshop updates installed")
|
||||||
|
.AddText(updatedEntries == 1 ? "A workshop update has been installed" : $"{updatedEntries} workshop updates have been installed")
|
||||||
|
.AddArgument("action", "view-library")
|
||||||
|
.AddButton(new ToastButton().SetContent("View changes").AddArgument("action", "view-library"))
|
||||||
|
.AddButton(new ToastButton().SetContent("Don't show again").AddArgument("action", "disable-workshop-notifications"))
|
||||||
|
.Show();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void ShowNotification(Guid releaseId, string releaseVersion)
|
public void ShowNotification(Guid releaseId, string releaseVersion)
|
||||||
{
|
{
|
||||||
@ -57,14 +71,8 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
|||||||
|
|
||||||
private void ViewRelease(Guid? releaseId)
|
private void ViewRelease(Guid? releaseId)
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.Invoke(async () =>
|
string route = releaseId != null && releaseId.Value != Guid.Empty ? $"settings/releases/{releaseId}" : "settings/releases";
|
||||||
{
|
NavigateToRoute(route);
|
||||||
_mainWindowService.OpenMainWindow();
|
|
||||||
if (releaseId != null && releaseId.Value != Guid.Empty)
|
|
||||||
await _router.Navigate($"settings/releases/{releaseId}");
|
|
||||||
else
|
|
||||||
await _router.Navigate("settings/releases");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InstallRelease(Guid releaseId, string releaseVersion)
|
private async Task InstallRelease(Guid releaseId, string releaseVersion)
|
||||||
@ -153,10 +161,8 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
|||||||
ToastArguments args = ToastArguments.Parse(e.Argument);
|
ToastArguments args = ToastArguments.Parse(e.Argument);
|
||||||
|
|
||||||
Guid releaseId = args.Contains("releaseId") ? Guid.Parse(args.Get("releaseId")) : Guid.Empty;
|
Guid releaseId = args.Contains("releaseId") ? Guid.Parse(args.Get("releaseId")) : Guid.Empty;
|
||||||
string releaseVersion = args.Get("releaseVersion");
|
string releaseVersion = args.Contains("releaseVersion") ? args.Get("releaseVersion") : string.Empty;
|
||||||
string action = "view-changes";
|
string action = args.Contains("action") ? args.Get("action") : "view-changes";
|
||||||
if (args.Contains("action"))
|
|
||||||
action = args.Get("action");
|
|
||||||
|
|
||||||
if (action == "install")
|
if (action == "install")
|
||||||
await InstallRelease(releaseId, releaseVersion);
|
await InstallRelease(releaseId, releaseVersion);
|
||||||
@ -166,5 +172,18 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
|||||||
_cancellationTokenSource?.Cancel();
|
_cancellationTokenSource?.Cancel();
|
||||||
else if (action == "restart-for-update")
|
else if (action == "restart-for-update")
|
||||||
_updateService.RestartForUpdate("WindowsNotification", false);
|
_updateService.RestartForUpdate("WindowsNotification", false);
|
||||||
|
else if (action == "disable-workshop-notifications")
|
||||||
|
_workshopUpdateService.DisableNotifications();
|
||||||
|
else if (action == "view-library")
|
||||||
|
NavigateToRoute("workshop/library");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NavigateToRoute(string route)
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Invoke(async () =>
|
||||||
|
{
|
||||||
|
_mainWindowService.OpenMainWindow();
|
||||||
|
await _router.Navigate(route);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@
|
|||||||
Auto-install updates
|
Auto-install updates
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<TextBlock Classes="subtitle" TextWrapping="Wrap">
|
<TextBlock Classes="subtitle" TextWrapping="Wrap">
|
||||||
If enabled, new updates will automatically be installed.
|
Automatically install new versions of Artemis in the background when available.
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||||
@ -203,6 +203,21 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
<Border Classes="card-separator" />
|
<Border Classes="card-separator" />
|
||||||
|
|
||||||
|
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto" IsVisible="{CompiledBinding IsWindows}">
|
||||||
|
<StackPanel Grid.Column="0">
|
||||||
|
<TextBlock>
|
||||||
|
Show workshop update notifications
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Classes="subtitle" TextWrapping="Wrap">
|
||||||
|
Show a desktop notification whenever workshop updates are installed.
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||||
|
<ToggleSwitch IsChecked="{CompiledBinding WorkshopShowNotifications.Value}" MinWidth="0" OnContent="Yes" OffContent="No" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
<Border Classes="card-separator" />
|
||||||
|
|
||||||
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
||||||
<StackPanel Grid.Column="0" VerticalAlignment="Center">
|
<StackPanel Grid.Column="0" VerticalAlignment="Center">
|
||||||
<TextBlock>
|
<TextBlock>
|
||||||
|
|||||||
@ -102,6 +102,7 @@ public class GeneralTabViewModel : RoutableScreen
|
|||||||
|
|
||||||
public bool IsAutoRunSupported => _autoRunProvider != null;
|
public bool IsAutoRunSupported => _autoRunProvider != null;
|
||||||
public bool IsWindows11 => OSVersionHelper.IsWindows11();
|
public bool IsWindows11 => OSVersionHelper.IsWindows11();
|
||||||
|
public bool IsWindows => OSVersionHelper.IsWindows();
|
||||||
|
|
||||||
public ObservableCollection<LayerBrushDescriptor> LayerBrushDescriptors { get; }
|
public ObservableCollection<LayerBrushDescriptor> LayerBrushDescriptors { get; }
|
||||||
public ObservableCollection<string> GraphicsContexts { get; }
|
public ObservableCollection<string> GraphicsContexts { get; }
|
||||||
@ -158,6 +159,7 @@ public class GeneralTabViewModel : RoutableScreen
|
|||||||
public PluginSetting<bool> UIShowOnStartup => _settingsService.GetSetting("UI.ShowOnStartup", true);
|
public PluginSetting<bool> UIShowOnStartup => _settingsService.GetSetting("UI.ShowOnStartup", true);
|
||||||
public PluginSetting<bool> EnableMica => _settingsService.GetSetting("UI.EnableMica", true);
|
public PluginSetting<bool> EnableMica => _settingsService.GetSetting("UI.EnableMica", true);
|
||||||
public PluginSetting<bool> UICheckForUpdates => _settingsService.GetSetting("UI.Updating.AutoCheck", true);
|
public PluginSetting<bool> UICheckForUpdates => _settingsService.GetSetting("UI.Updating.AutoCheck", true);
|
||||||
|
public PluginSetting<bool> WorkshopShowNotifications => _settingsService.GetSetting("Workshop.ShowNotifications", true);
|
||||||
public PluginSetting<bool> UIAutoUpdate => _settingsService.GetSetting("UI.Updating.AutoInstall", true);
|
public PluginSetting<bool> UIAutoUpdate => _settingsService.GetSetting("UI.Updating.AutoInstall", true);
|
||||||
public PluginSetting<bool> ProfileEditorShowDataModelValues => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
|
public PluginSetting<bool> ProfileEditorShowDataModelValues => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
|
||||||
public PluginSetting<LogEventLevel> CoreLoggingLevel => _settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information);
|
public PluginSetting<LogEventLevel> CoreLoggingLevel => _settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information);
|
||||||
|
|||||||
@ -101,14 +101,27 @@ public partial class EntryReleaseInfoViewModel : ActivatableViewModelBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If not the latest version, warn and offer to disable auto-updates
|
||||||
|
bool disableAutoUpdates = false;
|
||||||
|
if (Release.Id != Release.Entry.LatestReleaseId)
|
||||||
|
{
|
||||||
|
disableAutoUpdates = await _windowService.ShowConfirmContentDialog(
|
||||||
|
"You are installing an older version of this entry",
|
||||||
|
"Would you like to disable auto-updates for this entry?",
|
||||||
|
"Yes",
|
||||||
|
"No"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
_cts = new CancellationTokenSource();
|
_cts = new CancellationTokenSource();
|
||||||
InstallProgress = 0;
|
InstallProgress = 0;
|
||||||
InstallationInProgress = true;
|
InstallationInProgress = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
EntryInstallResult result = await _workshopService.InstallEntry(Release.Entry, Release, _progress, _cts.Token);
|
EntryInstallResult result = await _workshopService.InstallEntry(Release.Entry, Release, _progress, _cts.Token);
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess && result.Entry != null)
|
||||||
{
|
{
|
||||||
|
_workshopService.SetAutoUpdate(result.Entry, !disableAutoUpdates);
|
||||||
_notificationService.CreateNotification().WithTitle("Installation succeeded").WithSeverity(NotificationSeverity.Success).Show();
|
_notificationService.CreateNotification().WithTitle("Installation succeeded").WithSeverity(NotificationSeverity.Success).Show();
|
||||||
InstallationInProgress = false;
|
InstallationInProgress = false;
|
||||||
await Manage();
|
await Manage();
|
||||||
|
|||||||
@ -66,11 +66,9 @@
|
|||||||
|
|
||||||
<!-- Info -->
|
<!-- Info -->
|
||||||
<StackPanel Grid.Column="2" Grid.Row="0" Margin="0 0 4 0" HorizontalAlignment="Right">
|
<StackPanel Grid.Column="2" Grid.Row="0" Margin="0 0 4 0" HorizontalAlignment="Right">
|
||||||
<TextBlock TextAlignment="Right" Text="{CompiledBinding Entry.CreatedAt, FallbackValue=01-01-1337, Converter={StaticResource DateTimeConverter}}" />
|
|
||||||
<TextBlock TextAlignment="Right">
|
<TextBlock TextAlignment="Right">
|
||||||
<avalonia:MaterialIcon Kind="Downloads" />
|
<avalonia:MaterialIcon Kind="Harddisk" />
|
||||||
<Run Classes="h5" Text="{CompiledBinding Entry.Downloads, FallbackValue=0}" />
|
<Run Text="{CompiledBinding Entry.ReleaseVersion}" />
|
||||||
<Run>downloads</Run>
|
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
@ -89,7 +87,7 @@
|
|||||||
<Button Command="{CompiledBinding ViewLocal}" HorizontalAlignment="Stretch" >Open</Button>
|
<Button Command="{CompiledBinding ViewLocal}" HorizontalAlignment="Stretch" >Open</Button>
|
||||||
<Button Command="{CompiledBinding Uninstall}" HorizontalAlignment="Stretch">Uninstall</Button>
|
<Button Command="{CompiledBinding Uninstall}" HorizontalAlignment="Stretch">Uninstall</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<CheckBox MinHeight="26" Margin="0 4 0 0" IsEnabled="False">Auto-update</CheckBox>
|
<CheckBox MinHeight="26" Margin="0 4 0 0" IsChecked="{CompiledBinding AutoUpdate}">Auto-update</CheckBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
using Avalonia;
|
using Avalonia.ReactiveUI;
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
|
||||||
using Avalonia.ReactiveUI;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
|
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
using System.Reactive.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
@ -9,6 +10,7 @@ using Artemis.Core.Services;
|
|||||||
using Artemis.UI.DryIoc.Factories;
|
using Artemis.UI.DryIoc.Factories;
|
||||||
using Artemis.UI.Extensions;
|
using Artemis.UI.Extensions;
|
||||||
using Artemis.UI.Screens.Plugins;
|
using Artemis.UI.Screens.Plugins;
|
||||||
|
using Artemis.UI.Services.Interfaces;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Routing;
|
using Artemis.UI.Shared.Routing;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
@ -25,16 +27,19 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
|
|||||||
{
|
{
|
||||||
private readonly IWorkshopClient _client;
|
private readonly IWorkshopClient _client;
|
||||||
private readonly IWorkshopService _workshopService;
|
private readonly IWorkshopService _workshopService;
|
||||||
|
private readonly IWorkshopUpdateService _workshopUpdateService;
|
||||||
private readonly IRouter _router;
|
private readonly IRouter _router;
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
private readonly IPluginManagementService _pluginManagementService;
|
private readonly IPluginManagementService _pluginManagementService;
|
||||||
private readonly ISettingsVmFactory _settingsVmFactory;
|
private readonly ISettingsVmFactory _settingsVmFactory;
|
||||||
|
|
||||||
[Notify] private bool _updateAvailable;
|
[Notify] private bool _updateAvailable;
|
||||||
|
[Notify] private bool _autoUpdate;
|
||||||
|
|
||||||
public InstalledTabItemViewModel(InstalledEntry entry,
|
public InstalledTabItemViewModel(InstalledEntry entry,
|
||||||
IWorkshopClient client,
|
IWorkshopClient client,
|
||||||
IWorkshopService workshopService,
|
IWorkshopService workshopService,
|
||||||
|
IWorkshopUpdateService workshopUpdateService,
|
||||||
IRouter router,
|
IRouter router,
|
||||||
IWindowService windowService,
|
IWindowService windowService,
|
||||||
IPluginManagementService pluginManagementService,
|
IPluginManagementService pluginManagementService,
|
||||||
@ -42,10 +47,13 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
|
|||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_workshopService = workshopService;
|
_workshopService = workshopService;
|
||||||
|
_workshopUpdateService = workshopUpdateService;
|
||||||
_router = router;
|
_router = router;
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
_pluginManagementService = pluginManagementService;
|
_pluginManagementService = pluginManagementService;
|
||||||
_settingsVmFactory = settingsVmFactory;
|
_settingsVmFactory = settingsVmFactory;
|
||||||
|
_autoUpdate = entry.AutoUpdate;
|
||||||
|
|
||||||
Entry = entry;
|
Entry = entry;
|
||||||
|
|
||||||
this.WhenActivatedAsync(async _ =>
|
this.WhenActivatedAsync(async _ =>
|
||||||
@ -65,6 +73,8 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
|
|||||||
UpdateAvailable = Entry.ReleaseId != Entry.LatestReleaseId;
|
UpdateAvailable = Entry.ReleaseId != Entry.LatestReleaseId;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.WhenAnyValue(vm => vm.AutoUpdate).Skip(1).Subscribe(_ => AutoUpdateToggled());
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstalledEntry Entry { get; }
|
public InstalledEntry Entry { get; }
|
||||||
@ -108,4 +118,18 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
|
|||||||
PluginViewModel pluginViewModel = _settingsVmFactory.PluginViewModel(plugin, ReactiveCommand.Create(() => { }));
|
PluginViewModel pluginViewModel = _settingsVmFactory.PluginViewModel(plugin, ReactiveCommand.Create(() => { }));
|
||||||
await pluginViewModel.ExecuteRemovePrerequisites(true);
|
await pluginViewModel.ExecuteRemovePrerequisites(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AutoUpdateToggled()
|
||||||
|
{
|
||||||
|
_workshopService.SetAutoUpdate(Entry, AutoUpdate);
|
||||||
|
|
||||||
|
if (!AutoUpdate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await _workshopUpdateService.AutoUpdateEntry(Entry);
|
||||||
|
UpdateAvailable = Entry.ReleaseId != Entry.LatestReleaseId;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
25
src/Artemis.UI/Services/Interfaces/IWorkshopUpdateService.cs
Normal file
25
src/Artemis.UI/Services/Interfaces/IWorkshopUpdateService.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.WebClient.Workshop.Models;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Services.Interfaces;
|
||||||
|
|
||||||
|
public interface IWorkshopUpdateService : IArtemisUIService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Automatically updates all installed entries that have auto-update enabled and have a new version available.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A task that represents the asynchronous operation</returns>
|
||||||
|
Task AutoUpdateEntries();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Automatically updates the provided entry if a new version is available.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entry">The entry to update.</param>
|
||||||
|
/// <returns>A task of <see langword="true"/> if the entry was updated, <see langword="false"/> otherwise.</returns>
|
||||||
|
Task<bool> AutoUpdateEntry(InstalledEntry entry);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disable workshop update notifications.
|
||||||
|
/// </summary>
|
||||||
|
void DisableNotifications();
|
||||||
|
}
|
||||||
@ -57,6 +57,18 @@ public class BasicUpdateNotificationProvider : IUpdateNotificationProvider
|
|||||||
await _router.Navigate("settings/releases");
|
await _router.Navigate("settings/releases");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void ShowWorkshopNotification(int updatedEntries)
|
||||||
|
{
|
||||||
|
_notificationService.CreateNotification()
|
||||||
|
.WithTitle(updatedEntries == 1 ? "Workshop update installed" : "Workshop updates installed")
|
||||||
|
.WithMessage(updatedEntries == 1 ? "A workshop update has been installed" : $"{updatedEntries} workshop updates have been installed")
|
||||||
|
.WithSeverity(NotificationSeverity.Success)
|
||||||
|
.WithTimeout(TimeSpan.FromSeconds(15))
|
||||||
|
.HavingButton(b => b.WithText("View library").WithAction(async () => await _router.Navigate("settings/workshop")))
|
||||||
|
.Show();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void ShowNotification(Guid releaseId, string releaseVersion)
|
public void ShowNotification(Guid releaseId, string releaseVersion)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -4,6 +4,7 @@ namespace Artemis.UI.Services.Updating;
|
|||||||
|
|
||||||
public interface IUpdateNotificationProvider
|
public interface IUpdateNotificationProvider
|
||||||
{
|
{
|
||||||
|
void ShowWorkshopNotification(int updatedEntries);
|
||||||
void ShowNotification(Guid releaseId, string releaseVersion);
|
void ShowNotification(Guid releaseId, string releaseVersion);
|
||||||
void ShowInstalledNotification(string installedVersion);
|
void ShowInstalledNotification(string installedVersion);
|
||||||
}
|
}
|
||||||
@ -8,8 +8,10 @@ using Artemis.Core.Services;
|
|||||||
using Artemis.Storage.Repositories;
|
using Artemis.Storage.Repositories;
|
||||||
using Artemis.Storage.Repositories.Interfaces;
|
using Artemis.Storage.Repositories.Interfaces;
|
||||||
using Artemis.UI.Exceptions;
|
using Artemis.UI.Exceptions;
|
||||||
|
using Artemis.UI.Services.Interfaces;
|
||||||
using Artemis.UI.Shared.Services.MainWindow;
|
using Artemis.UI.Shared.Services.MainWindow;
|
||||||
using Artemis.WebClient.Updating;
|
using Artemis.WebClient.Updating;
|
||||||
|
using Artemis.WebClient.Workshop.Services;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using StrawberryShake;
|
using StrawberryShake;
|
||||||
using Timer = System.Timers.Timer;
|
using Timer = System.Timers.Timer;
|
||||||
@ -26,6 +28,7 @@ public class UpdateService : IUpdateService
|
|||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IMainWindowService _mainWindowService;
|
private readonly IMainWindowService _mainWindowService;
|
||||||
private readonly IReleaseRepository _releaseRepository;
|
private readonly IReleaseRepository _releaseRepository;
|
||||||
|
private readonly IWorkshopUpdateService _workshopUpdateService;
|
||||||
private readonly Lazy<IUpdateNotificationProvider> _updateNotificationProvider;
|
private readonly Lazy<IUpdateNotificationProvider> _updateNotificationProvider;
|
||||||
private readonly Platform _updatePlatform;
|
private readonly Platform _updatePlatform;
|
||||||
private readonly IUpdatingClient _updatingClient;
|
private readonly IUpdatingClient _updatingClient;
|
||||||
@ -38,6 +41,7 @@ public class UpdateService : IUpdateService
|
|||||||
IMainWindowService mainWindowService,
|
IMainWindowService mainWindowService,
|
||||||
IUpdatingClient updatingClient,
|
IUpdatingClient updatingClient,
|
||||||
IReleaseRepository releaseRepository,
|
IReleaseRepository releaseRepository,
|
||||||
|
IWorkshopUpdateService workshopUpdateService,
|
||||||
Lazy<IUpdateNotificationProvider> updateNotificationProvider,
|
Lazy<IUpdateNotificationProvider> updateNotificationProvider,
|
||||||
Func<Guid, ReleaseInstaller> getReleaseInstaller)
|
Func<Guid, ReleaseInstaller> getReleaseInstaller)
|
||||||
{
|
{
|
||||||
@ -45,6 +49,7 @@ public class UpdateService : IUpdateService
|
|||||||
_mainWindowService = mainWindowService;
|
_mainWindowService = mainWindowService;
|
||||||
_updatingClient = updatingClient;
|
_updatingClient = updatingClient;
|
||||||
_releaseRepository = releaseRepository;
|
_releaseRepository = releaseRepository;
|
||||||
|
_workshopUpdateService = workshopUpdateService;
|
||||||
_updateNotificationProvider = updateNotificationProvider;
|
_updateNotificationProvider = updateNotificationProvider;
|
||||||
_getReleaseInstaller = getReleaseInstaller;
|
_getReleaseInstaller = getReleaseInstaller;
|
||||||
|
|
||||||
@ -66,71 +71,6 @@ public class UpdateService : IUpdateService
|
|||||||
timer.Start();
|
timer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessReleaseStatus()
|
|
||||||
{
|
|
||||||
string currentVersion = Constants.CurrentVersion;
|
|
||||||
bool updated = _releaseRepository.SaveVersionInstallDate(currentVersion);
|
|
||||||
PreviousVersion = _releaseRepository.GetPreviousInstalledVersion()?.Version;
|
|
||||||
|
|
||||||
if (!Directory.Exists(Constants.UpdatingFolder))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Clean up the update folder, leaving only the last ZIP
|
|
||||||
foreach (string file in Directory.GetFiles(Constants.UpdatingFolder))
|
|
||||||
{
|
|
||||||
if (Path.GetExtension(file) != ".zip" || Path.GetFileName(file) == $"{currentVersion}.zip")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_logger.Debug("Cleaning up old update file at {FilePath}", file);
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_logger.Warning(e, "Failed to clean up old update file at {FilePath}", file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updated)
|
|
||||||
_updateNotificationProvider.Value.ShowInstalledNotification(currentVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ShowUpdateNotification(IGetNextRelease_NextPublishedRelease release)
|
|
||||||
{
|
|
||||||
_updateNotificationProvider.Value.ShowNotification(release.Id, release.Version);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AutoInstallUpdate(IGetNextRelease_NextPublishedRelease release)
|
|
||||||
{
|
|
||||||
ReleaseInstaller installer = _getReleaseInstaller(release.Id);
|
|
||||||
await installer.InstallAsync(CancellationToken.None);
|
|
||||||
RestartForUpdate("AutoInstallUpdate", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void HandleAutoUpdateEvent(object? sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (Constants.CurrentVersion == "local")
|
|
||||||
return;
|
|
||||||
|
|
||||||
// The event can trigger from multiple sources with a timer acting as a fallback, only actually perform an action once per max 59 minutes
|
|
||||||
if (DateTime.UtcNow - _lastAutoUpdateCheck < TimeSpan.FromMinutes(59))
|
|
||||||
return;
|
|
||||||
_lastAutoUpdateCheck = DateTime.UtcNow;
|
|
||||||
|
|
||||||
if (!_autoCheck.Value || _suspendAutoCheck)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await CheckForUpdate();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.Warning(ex, "Auto update-check failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Channel { get; private set; } = "master";
|
public string Channel { get; private set; } = "master";
|
||||||
|
|
||||||
@ -257,4 +197,86 @@ public class UpdateService : IUpdateService
|
|||||||
_logger.Information("Update service initialized for {Channel} channel", Channel);
|
_logger.Information("Update service initialized for {Channel} channel", Channel);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> AutoCheckForUpdates()
|
||||||
|
{
|
||||||
|
// Don't perform auto-updates if the current version is local
|
||||||
|
if (Constants.CurrentVersion == "local")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Don't perform auto-updates if the setting is disabled or an update was found but not yet installed
|
||||||
|
if (!_autoCheck.Value || _suspendAutoCheck)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await CheckForUpdate() && _autoInstall.Value;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Warning(ex, "Auto update-check failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessReleaseStatus()
|
||||||
|
{
|
||||||
|
string currentVersion = Constants.CurrentVersion;
|
||||||
|
bool updated = _releaseRepository.SaveVersionInstallDate(currentVersion);
|
||||||
|
PreviousVersion = _releaseRepository.GetPreviousInstalledVersion()?.Version;
|
||||||
|
|
||||||
|
if (!Directory.Exists(Constants.UpdatingFolder))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Clean up the update folder, leaving only the last ZIP
|
||||||
|
foreach (string file in Directory.GetFiles(Constants.UpdatingFolder))
|
||||||
|
{
|
||||||
|
if (Path.GetExtension(file) != ".zip" || Path.GetFileName(file) == $"{currentVersion}.zip")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.Debug("Cleaning up old update file at {FilePath}", file);
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Warning(e, "Failed to clean up old update file at {FilePath}", file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updated)
|
||||||
|
_updateNotificationProvider.Value.ShowInstalledNotification(currentVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowUpdateNotification(IGetNextRelease_NextPublishedRelease release)
|
||||||
|
{
|
||||||
|
_updateNotificationProvider.Value.ShowNotification(release.Id, release.Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task AutoInstallUpdate(IGetNextRelease_NextPublishedRelease release)
|
||||||
|
{
|
||||||
|
ReleaseInstaller installer = _getReleaseInstaller(release.Id);
|
||||||
|
await installer.InstallAsync(CancellationToken.None);
|
||||||
|
RestartForUpdate("AutoInstallUpdate", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void HandleAutoUpdateEvent(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
// The event can trigger from multiple sources with a timer acting as a fallback, only actually perform an action once per max 59 minutes
|
||||||
|
if (DateTime.UtcNow - _lastAutoUpdateCheck < TimeSpan.FromMinutes(59))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_lastAutoUpdateCheck = DateTime.UtcNow;
|
||||||
|
|
||||||
|
if (await AutoCheckForUpdates())
|
||||||
|
{
|
||||||
|
_logger.Information("Auto-installing update, not performing workshop update check");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _workshopUpdateService.AutoUpdateEntries();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
89
src/Artemis.UI/Services/Updating/WorkshopUpdateService.cs
Normal file
89
src/Artemis.UI/Services/Updating/WorkshopUpdateService.cs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Services.Interfaces;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Artemis.UI.Shared.Utilities;
|
||||||
|
using Artemis.WebClient.Workshop;
|
||||||
|
using Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
|
||||||
|
using Artemis.WebClient.Workshop.Models;
|
||||||
|
using Artemis.WebClient.Workshop.Services;
|
||||||
|
using Serilog;
|
||||||
|
using StrawberryShake;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Services.Updating;
|
||||||
|
|
||||||
|
public class WorkshopUpdateService : IWorkshopUpdateService
|
||||||
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly IWorkshopClient _client;
|
||||||
|
private readonly INotificationService _notificationService;
|
||||||
|
private readonly IWorkshopService _workshopService;
|
||||||
|
private readonly Lazy<IUpdateNotificationProvider> _updateNotificationProvider;
|
||||||
|
private readonly PluginSetting<bool> _showNotifications;
|
||||||
|
|
||||||
|
public WorkshopUpdateService(ILogger logger, IWorkshopClient client, IWorkshopService workshopService, ISettingsService settingsService,
|
||||||
|
Lazy<IUpdateNotificationProvider> updateNotificationProvider)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_client = client;
|
||||||
|
_workshopService = workshopService;
|
||||||
|
_updateNotificationProvider = updateNotificationProvider;
|
||||||
|
_showNotifications = settingsService.GetSetting("Workshop.ShowNotifications", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AutoUpdateEntries()
|
||||||
|
{
|
||||||
|
_logger.Information("Checking for workshop updates");
|
||||||
|
int checkedEntries = 0;
|
||||||
|
int updatedEntries = 0;
|
||||||
|
|
||||||
|
foreach (InstalledEntry entry in _workshopService.GetInstalledEntries())
|
||||||
|
{
|
||||||
|
if (!entry.AutoUpdate)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
checkedEntries++;
|
||||||
|
bool updated = await AutoUpdateEntry(entry);
|
||||||
|
if (updated)
|
||||||
|
updatedEntries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Information("Checked {CheckedEntries} entries, updated {UpdatedEntries}", checkedEntries, updatedEntries);
|
||||||
|
|
||||||
|
if (updatedEntries > 0 && _showNotifications.Value)
|
||||||
|
_updateNotificationProvider.Value.ShowWorkshopNotification(updatedEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> AutoUpdateEntry(InstalledEntry entry)
|
||||||
|
{
|
||||||
|
// Query the latest version
|
||||||
|
IOperationResult<IGetEntryLatestReleaseByIdResult> latestReleaseResult = await _client.GetEntryLatestReleaseById.ExecuteAsync(entry.Id);
|
||||||
|
|
||||||
|
if (latestReleaseResult.Data?.Entry?.LatestRelease is not IRelease latestRelease)
|
||||||
|
return false;
|
||||||
|
if (latestRelease.Id == entry.ReleaseId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_logger.Information("Auto-updating entry {Entry} to version {Version}", entry, latestRelease.Version);
|
||||||
|
|
||||||
|
EntryInstallResult updateResult = await _workshopService.InstallEntry(entry, latestRelease, new Progress<StreamProgress>(), CancellationToken.None);
|
||||||
|
|
||||||
|
// This happens during installation too but not on our reference of the entry
|
||||||
|
if (updateResult.IsSuccess)
|
||||||
|
entry.ApplyRelease(latestRelease);
|
||||||
|
|
||||||
|
_logger.Information("Auto-update result: {Result}", updateResult);
|
||||||
|
|
||||||
|
return updateResult.IsSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void DisableNotifications()
|
||||||
|
{
|
||||||
|
_showNotifications.Value = false;
|
||||||
|
_showNotifications.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -26,4 +26,10 @@ public class EntryInstallResult
|
|||||||
Entry = installedEntry
|
Entry = installedEntry
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{nameof(IsSuccess)}: {IsSuccess}, {nameof(Message)}: {Message}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ public class PluginEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
{
|
{
|
||||||
// If the folder already exists, we're not going to reinstall the plugin since files may be in use, consider our job done
|
// If the folder already exists, we're not going to reinstall the plugin since files may be in use, consider our job done
|
||||||
if (installedEntry.GetReleaseDirectory(release).Exists)
|
if (installedEntry.GetReleaseDirectory(release).Exists)
|
||||||
return EntryInstallResult.FromSuccess(installedEntry);
|
return ApplyAndSave(installedEntry, release);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -102,10 +102,7 @@ public class PluginEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
return EntryInstallResult.FromFailure(e.Message);
|
return EntryInstallResult.FromFailure(e.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
installedEntry.ApplyRelease(release);
|
return ApplyAndSave(installedEntry, release);
|
||||||
|
|
||||||
_workshopService.SaveInstalledEntry(installedEntry);
|
|
||||||
return EntryInstallResult.FromSuccess(installedEntry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<EntryUninstallResult> UninstallAsync(InstalledEntry installedEntry, CancellationToken cancellationToken)
|
public Task<EntryUninstallResult> UninstallAsync(InstalledEntry installedEntry, CancellationToken cancellationToken)
|
||||||
@ -135,4 +132,11 @@ public class PluginEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
_workshopService.RemoveInstalledEntry(installedEntry);
|
_workshopService.RemoveInstalledEntry(installedEntry);
|
||||||
return Task.FromResult(EntryUninstallResult.FromSuccess(message));
|
return Task.FromResult(EntryUninstallResult.FromSuccess(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private EntryInstallResult ApplyAndSave(InstalledEntry installedEntry, IRelease release)
|
||||||
|
{
|
||||||
|
installedEntry.ApplyRelease(release);
|
||||||
|
_workshopService.SaveInstalledEntry(installedEntry);
|
||||||
|
return EntryInstallResult.FromSuccess(installedEntry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -18,6 +18,9 @@ public class InstalledEntry : CorePropertyChanged, IEntrySummary
|
|||||||
private DateTimeOffset _createdAt;
|
private DateTimeOffset _createdAt;
|
||||||
private long? _latestReleaseId;
|
private long? _latestReleaseId;
|
||||||
private IReadOnlyList<IGetDependantEntries_Entries_Items_Categories> _categories;
|
private IReadOnlyList<IGetDependantEntries_Entries_Items_Categories> _categories;
|
||||||
|
private long _releaseId;
|
||||||
|
private string _releaseVersion = string.Empty;
|
||||||
|
private bool _autoUpdate;
|
||||||
|
|
||||||
internal InstalledEntry(EntryEntity entity)
|
internal InstalledEntry(EntryEntity entity)
|
||||||
{
|
{
|
||||||
@ -36,12 +39,26 @@ public class InstalledEntry : CorePropertyChanged, IEntrySummary
|
|||||||
AutoUpdate = true;
|
AutoUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long ReleaseId { get; set; }
|
|
||||||
public string ReleaseVersion { get; set; } = string.Empty;
|
|
||||||
public DateTimeOffset InstalledAt { get; set; }
|
|
||||||
public bool AutoUpdate { get; set; }
|
|
||||||
|
|
||||||
internal EntryEntity Entity { get; }
|
internal EntryEntity Entity { get; }
|
||||||
|
public DateTimeOffset InstalledAt { get; set; }
|
||||||
|
|
||||||
|
public long ReleaseId
|
||||||
|
{
|
||||||
|
get => _releaseId;
|
||||||
|
set => SetAndNotify(ref _releaseId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReleaseVersion
|
||||||
|
{
|
||||||
|
get => _releaseVersion;
|
||||||
|
set => SetAndNotify(ref _releaseVersion, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AutoUpdate
|
||||||
|
{
|
||||||
|
get => _autoUpdate;
|
||||||
|
set => SetAndNotify(ref _autoUpdate, value);
|
||||||
|
}
|
||||||
|
|
||||||
internal void Load()
|
internal void Load()
|
||||||
{
|
{
|
||||||
@ -233,4 +250,10 @@ public class InstalledEntry : CorePropertyChanged, IEntrySummary
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"[{EntryType}] {Id} - {Name}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -33,3 +33,11 @@ query GetEntrySummaryById($id: Long!) {
|
|||||||
...entrySummary
|
...entrySummary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query GetEntryLatestReleaseById($id: Long!) {
|
||||||
|
entry(id: $id) {
|
||||||
|
latestRelease {
|
||||||
|
...releaseDetails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -134,4 +134,5 @@ public interface IWorkshopService
|
|||||||
public event EventHandler<InstalledEntry>? OnEntryUninstalled;
|
public event EventHandler<InstalledEntry>? OnEntryUninstalled;
|
||||||
public event EventHandler<InstalledEntry>? OnEntryInstalled;
|
public event EventHandler<InstalledEntry>? OnEntryInstalled;
|
||||||
|
|
||||||
|
void SetAutoUpdate(InstalledEntry installedEntry, bool autoUpdate);
|
||||||
}
|
}
|
||||||
@ -165,7 +165,7 @@ public class WorkshopService : IWorkshopService
|
|||||||
if (result.IsSuccess && result.Entry != null)
|
if (result.IsSuccess && result.Entry != null)
|
||||||
OnEntryInstalled?.Invoke(this, result.Entry);
|
OnEntryInstalled?.Invoke(this, result.Entry);
|
||||||
else
|
else
|
||||||
_logger.Warning("Failed to install entry {EntryId}: {Message}", entry.Id, result.Message);
|
_logger.Warning("Failed to install entry {Entry}: {Message}", entry, result.Message);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -254,6 +254,16 @@ public class WorkshopService : IWorkshopService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void SetAutoUpdate(InstalledEntry installedEntry, bool autoUpdate)
|
||||||
|
{
|
||||||
|
if (installedEntry.AutoUpdate == autoUpdate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
installedEntry.AutoUpdate = autoUpdate;
|
||||||
|
SaveInstalledEntry(installedEntry);
|
||||||
|
}
|
||||||
|
|
||||||
private void RemoveOrphanedFiles()
|
private void RemoveOrphanedFiles()
|
||||||
{
|
{
|
||||||
List<InstalledEntry> entries = GetInstalledEntries();
|
List<InstalledEntry> entries = GetInstalledEntries();
|
||||||
@ -308,6 +318,8 @@ public class WorkshopService : IWorkshopService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<InstalledEntry>? OnInstalledEntrySaved;
|
public event EventHandler<InstalledEntry>? OnInstalledEntrySaved;
|
||||||
|
|
||||||
public event EventHandler<InstalledEntry>? OnEntryUninstalled;
|
public event EventHandler<InstalledEntry>? OnEntryUninstalled;
|
||||||
|
|
||||||
public event EventHandler<InstalledEntry>? OnEntryInstalled;
|
public event EventHandler<InstalledEntry>? OnEntryInstalled;
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user