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. 7
      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
{
CurrentProgress = new ProgressReport(0.5f, "Installing package...")
}
},
new List<IPackageStep>()
)
}
);
@ -493,6 +494,14 @@ public static class DesignData
{
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
{
Author = "123",

1
StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj

@ -33,6 +33,7 @@
<PackageReference Include="AsyncImageLoader.Avalonia" Version="3.2.1" />
<PackageReference Include="AutoComplete.Net" Version="1.2211.2014.42"/>
<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" 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.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;
@ -7,11 +9,19 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DynamicData;
using DynamicData.Binding;
using Microsoft.Extensions.Logging;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Avalonia.Views.Dialogs;
using StabilityMatrix.Core.Attributes;
using StabilityMatrix.Core.Extensions;
using StabilityMatrix.Core.Helper;
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.Python;
using StabilityMatrix.Core.Services;
namespace StabilityMatrix.Avalonia.ViewModels.Dialogs;
@ -19,6 +29,10 @@ namespace StabilityMatrix.Avalonia.ViewModels.Dialogs;
[ManagedService]
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 IObservableCollection<BasePackage> ShownPackages { get; set; } =
@ -27,8 +41,19 @@ public partial class NewOneClickInstallViewModel : ContentDialogViewModelBase
[ObservableProperty]
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)
.Select(_ => new Func<BasePackage, bool>(p => p.IsCompatible || ShowIncompatiblePackages))
.AsObservable();
@ -50,12 +75,83 @@ public partial class NewOneClickInstallViewModel : ContentDialogViewModelBase
}
[RelayCommand]
private async Task InstallComfyForInference()
private Task InstallComfyForInference()
{
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.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AsyncAwaitBestPractices;
using Avalonia.Controls;
using Avalonia.Threading;
using FluentAvalonia.UI.Controls;
using StabilityMatrix.Avalonia.Controls;
@ -15,28 +18,37 @@ namespace StabilityMatrix.Avalonia.ViewModels.Progress;
public class PackageInstallProgressItemViewModel : ProgressItemViewModelBase
{
private readonly IPackageModificationRunner packageModificationRunner;
private readonly IReadOnlyList<IPackageStep>? packageSteps;
private BetterContentDialog? dialog;
public PackageInstallProgressItemViewModel(
IPackageModificationRunner packageModificationRunner,
bool hideCloseButton = false
IReadOnlyList<IPackageStep>? packageSteps = null
)
{
this.packageModificationRunner = packageModificationRunner;
this.packageSteps = packageSteps;
Id = packageModificationRunner.Id;
Name = packageModificationRunner.CurrentStep?.ProgressTitle;
Progress.Value = packageModificationRunner.CurrentProgress.Percentage;
Progress.Text = packageModificationRunner.ConsoleOutput.LastOrDefault();
Progress.IsIndeterminate = packageModificationRunner.CurrentProgress.IsIndeterminate;
Progress.HideCloseButton = hideCloseButton;
Progress.HideCloseButton = packageModificationRunner.HideCloseButton;
if (Design.IsDesignMode)
return;
Progress.Console.StartUpdates();
Progress.Console.Post(
string.Join(Environment.NewLine, packageModificationRunner.ConsoleOutput)
);
Progress.Console.Post(string.Join(Environment.NewLine, packageModificationRunner.ConsoleOutput));
packageModificationRunner.ProgressChanged += PackageModificationRunnerOnProgressChanged;
if (packageSteps is { Count: > 0 })
{
packageModificationRunner.ExecuteSteps(packageSteps).SafeFireAndForget();
}
}
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
trackedDownloadService.DownloadAdded += TrackedDownloadService_OnDownloadAdded;
EventManager.Instance.PackageInstallProgressAdded += InstanceOnPackageInstallProgressAdded;
EventManager.Instance.ToggleProgressFlyout += (_, _) => IsOpen = !IsOpen;
EventManager.Instance.AddPackageInstallWithoutBlocking += InstanceOnAddPackageInstallWithoutBlocking;
EventManager.Instance.PackageInstallProgressAdded += InstanceOnPackageInstallProgressAdded;
}
private void InstanceOnPackageInstallProgressAdded(object? sender, IPackageModificationRunner runner)
@ -66,6 +67,12 @@ public partial class ProgressManagerViewModel : PageViewModelBase
AddPackageInstall(runner).SafeFireAndForget();
}
private Task InstanceOnAddPackageInstallWithoutBlocking(
object? sender,
IPackageModificationRunner runner,
IReadOnlyList<IPackageStep> steps
) => AddPackageInstall(runner, steps);
private void TrackedDownloadService_OnDownloadAdded(object? sender, TrackedDownload 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))
{
return Task.CompletedTask;
}
var vm = new PackageInstallProgressItemViewModel(
packageModificationRunner,
packageModificationRunner.HideCloseButton
);
var vm = new PackageInstallProgressItemViewModel(packageModificationRunner, steps);
ProgressItems.Add(vm);
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">
<controls:UserControlBase.Resources>
<!-- <input:StandardUICommand x:Key="PackageSelected" -->
<!-- Command="{Binding OnPackageSelected}" /> -->
<input:StandardUICommand x:Key="InstallPackageCommand"
Command="{Binding InstallPackageCommand}" />
<DataTemplate x:DataType="packages:BasePackage" x:Key="PackageTemplate">
<Button Padding="0"
@ -26,7 +26,7 @@
Margin="4"
Classes="transparent-full"
CornerRadius="8"
Command="{StaticResource PackageSelected}"
Command="{StaticResource InstallPackageCommand}"
CommandParameter="{Binding }">
<controls:Card Padding="8, 0">

7
StabilityMatrix.Core/Api/ICivitApi.cs

@ -7,10 +7,13 @@ public interface ICivitApi
{
[Get("/api/v1/models")]
Task<CivitModelsResponse> GetModels(CivitModelsRequest request);
[Get("/api/v1/models/{id}")]
Task<CivitModel> GetModelById([AliasAs("id")] int id);
[Get("/api/v1/model-versions/by-hash/{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
)
{
var result = await GetPatreonOAuthRedirect(redirectUrl, cancellationToken)
.ConfigureAwait(false);
var result = await GetPatreonOAuthRedirect(redirectUrl, cancellationToken).ConfigureAwait(false);
if (result.StatusCode != HttpStatusCode.Redirect)
{
result.EnsureSuccessStatusCode();
throw new InvalidOperationException(
$"Expected a redirect 302 response, got {result.StatusCode}"
);
throw new InvalidOperationException($"Expected a redirect 302 response, got {result.StatusCode}");
}
return result.Headers.Location?.ToString()
@ -70,4 +67,7 @@ public interface ILykosAuthApi
string path,
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<ProgressItem>? ProgressChanged;
public event EventHandler<RunningPackageStatusChangedEventArgs>? RunningPackageStatusChanged;
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<CultureInfo>? CultureChanged;
public event EventHandler? ModelIndexChanged;
public event EventHandler<FilePath>? ImageFileAdded;
public event EventHandler<LocalImageFile>? InferenceTextToImageRequested;
public event EventHandler<LocalImageFile>? InferenceUpscaleRequested;
@ -90,4 +92,10 @@ public class EventManager
public void OnNavigateAndFindCivitModelRequested(int 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