Browse Source

added non-blocking package runner option to show new dialog that doesnt exist yet

also fixed env vars not being editable in release mode
also added api stuff for recommended models dialog (that doesnt exist yet)
pull/438/head
JT 10 months ago
parent
commit
abe631df13
  1. 11
      StabilityMatrix.Avalonia/DesignData/DesignData.cs
  2. 1
      StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
  3. 104
      StabilityMatrix.Avalonia/ViewModels/Dialogs/NewOneClickInstallViewModel.cs
  4. 14
      StabilityMatrix.Avalonia/ViewModels/Dialogs/RecommendedModelsViewModel.cs
  5. 22
      StabilityMatrix.Avalonia/ViewModels/Progress/PackageInstallProgressItemViewModel.cs
  6. 19
      StabilityMatrix.Avalonia/ViewModels/Progress/ProgressManagerViewModel.cs
  7. 6
      StabilityMatrix.Avalonia/Views/Dialogs/NewOneClickInstallDialog.axaml
  8. 3
      StabilityMatrix.Core/Api/ICivitApi.cs
  9. 10
      StabilityMatrix.Core/Api/ILykosAuthApi.cs
  10. 16
      StabilityMatrix.Core/Helper/EventManager.cs
  11. 7
      StabilityMatrix.Core/Models/Api/Lykos/GetRecommendedModelsResponse.cs

11
StabilityMatrix.Avalonia/DesignData/DesignData.cs

@ -404,7 +404,8 @@ public static class DesignData
new PackageModificationRunner new PackageModificationRunner
{ {
CurrentProgress = new ProgressReport(0.5f, "Installing package...") CurrentProgress = new ProgressReport(0.5f, "Installing package...")
} },
new List<IPackageStep>()
) )
} }
); );
@ -493,6 +494,14 @@ public static class DesignData
{ {
vm.AddExtensions( vm.AddExtensions(
[ [
new PackageExtension
{
Author = "123",
Title = "Cool Extension",
Description = "This is an interesting extension",
Reference = new Uri("https://github.com/LykosAI/StabilityMatrix"),
Files = [new Uri("https://github.com/LykosAI/StabilityMatrix")]
},
new PackageExtension new PackageExtension
{ {
Author = "123", Author = "123",

1
StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj

@ -33,6 +33,7 @@
<PackageReference Include="AsyncImageLoader.Avalonia" Version="3.2.1" /> <PackageReference Include="AsyncImageLoader.Avalonia" Version="3.2.1" />
<PackageReference Include="AutoComplete.Net" Version="1.2211.2014.42"/> <PackageReference Include="AutoComplete.Net" Version="1.2211.2014.42"/>
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.0.6" /> <PackageReference Include="Avalonia.AvaloniaEdit" Version="11.0.6" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.0.7" />
<PackageReference Include="Avalonia.Controls.PanAndZoom" Version="11.0.0.2" /> <PackageReference Include="Avalonia.Controls.PanAndZoom" Version="11.0.0.2" />
<PackageReference Include="Avalonia" Version="11.0.7" /> <PackageReference Include="Avalonia" Version="11.0.7" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.7" /> <PackageReference Include="Avalonia.Desktop" Version="11.0.7" />

104
StabilityMatrix.Avalonia/ViewModels/Dialogs/NewOneClickInstallViewModel.cs

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.IO;
using System.Linq; using System.Linq;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -7,11 +9,19 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using DynamicData; using DynamicData;
using DynamicData.Binding; using DynamicData.Binding;
using Microsoft.Extensions.Logging;
using StabilityMatrix.Avalonia.ViewModels.Base; using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Avalonia.Views.Dialogs; using StabilityMatrix.Avalonia.Views.Dialogs;
using StabilityMatrix.Core.Attributes; using StabilityMatrix.Core.Attributes;
using StabilityMatrix.Core.Extensions;
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Helper.Factory; using StabilityMatrix.Core.Helper.Factory;
using StabilityMatrix.Core.Models;
using StabilityMatrix.Core.Models.FileInterfaces;
using StabilityMatrix.Core.Models.PackageModification;
using StabilityMatrix.Core.Models.Packages; using StabilityMatrix.Core.Models.Packages;
using StabilityMatrix.Core.Python;
using StabilityMatrix.Core.Services;
namespace StabilityMatrix.Avalonia.ViewModels.Dialogs; namespace StabilityMatrix.Avalonia.ViewModels.Dialogs;
@ -19,6 +29,10 @@ namespace StabilityMatrix.Avalonia.ViewModels.Dialogs;
[ManagedService] [ManagedService]
public partial class NewOneClickInstallViewModel : ContentDialogViewModelBase public partial class NewOneClickInstallViewModel : ContentDialogViewModelBase
{ {
private readonly ISettingsManager settingsManager;
private readonly IPrerequisiteHelper prerequisiteHelper;
private readonly ILogger<NewOneClickInstallViewModel> logger;
private readonly IPyRunner pyRunner;
public SourceCache<BasePackage, string> AllPackagesCache { get; } = new(p => p.Author + p.Name); public SourceCache<BasePackage, string> AllPackagesCache { get; } = new(p => p.Author + p.Name);
public IObservableCollection<BasePackage> ShownPackages { get; set; } = public IObservableCollection<BasePackage> ShownPackages { get; set; } =
@ -27,8 +41,19 @@ public partial class NewOneClickInstallViewModel : ContentDialogViewModelBase
[ObservableProperty] [ObservableProperty]
private bool showIncompatiblePackages; private bool showIncompatiblePackages;
public NewOneClickInstallViewModel(IPackageFactory packageFactory) public NewOneClickInstallViewModel(
IPackageFactory packageFactory,
ISettingsManager settingsManager,
IPrerequisiteHelper prerequisiteHelper,
ILogger<NewOneClickInstallViewModel> logger,
IPyRunner pyRunner
)
{ {
this.settingsManager = settingsManager;
this.prerequisiteHelper = prerequisiteHelper;
this.logger = logger;
this.pyRunner = pyRunner;
var incompatiblePredicate = this.WhenPropertyChanged(vm => vm.ShowIncompatiblePackages) var incompatiblePredicate = this.WhenPropertyChanged(vm => vm.ShowIncompatiblePackages)
.Select(_ => new Func<BasePackage, bool>(p => p.IsCompatible || ShowIncompatiblePackages)) .Select(_ => new Func<BasePackage, bool>(p => p.IsCompatible || ShowIncompatiblePackages))
.AsObservable(); .AsObservable();
@ -50,12 +75,83 @@ public partial class NewOneClickInstallViewModel : ContentDialogViewModelBase
} }
[RelayCommand] [RelayCommand]
private async Task InstallComfyForInference() private Task InstallComfyForInference()
{ {
var comfyPackage = ShownPackages.FirstOrDefault(x => x is ComfyUI); var comfyPackage = ShownPackages.FirstOrDefault(x => x is ComfyUI);
if (comfyPackage != null) return comfyPackage != null ? InstallPackage(comfyPackage) : Task.CompletedTask;
}
[RelayCommand]
private async Task InstallPackage(BasePackage selectedPackage)
{
var steps = new List<IPackageStep>
{
new SetPackageInstallingStep(settingsManager, selectedPackage.Name),
new SetupPrerequisitesStep(prerequisiteHelper, pyRunner)
};
// get latest version & download & install
var installLocation = Path.Combine(settingsManager.LibraryDir, "Packages", selectedPackage.Name);
if (Directory.Exists(installLocation))
{
var installPath = new DirectoryPath(installLocation);
await installPath.DeleteVerboseAsync(logger);
}
var downloadVersion = await selectedPackage.GetLatestVersion();
var installedVersion = new InstalledPackageVersion { IsPrerelease = false };
if (selectedPackage.ShouldIgnoreReleases)
{ {
// install installedVersion.InstalledBranch = downloadVersion.BranchName;
installedVersion.InstalledCommitSha = downloadVersion.CommitHash;
} }
else
{
installedVersion.InstalledReleaseVersion = downloadVersion.VersionTag;
}
var torchVersion = selectedPackage.GetRecommendedTorchVersion();
var recommendedSharedFolderMethod = selectedPackage.RecommendedSharedFolderMethod;
var downloadStep = new DownloadPackageVersionStep(selectedPackage, installLocation, downloadVersion);
steps.Add(downloadStep);
var installStep = new InstallPackageStep(
selectedPackage,
torchVersion,
recommendedSharedFolderMethod,
downloadVersion,
installLocation
);
steps.Add(installStep);
var setupModelFoldersStep = new SetupModelFoldersStep(
selectedPackage,
recommendedSharedFolderMethod,
installLocation
);
steps.Add(setupModelFoldersStep);
var installedPackage = new InstalledPackage
{
DisplayName = selectedPackage.DisplayName,
LibraryPath = Path.Combine("Packages", selectedPackage.Name),
Id = Guid.NewGuid(),
PackageName = selectedPackage.Name,
Version = installedVersion,
LaunchCommand = selectedPackage.LaunchCommand,
LastUpdateCheck = DateTimeOffset.Now,
PreferredTorchVersion = torchVersion,
PreferredSharedFolderMethod = recommendedSharedFolderMethod
};
var addInstalledPackageStep = new AddInstalledPackageStep(settingsManager, installedPackage);
steps.Add(addInstalledPackageStep);
var runner = new PackageModificationRunner { ShowDialogOnStart = true, HideCloseButton = true, };
EventManager.Instance.OnAddPackageInstallWithoutBlocking(this, runner, steps);
OnPrimaryButtonClick();
} }
} }

14
StabilityMatrix.Avalonia/ViewModels/Dialogs/RecommendedModelsViewModel.cs

@ -0,0 +1,14 @@
using System.Threading.Tasks;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Core.Api;
namespace StabilityMatrix.Avalonia.ViewModels.Dialogs;
public class RecommendedModelsViewModel(ILykosAuthApi lykosApi, ICivitApi civitApi)
: ContentDialogViewModelBase
{
public override async Task OnLoadedAsync()
{
var recommendedModels = await lykosApi.GetRecommendedModels();
}
}

22
StabilityMatrix.Avalonia/ViewModels/Progress/PackageInstallProgressItemViewModel.cs

@ -1,6 +1,9 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using AsyncAwaitBestPractices;
using Avalonia.Controls;
using Avalonia.Threading; using Avalonia.Threading;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using StabilityMatrix.Avalonia.Controls; using StabilityMatrix.Avalonia.Controls;
@ -15,28 +18,37 @@ namespace StabilityMatrix.Avalonia.ViewModels.Progress;
public class PackageInstallProgressItemViewModel : ProgressItemViewModelBase public class PackageInstallProgressItemViewModel : ProgressItemViewModelBase
{ {
private readonly IPackageModificationRunner packageModificationRunner; private readonly IPackageModificationRunner packageModificationRunner;
private readonly IReadOnlyList<IPackageStep>? packageSteps;
private BetterContentDialog? dialog; private BetterContentDialog? dialog;
public PackageInstallProgressItemViewModel( public PackageInstallProgressItemViewModel(
IPackageModificationRunner packageModificationRunner, IPackageModificationRunner packageModificationRunner,
bool hideCloseButton = false IReadOnlyList<IPackageStep>? packageSteps = null
) )
{ {
this.packageModificationRunner = packageModificationRunner; this.packageModificationRunner = packageModificationRunner;
this.packageSteps = packageSteps;
Id = packageModificationRunner.Id; Id = packageModificationRunner.Id;
Name = packageModificationRunner.CurrentStep?.ProgressTitle; Name = packageModificationRunner.CurrentStep?.ProgressTitle;
Progress.Value = packageModificationRunner.CurrentProgress.Percentage; Progress.Value = packageModificationRunner.CurrentProgress.Percentage;
Progress.Text = packageModificationRunner.ConsoleOutput.LastOrDefault(); Progress.Text = packageModificationRunner.ConsoleOutput.LastOrDefault();
Progress.IsIndeterminate = packageModificationRunner.CurrentProgress.IsIndeterminate; Progress.IsIndeterminate = packageModificationRunner.CurrentProgress.IsIndeterminate;
Progress.HideCloseButton = hideCloseButton; Progress.HideCloseButton = packageModificationRunner.HideCloseButton;
if (Design.IsDesignMode)
return;
Progress.Console.StartUpdates(); Progress.Console.StartUpdates();
Progress.Console.Post( Progress.Console.Post(string.Join(Environment.NewLine, packageModificationRunner.ConsoleOutput));
string.Join(Environment.NewLine, packageModificationRunner.ConsoleOutput)
);
packageModificationRunner.ProgressChanged += PackageModificationRunnerOnProgressChanged; packageModificationRunner.ProgressChanged += PackageModificationRunnerOnProgressChanged;
if (packageSteps is { Count: > 0 })
{
packageModificationRunner.ExecuteSteps(packageSteps).SafeFireAndForget();
}
} }
private void PackageModificationRunnerOnProgressChanged(object? sender, ProgressReport e) private void PackageModificationRunnerOnProgressChanged(object? sender, ProgressReport e)

19
StabilityMatrix.Avalonia/ViewModels/Progress/ProgressManagerViewModel.cs

@ -57,8 +57,9 @@ public partial class ProgressManagerViewModel : PageViewModelBase
// Attach to the event // Attach to the event
trackedDownloadService.DownloadAdded += TrackedDownloadService_OnDownloadAdded; trackedDownloadService.DownloadAdded += TrackedDownloadService_OnDownloadAdded;
EventManager.Instance.PackageInstallProgressAdded += InstanceOnPackageInstallProgressAdded;
EventManager.Instance.ToggleProgressFlyout += (_, _) => IsOpen = !IsOpen; EventManager.Instance.ToggleProgressFlyout += (_, _) => IsOpen = !IsOpen;
EventManager.Instance.AddPackageInstallWithoutBlocking += InstanceOnAddPackageInstallWithoutBlocking;
EventManager.Instance.PackageInstallProgressAdded += InstanceOnPackageInstallProgressAdded;
} }
private void InstanceOnPackageInstallProgressAdded(object? sender, IPackageModificationRunner runner) private void InstanceOnPackageInstallProgressAdded(object? sender, IPackageModificationRunner runner)
@ -66,6 +67,12 @@ public partial class ProgressManagerViewModel : PageViewModelBase
AddPackageInstall(runner).SafeFireAndForget(); AddPackageInstall(runner).SafeFireAndForget();
} }
private Task InstanceOnAddPackageInstallWithoutBlocking(
object? sender,
IPackageModificationRunner runner,
IReadOnlyList<IPackageStep> steps
) => AddPackageInstall(runner, steps);
private void TrackedDownloadService_OnDownloadAdded(object? sender, TrackedDownload e) private void TrackedDownloadService_OnDownloadAdded(object? sender, TrackedDownload e)
{ {
var vm = new DownloadProgressItemViewModel(e); var vm = new DownloadProgressItemViewModel(e);
@ -165,17 +172,17 @@ public partial class ProgressManagerViewModel : PageViewModelBase
} }
} }
private Task AddPackageInstall(IPackageModificationRunner packageModificationRunner) private Task AddPackageInstall(
IPackageModificationRunner packageModificationRunner,
IReadOnlyList<IPackageStep>? steps = null
)
{ {
if (ProgressItems.Any(vm => vm.Id == packageModificationRunner.Id)) if (ProgressItems.Any(vm => vm.Id == packageModificationRunner.Id))
{ {
return Task.CompletedTask; return Task.CompletedTask;
} }
var vm = new PackageInstallProgressItemViewModel( var vm = new PackageInstallProgressItemViewModel(packageModificationRunner, steps);
packageModificationRunner,
packageModificationRunner.HideCloseButton
);
ProgressItems.Add(vm); ProgressItems.Add(vm);
return packageModificationRunner.ShowDialogOnStart ? vm.ShowProgressDialog() : Task.CompletedTask; return packageModificationRunner.ShowDialogOnStart ? vm.ShowProgressDialog() : Task.CompletedTask;

6
StabilityMatrix.Avalonia/Views/Dialogs/NewOneClickInstallDialog.axaml

@ -16,8 +16,8 @@
x:Class="StabilityMatrix.Avalonia.Views.Dialogs.NewOneClickInstallDialog"> x:Class="StabilityMatrix.Avalonia.Views.Dialogs.NewOneClickInstallDialog">
<controls:UserControlBase.Resources> <controls:UserControlBase.Resources>
<!-- <input:StandardUICommand x:Key="PackageSelected" --> <input:StandardUICommand x:Key="InstallPackageCommand"
<!-- Command="{Binding OnPackageSelected}" /> --> Command="{Binding InstallPackageCommand}" />
<DataTemplate x:DataType="packages:BasePackage" x:Key="PackageTemplate"> <DataTemplate x:DataType="packages:BasePackage" x:Key="PackageTemplate">
<Button Padding="0" <Button Padding="0"
@ -26,7 +26,7 @@
Margin="4" Margin="4"
Classes="transparent-full" Classes="transparent-full"
CornerRadius="8" CornerRadius="8"
Command="{StaticResource PackageSelected}" Command="{StaticResource InstallPackageCommand}"
CommandParameter="{Binding }"> CommandParameter="{Binding }">
<controls:Card Padding="8, 0"> <controls:Card Padding="8, 0">

3
StabilityMatrix.Core/Api/ICivitApi.cs

@ -13,4 +13,7 @@ public interface ICivitApi
[Get("/api/v1/model-versions/by-hash/{hash}")] [Get("/api/v1/model-versions/by-hash/{hash}")]
Task<CivitModelVersionResponse> GetModelVersionByHash([Query] string hash); Task<CivitModelVersionResponse> GetModelVersionByHash([Query] string hash);
[Get("/api/v1/model-versions/{id}")]
Task<CivitModelVersion> GetModelVersionById(int id);
} }

10
StabilityMatrix.Core/Api/ILykosAuthApi.cs

@ -45,15 +45,12 @@ public interface ILykosAuthApi
CancellationToken cancellationToken = default CancellationToken cancellationToken = default
) )
{ {
var result = await GetPatreonOAuthRedirect(redirectUrl, cancellationToken) var result = await GetPatreonOAuthRedirect(redirectUrl, cancellationToken).ConfigureAwait(false);
.ConfigureAwait(false);
if (result.StatusCode != HttpStatusCode.Redirect) if (result.StatusCode != HttpStatusCode.Redirect)
{ {
result.EnsureSuccessStatusCode(); result.EnsureSuccessStatusCode();
throw new InvalidOperationException( throw new InvalidOperationException($"Expected a redirect 302 response, got {result.StatusCode}");
$"Expected a redirect 302 response, got {result.StatusCode}"
);
} }
return result.Headers.Location?.ToString() return result.Headers.Location?.ToString()
@ -70,4 +67,7 @@ public interface ILykosAuthApi
string path, string path,
CancellationToken cancellationToken = default CancellationToken cancellationToken = default
); );
[Get("/api/Models/recommended")]
Task<GetRecommendedModelsResponse> GetRecommendedModels();
} }

16
StabilityMatrix.Core/Helper/EventManager.cs

@ -26,14 +26,16 @@ public class EventManager
public event EventHandler? ScrollToBottomRequested; public event EventHandler? ScrollToBottomRequested;
public event EventHandler<ProgressItem>? ProgressChanged; public event EventHandler<ProgressItem>? ProgressChanged;
public event EventHandler<RunningPackageStatusChangedEventArgs>? RunningPackageStatusChanged; public event EventHandler<RunningPackageStatusChangedEventArgs>? RunningPackageStatusChanged;
public event EventHandler<IPackageModificationRunner>? PackageInstallProgressAdded; public event EventHandler<IPackageModificationRunner>? PackageInstallProgressAdded;
public delegate Task AddPackageInstallEventHandler(
object? sender,
IPackageModificationRunner runner,
IReadOnlyList<IPackageStep> steps
);
public event AddPackageInstallEventHandler? AddPackageInstallWithoutBlocking;
public event EventHandler? ToggleProgressFlyout; public event EventHandler? ToggleProgressFlyout;
public event EventHandler<CultureInfo>? CultureChanged; public event EventHandler<CultureInfo>? CultureChanged;
public event EventHandler? ModelIndexChanged; public event EventHandler? ModelIndexChanged;
public event EventHandler<FilePath>? ImageFileAdded; public event EventHandler<FilePath>? ImageFileAdded;
public event EventHandler<LocalImageFile>? InferenceTextToImageRequested; public event EventHandler<LocalImageFile>? InferenceTextToImageRequested;
public event EventHandler<LocalImageFile>? InferenceUpscaleRequested; public event EventHandler<LocalImageFile>? InferenceUpscaleRequested;
@ -90,4 +92,10 @@ public class EventManager
public void OnNavigateAndFindCivitModelRequested(int modelId) => public void OnNavigateAndFindCivitModelRequested(int modelId) =>
NavigateAndFindCivitModelRequested?.Invoke(this, modelId); NavigateAndFindCivitModelRequested?.Invoke(this, modelId);
public void OnAddPackageInstallWithoutBlocking(
object? sender,
IPackageModificationRunner runner,
IReadOnlyList<IPackageStep> steps
) => AddPackageInstallWithoutBlocking?.Invoke(sender, runner, steps);
} }

7
StabilityMatrix.Core/Models/Api/Lykos/GetRecommendedModelsResponse.cs

@ -0,0 +1,7 @@
namespace StabilityMatrix.Core.Models.Api.Lykos;
public class GetRecommendedModelsResponse
{
public required IEnumerable<int> Sd15 { get; set; }
public required IEnumerable<int> Sdxl { get; set; }
}
Loading…
Cancel
Save