1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2026-03-25 18:58:48 +00:00
Artemis/src/Artemis.UI/Screens/Workshop/EntryReleases/EntryReleaseInfoViewModel.cs
Robert 648b7765ef Core - Added API for retrieving current suspended device providers
Core - Added events for plugin removal, entry installlation/uninstallation
Workshop - Remove the related workshop entry when manually removing a plugin or profile
Workshop - Prevent installing profiles with missing plugins and show a dialog with which plugins are missing
2024-06-30 09:42:41 +02:00

184 lines
6.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.DryIoc.Factories;
using Artemis.UI.Screens.Plugins;
using Artemis.UI.Screens.Workshop.EntryReleases.Dialogs;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.Builders;
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 PropertyChanged.SourceGenerator;
using ReactiveUI;
namespace Artemis.UI.Screens.Workshop.EntryReleases;
public partial class EntryReleaseInfoViewModel : ActivatableViewModelBase
{
private readonly IRouter _router;
private readonly INotificationService _notificationService;
private readonly IWindowService _windowService;
private readonly IWorkshopService _workshopService;
private readonly IPluginManagementService _pluginManagementService;
private readonly ISettingsVmFactory _settingsVmFactory;
private readonly Progress<StreamProgress> _progress = new();
[Notify] private IReleaseDetails? _release;
[Notify] private float _installProgress;
[Notify] private bool _isCurrentVersion;
[Notify] private bool _installationInProgress;
[Notify] private bool _inDetailsScreen;
private CancellationTokenSource? _cts;
public EntryReleaseInfoViewModel(IRouter router,
INotificationService notificationService,
IWindowService windowService,
IWorkshopService workshopService,
IPluginManagementService pluginManagementService,
ISettingsVmFactory settingsVmFactory)
{
_router = router;
_notificationService = notificationService;
_windowService = windowService;
_workshopService = workshopService;
_pluginManagementService = pluginManagementService;
_settingsVmFactory = settingsVmFactory;
_progress.ProgressChanged += (_, f) => InstallProgress = f.ProgressPercentage;
this.WhenActivated(d =>
{
_workshopService.OnEntryInstalled += WorkshopServiceOnOnEntryInstalled;
_workshopService.OnEntryUninstalled += WorkshopServiceOnOnEntryInstalled;
Disposable.Create(() =>
{
_workshopService.OnEntryInstalled -= WorkshopServiceOnOnEntryInstalled;
_workshopService.OnEntryUninstalled -= WorkshopServiceOnOnEntryInstalled;
}).DisposeWith(d);
IsCurrentVersion = Release != null && _workshopService.GetInstalledEntry(Release.Entry.Id)?.ReleaseId == Release.Id;
});
this.WhenAnyValue(vm => vm.Release).Subscribe(r => IsCurrentVersion = r != null && _workshopService.GetInstalledEntry(r.Entry.Id)?.ReleaseId == r.Id);
InDetailsScreen = true;
}
private void WorkshopServiceOnOnEntryInstalled(object? sender, InstalledEntry e)
{
IsCurrentVersion = Release != null && _workshopService.GetInstalledEntry(Release.Entry.Id)?.ReleaseId == Release.Id;
}
public async Task Close()
{
await _router.GoUp();
}
public async Task Install()
{
if (Release == null)
return;
// If the entry has missing dependencies, show a dialog
List<IEntrySummary> missing = Release.Dependencies.Where(d => _workshopService.GetInstalledEntry(d.Id) == null).Cast<IEntrySummary>().ToList();
if (missing.Count > 0)
{
await _windowService.CreateContentDialog()
.WithTitle("Requirements missing")
.WithViewModel(out DependenciesDialogViewModel _, Release.Entry, missing)
.WithCloseButtonText("Cancel installation")
.ShowAsync();
return;
}
_cts = new CancellationTokenSource();
InstallProgress = 0;
InstallationInProgress = true;
try
{
EntryInstallResult result = await _workshopService.InstallEntry(Release.Entry, Release, _progress, _cts.Token);
if (result.IsSuccess)
{
_notificationService.CreateNotification().WithTitle("Installation succeeded").WithSeverity(NotificationSeverity.Success).Show();
InstallationInProgress = false;
await Manage();
}
else if (!_cts.IsCancellationRequested)
_notificationService.CreateNotification().WithTitle("Installation failed").WithMessage(result.Message).WithSeverity(NotificationSeverity.Error).Show();
}
catch (Exception e)
{
_windowService.ShowExceptionDialog("Failed to install workshop entry", e);
}
finally
{
InstallationInProgress = false;
}
}
public async Task Manage()
{
if (Release?.Entry.EntryType != EntryType.Profile)
await _router.Navigate("../../manage", new RouterNavigationOptions {AdditionalArguments = true});
}
public async Task Reinstall()
{
if (await _windowService.ShowConfirmContentDialog("Reinstall entry", "Are you sure you want to reinstall this entry?"))
await Install();
}
public async Task Uninstall()
{
InstalledEntry? installedEntry = _workshopService.GetInstalledEntry(Release!.Entry.Id);
if (installedEntry == null)
return;
InstallationInProgress = true;
try
{
bool confirmed = await _windowService.ShowConfirmContentDialog("Do you want to uninstall this entry?", "Both the entry and its contents will be removed.");
if (!confirmed)
return;
// Ideally the installation handler does this but it doesn't have access to the required view models
if (installedEntry.EntryType == EntryType.Plugin)
await UninstallPluginPrerequisites(installedEntry);
await _workshopService.UninstallEntry(installedEntry, CancellationToken.None);
_notificationService.CreateNotification().WithTitle("Entry uninstalled").WithSeverity(NotificationSeverity.Success).Show();
}
finally
{
InstallationInProgress = false;
}
}
public void Cancel()
{
_cts?.Cancel();
}
private async Task UninstallPluginPrerequisites(InstalledEntry installedEntry)
{
if (!installedEntry.TryGetMetadata("PluginId", out Guid pluginId))
return;
Plugin? plugin = _pluginManagementService.GetAllPlugins().FirstOrDefault(p => p.Guid == pluginId);
if (plugin == null)
return;
PluginViewModel pluginViewModel = _settingsVmFactory.PluginViewModel(plugin, ReactiveCommand.Create(() => { }));
await pluginViewModel.ExecuteRemovePrerequisites(true);
}
}