1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00
Artemis/src/Artemis.UI/Screens/Settings/Updating/ReleaseDetailsViewModel.cs
RobertBeekman 962b13c6ed
UI - Added routing (#802)
ColorGradient - Fixed GetColor returning the first stop if position was after the last stop
2023-07-02 22:15:38 +02:00

195 lines
6.4 KiB
C#

using System;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.UI.Services.Updating;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.Builders;
using Artemis.WebClient.Updating;
using ReactiveUI;
using Serilog;
using StrawberryShake;
namespace Artemis.UI.Screens.Settings.Updating;
public class ReleaseDetailsViewModel : RoutableScreen<ViewModelBase, ReleaseDetailsViewModelParameters>
{
private readonly ObservableAsPropertyHelper<long> _fileSize;
private readonly ILogger _logger;
private readonly INotificationService _notificationService;
private readonly IUpdateService _updateService;
private readonly IUpdatingClient _updatingClient;
private bool _installationAvailable;
private bool _installationFinished;
private bool _installationInProgress;
private CancellationTokenSource? _installerCts;
private bool _loading = true;
private IGetReleaseById_PublishedRelease? _release;
private ReleaseInstaller? _releaseInstaller;
public ReleaseDetailsViewModel(ILogger logger, IUpdatingClient updatingClient, INotificationService notificationService, IUpdateService updateService)
{
_logger = logger;
_updatingClient = updatingClient;
_notificationService = notificationService;
_updateService = updateService;
Platform updatePlatform;
if (OperatingSystem.IsWindows())
updatePlatform = Platform.Windows;
else if (OperatingSystem.IsLinux())
updatePlatform = Platform.Linux;
else if (OperatingSystem.IsMacOS())
updatePlatform = Platform.Osx;
else
throw new PlatformNotSupportedException("Cannot auto update on the current platform");
Install = ReactiveCommand.CreateFromTask(ExecuteInstall);
Restart = ReactiveCommand.Create(ExecuteRestart);
CancelInstall = ReactiveCommand.Create(() => _installerCts?.Cancel());
_fileSize = this.WhenAnyValue(vm => vm.Release)
.Select(release => release?.Artifacts.FirstOrDefault(a => a.Platform == updatePlatform)?.FileInfo.DownloadSize ?? 0)
.ToProperty(this, vm => vm.FileSize);
this.WhenActivated(d => Disposable.Create(_installerCts, cts => cts?.Cancel()).DisposeWith(d));
}
public ReactiveCommand<Unit, Unit> Restart { get; }
public ReactiveCommand<Unit, Unit> Install { get; }
public ReactiveCommand<Unit, Unit> CancelInstall { get; }
public long FileSize => _fileSize.Value;
public IGetReleaseById_PublishedRelease? Release
{
get => _release;
set => RaiseAndSetIfChanged(ref _release, value);
}
public ReleaseInstaller? ReleaseInstaller
{
get => _releaseInstaller;
set => RaiseAndSetIfChanged(ref _releaseInstaller, value);
}
public bool Loading
{
get => _loading;
private set => RaiseAndSetIfChanged(ref _loading, value);
}
public bool InstallationAvailable
{
get => _installationAvailable;
set => RaiseAndSetIfChanged(ref _installationAvailable, value);
}
public bool InstallationInProgress
{
get => _installationInProgress;
set => RaiseAndSetIfChanged(ref _installationInProgress, value);
}
public bool InstallationFinished
{
get => _installationFinished;
set => RaiseAndSetIfChanged(ref _installationFinished, value);
}
public void NavigateToSource()
{
if (Release != null)
Utilities.OpenUrl($"https://github.com/Artemis-RGB/Artemis/commit/{Release.Commit}");
}
/// <inheritdoc />
public override async Task OnNavigating(ReleaseDetailsViewModelParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
{
// There's no point in running anything but the latest version of the current channel.
// Perhaps later that won't be true anymore, then we could consider allowing to install
// older versions with compatible database versions.
InstallationAvailable = _updateService.CachedLatestRelease?.Id == parameters.ReleaseId;
await RetrieveDetails(parameters.ReleaseId, cancellationToken);
ReleaseInstaller = _updateService.GetReleaseInstaller(parameters.ReleaseId);
}
private void ExecuteRestart()
{
_updateService.RestartForUpdate(false);
}
private async Task ExecuteInstall(CancellationToken cancellationToken)
{
if (ReleaseInstaller == null)
return;
_installerCts = new CancellationTokenSource();
try
{
InstallationInProgress = true;
await ReleaseInstaller.InstallAsync(_installerCts.Token);
InstallationFinished = true;
}
catch (Exception e)
{
if (_installerCts.IsCancellationRequested)
return;
_logger.Warning(e, "Failed to install update through UI");
_notificationService.CreateNotification()
.WithTitle("Failed to install update")
.WithMessage(e.Message)
.WithSeverity(NotificationSeverity.Warning)
.Show();
}
finally
{
InstallationInProgress = false;
}
}
private async Task RetrieveDetails(Guid releaseId, CancellationToken cancellationToken)
{
try
{
Loading = true;
IOperationResult<IGetReleaseByIdResult> result = await _updatingClient.GetReleaseById.ExecuteAsync(releaseId, cancellationToken);
IGetReleaseById_PublishedRelease? release = result.Data?.PublishedRelease;
if (release == null)
return;
Release = release;
}
catch (TaskCanceledException)
{
// ignored
}
catch (Exception e)
{
_logger.Warning(e, "Failed to retrieve release details");
_notificationService.CreateNotification()
.WithTitle("Failed to retrieve details")
.WithMessage(e.Message)
.WithSeverity(NotificationSeverity.Warning)
.Show();
}
finally
{
Loading = false;
}
}
}
public class ReleaseDetailsViewModelParameters
{
public Guid ReleaseId { get; set; }
}