Browse Source

Actually check for updates & launch button fixes

pull/109/head
JT 1 year ago
parent
commit
2632c85ead
  1. 5
      StabilityMatrix.Avalonia/DesignData/DesignData.cs
  2. 1
      StabilityMatrix.Avalonia/Program.cs
  3. 10
      StabilityMatrix.Avalonia/Services/ServiceManager.cs
  4. 2
      StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs
  5. 6
      StabilityMatrix.Avalonia/ViewModels/LaunchPageViewModel.cs
  6. 47
      StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs
  7. 55
      StabilityMatrix.Avalonia/ViewModels/PackageManagerViewModel.cs
  8. 27
      StabilityMatrix.Avalonia/Views/PackageManagerPage.axaml
  9. 1
      StabilityMatrix.Core/Database/LiteDbContext.cs

5
StabilityMatrix.Avalonia/DesignData/DesignData.cs

@ -11,6 +11,7 @@ using StabilityMatrix.Avalonia.Models;
using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels;
using StabilityMatrix.Avalonia.ViewModels.Dialogs;
using StabilityMatrix.Avalonia.ViewModels.PackageManager;
using StabilityMatrix.Core.Api;
using StabilityMatrix.Core.Database;
using StabilityMatrix.Core.Helper;
@ -254,7 +255,11 @@ public static class DesignData
{
get
{
var settings = Services.GetRequiredService<ISettingsManager>();
var vm = Services.GetRequiredService<PackageManagerViewModel>();
vm.Packages = new ObservableCollection<PackageCardViewModel>(
settings.Settings.InstalledPackages.Select(p =>
DialogFactory.Get<PackageCardViewModel>(viewModel => viewModel.Package = p)));
vm.Packages.First().IsUpdateAvailable = true;
return vm;
}

1
StabilityMatrix.Avalonia/Program.cs

@ -12,7 +12,6 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Threading;
using Microsoft.Extensions.DependencyInjection;
using NLog;
using Polly.Contrib.WaitAndRetry;
using Projektanker.Icons.Avalonia;

10
StabilityMatrix.Avalonia/Services/ServiceManager.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
namespace StabilityMatrix.Avalonia.Services;
@ -129,4 +130,13 @@ public class ServiceManager<T>
initializer(instance);
return instance;
}
/// <summary>
/// Get a view model instance with an initializer parameter, but asynchronously
/// </summary>
public async Task<TService> GetAsync<TService>(Func<TService, Task<TService>> initializer) where TService : T
{
var instance = Get<TService>();
return await initializer(instance);
}
}

2
StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs

@ -6,7 +6,6 @@ using System.Threading.Tasks;
using AsyncAwaitBestPractices;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Python.Runtime;
using StabilityMatrix.Avalonia.Views.Dialogs;
using StabilityMatrix.Core.Attributes;
using StabilityMatrix.Core.Helper;
@ -14,7 +13,6 @@ using StabilityMatrix.Core.Models.Progress;
using StabilityMatrix.Core.Models.Update;
using StabilityMatrix.Core.Services;
using StabilityMatrix.Core.Updater;
using Dispatcher = Avalonia.Threading.Dispatcher;
namespace StabilityMatrix.Avalonia.ViewModels.Dialogs;

6
StabilityMatrix.Avalonia/ViewModels/LaunchPageViewModel.cs

@ -135,10 +135,8 @@ public partial class LaunchPageViewModel : PageViewModelBase, IDisposable, IAsyn
NotificationType.Error);
return;
}
OnLoaded();
if (SelectedPackage is null) return;
SelectedPackage = InstalledPackages.FirstOrDefault(x => x.Id == e);
LaunchAsync().SafeFireAndForget();
}

47
StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs

@ -1,7 +1,10 @@
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using AsyncAwaitBestPractices;
using Avalonia.Controls.Notifications;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using FluentAvalonia.UI.Controls;
using NLog;
@ -25,6 +28,7 @@ public partial class PackageCardViewModel : ProgressViewModel
[ObservableProperty] private InstalledPackage? package;
[ObservableProperty] private Uri cardImage;
[ObservableProperty] private bool isUpdateAvailable;
[ObservableProperty] private string installedVersion;
public PackageCardViewModel(IPackageFactory packageFactory,
INotificationService notificationService, ISettingsManager settingsManager)
@ -41,6 +45,12 @@ public partial class PackageCardViewModel : ProgressViewModel
var basePackage = packageFactory[value.PackageName];
CardImage = basePackage?.PreviewImageUri ?? Assets.NoImage;
InstalledVersion = value.DisplayVersion ?? "Unknown";
}
public override async Task OnLoadedAsync()
{
IsUpdateAvailable = await HasUpdate();
}
public void Launch()
@ -49,7 +59,6 @@ public partial class PackageCardViewModel : ProgressViewModel
return;
settingsManager.Transaction(s => s.ActiveInstalledPackageId = Package.Id);
EventManager.Instance.RequestPageChange(typeof(LaunchPageViewModel));
EventManager.Instance.OnPackageLaunchRequested(Package.Id);
}
@ -100,7 +109,7 @@ public partial class PackageCardViewModel : ProgressViewModel
public async Task Update()
{
if (Package == null) return;
var basePackage = packageFactory.FindPackageByName(Package.PackageName);
var basePackage = packageFactory[Package.PackageName!];
if (basePackage == null)
{
logger.Error("Could not find package {SelectedPackagePackageName}",
@ -108,7 +117,7 @@ public partial class PackageCardViewModel : ProgressViewModel
return;
}
Text = $"Updating {Package.DisplayName} to latest version...";
Text = $"Updating {Package.DisplayName}";
basePackage.InstallLocation = Package.FullPath!;
var progress = new Progress<ProgressReport>(progress =>
{
@ -116,7 +125,7 @@ public partial class PackageCardViewModel : ProgressViewModel
Value = percent;
IsIndeterminate = progress.IsIndeterminate;
Text = $"Updating {Package.DisplayName} to latest version... {percent:N0}%";
Text = $"Updating {Package.DisplayName}";
EventManager.Instance.OnGlobalProgressChanged(percent);
});
@ -146,6 +155,10 @@ public partial class PackageCardViewModel : ProgressViewModel
Package.UpdateAvailable = false;
IsUpdateAvailable = false;
IsIndeterminate = false;
InstalledVersion = settingsManager.Settings.InstalledPackages
.First(x => x.Id == Package.Id).DisplayVersion ?? "Unknown";
Value = 0;
}
/// <summary>
@ -232,19 +245,23 @@ public partial class PackageCardViewModel : ProgressViewModel
var basePackage = packageFactory[Package.PackageName!];
if (basePackage == null) return false;
var canCheckUpdate = Package.LastUpdateCheck == null ||
var canCheckUpdate = Package.LastUpdateCheck == null ||
Package.LastUpdateCheck < DateTime.Now.AddMinutes(-15);
if (!canCheckUpdate) return false;
var hasUpdate = await basePackage.CheckForUpdates(Package);
Package.UpdateAvailable = hasUpdate;
Package.LastUpdateCheck = DateTimeOffset.Now;
IsUpdateAvailable = true;
settingsManager.SetLastUpdateCheck(Package);
return hasUpdate;
if (!canCheckUpdate) return false;
try
{
var hasUpdate = await basePackage.CheckForUpdates(Package);
Package.UpdateAvailable = hasUpdate;
Package.LastUpdateCheck = DateTimeOffset.Now;
settingsManager.SetLastUpdateCheck(Package);
return hasUpdate;
}
catch (Exception e)
{
return false;
}
}
}

55
StabilityMatrix.Avalonia/ViewModels/PackageManagerViewModel.cs

@ -1,18 +1,12 @@
using System;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using AsyncAwaitBestPractices;
using Avalonia.Controls;
using Avalonia.Controls.Notifications;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using FluentAvalonia.UI.Controls;
using Microsoft.Extensions.Logging;
using Polly;
using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Dialogs;
@ -22,9 +16,6 @@ using StabilityMatrix.Avalonia.Views.Dialogs;
using StabilityMatrix.Core.Attributes;
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Helper.Factory;
using StabilityMatrix.Core.Models;
using StabilityMatrix.Core.Models.Packages;
using StabilityMatrix.Core.Models.Progress;
using StabilityMatrix.Core.Services;
using Symbol = FluentIcons.Common.Symbol;
using SymbolIconSource = FluentIcons.FluentAvalonia.SymbolIconSource;
@ -38,28 +29,16 @@ namespace StabilityMatrix.Avalonia.ViewModels;
[View(typeof(PackageManagerPage))]
public partial class PackageManagerViewModel : PageViewModelBase
{
private readonly ILogger<PackageManagerViewModel> logger;
private readonly ISettingsManager settingsManager;
private readonly IPackageFactory packageFactory;
private readonly INotificationService notificationService;
private readonly ServiceManager<ViewModelBase> dialogFactory;
private const int MinutesToWaitForUpdateCheck = 60;
public PackageManagerViewModel(ILogger<PackageManagerViewModel> logger,
ISettingsManager settingsManager, IPackageFactory packageFactory,
INotificationService notificationService, ServiceManager<ViewModelBase> dialogFactory)
public PackageManagerViewModel(ISettingsManager settingsManager, IPackageFactory packageFactory,
ServiceManager<ViewModelBase> dialogFactory)
{
this.logger = logger;
this.settingsManager = settingsManager;
this.packageFactory = packageFactory;
this.notificationService = notificationService;
this.dialogFactory = dialogFactory;
Packages =
new ObservableCollection<PackageCardViewModel>(
settingsManager.Settings.InstalledPackages.Select(p =>
dialogFactory.Get<PackageCardViewModel>(vm => vm.Package = p)));
EventManager.Instance.InstalledPackagesChanged += OnInstalledPackagesChanged;
}
@ -70,15 +49,25 @@ public partial class PackageManagerViewModel : PageViewModelBase
public override bool CanNavigatePrevious { get; protected set; }
public override string Title => "Packages";
public override IconSource IconSource => new SymbolIconSource { Symbol = Symbol.Box, IsFilled = true};
public override void OnLoaded()
public override async Task OnLoadedAsync()
{
Packages =
new ObservableCollection<PackageCardViewModel>(
settingsManager.Settings.InstalledPackages.Select(p =>
dialogFactory.Get<PackageCardViewModel>(vm => vm.Package = p)));
if (Design.IsDesignMode) return;
var installedPackages = settingsManager.Settings.InstalledPackages;
Packages = new ObservableCollection<PackageCardViewModel>(installedPackages.Select(
package => dialogFactory.Get<PackageCardViewModel>(vm =>
{
vm.Package = package;
return vm;
})));
foreach (var package in Packages)
{
await package.OnLoadedAsync();
}
}
public async Task ShowInstallDialog()
{
var viewModel = dialogFactory.Get<InstallerViewModel>();
@ -100,8 +89,8 @@ public partial class PackageManagerViewModel : PageViewModelBase
};
await dialog.ShowAsync();
OnLoaded();
await OnLoadedAsync();
}
private void OnInstalledPackagesChanged(object? sender, EventArgs e) => OnLoaded();
private void OnInstalledPackagesChanged(object? sender, EventArgs e) =>OnLoaded();
}

27
StabilityMatrix.Avalonia/Views/PackageManagerPage.axaml

@ -29,15 +29,16 @@
<TextBlock Grid.Row="0"
Grid.Column="0"
Margin="0,4,4,4"
Text="{Binding Package.DisplayName}"
TextAlignment="Left" />
<Button
Grid.Row="0"
Grid.RowSpan="2"
HorizontalContentAlignment="Right"
HorizontalAlignment="Right"
Margin="8,4,0,4"
Margin="8,-8,0,4"
Classes="transparent"
Width="24"
BorderThickness="0">
<ui:SymbolIcon FontSize="18" Symbol="MoreVertical" />
<Button.Flyout>
@ -60,9 +61,9 @@
<TextBlock Grid.Row="1"
Grid.Column="0"
Margin="2,-8,0,0"
Margin="2,0,0,0"
VerticalAlignment="Center"
Text="{Binding Package.DisplayVersion}" />
Text="{Binding InstalledVersion}" />
<controls:BetterAdvancedImage
Grid.Row="2"
@ -93,7 +94,8 @@
</Button>
<Button Grid.Column="1" Classes="accent"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch">
HorizontalAlignment="Stretch"
Command="{Binding Update}">
<StackPanel Orientation="Horizontal" Margin="0,2,0,2">
<faicon:Icon Value="fa-solid fa-download"
Margin="0,0,8,0"
@ -125,11 +127,11 @@
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsVisible="{Binding IsProgressVisible}" />
<StackPanel Grid.Row="0" Grid.RowSpan="4"
<Grid Grid.Row="0" Grid.RowSpan="4"
Grid.Column="0"
HorizontalAlignment="Stretch"
Orientation="Vertical"
VerticalAlignment="Center"
RowDefinitions="Auto, *"
IsVisible="{Binding IsProgressVisible}">
<controls:ProgressRing
HorizontalAlignment="Center"
@ -140,12 +142,15 @@
EndAngle="450"
Value="{Binding Value}"
VerticalAlignment="Center" />
<TextBlock
<TextBlock Grid.Row="1"
HorizontalAlignment="Center"
Margin="0,8,0,0"
Text="{Binding Text, TargetNullValue=Updating...}"
Margin="8,8,8,0"
TextAlignment="Center"
Width="180"
Text="{Binding Text, TargetNullValue=Updating so and so to the latest version... 5%}"
TextWrapping="Wrap"
VerticalAlignment="Center" />
</StackPanel>
</Grid>
</Grid>
</controls:Card>
</DataTemplate>

1
StabilityMatrix.Core/Database/LiteDbContext.cs

@ -115,7 +115,6 @@ public class LiteDbContext : ILiteDbContext
public void Dispose()
{
database?.UnderlyingDatabase.Dispose();
database?.Dispose();
GC.SuppressFinalize(this);
}

Loading…
Cancel
Save