Browse Source

Merge pull request #447 from LykosAI/main

v2.8.2 Update
pull/457/head
Ionite 9 months ago committed by GitHub
parent
commit
a0ff4a07dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      .github/workflows/backport.yml
  2. 9
      CHANGELOG.md
  3. 8
      StabilityMatrix.Avalonia/Controls/Inference/SamplerCard.axaml
  4. 77
      StabilityMatrix.Avalonia/Services/InferenceClientManager.cs
  5. 2
      StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
  6. 44
      StabilityMatrix.Avalonia/ViewModels/Dialogs/RecommendedModelsViewModel.cs
  7. 8
      StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs
  8. 28
      StabilityMatrix.Avalonia/ViewModels/Inference/SamplerCardViewModel.cs
  9. 21
      StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageExtensionBrowserViewModel.cs
  10. 5
      StabilityMatrix.Core/Models/PackageModification/PackageModificationRunner.cs
  11. 1
      StabilityMatrix.Core/Models/Packages/A3WebUI.cs
  12. 16
      StabilityMatrix.Core/Models/Packages/Extensions/GitPackageExtensionManager.cs

6
.github/workflows/backport.yml

@ -1,12 +1,12 @@
name: Automatic Backport name: Automatic Backport
on: on:
pull_request_target: pull_request:
types: ["labeled", "closed"] types: ["closed", "labeled"]
jobs: jobs:
backport: backport:
if: startsWith(github.event.pull_request.labels.*.name, 'backport-to-') if: ${{ (github.event.pull_request.merged == true) && (contains(github.event.pull_request.labels.*.name, 'backport-to-main') == true) }}
name: Backport PR name: Backport PR
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

9
CHANGELOG.md

@ -5,6 +5,15 @@ All notable changes to Stability Matrix will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html).
## v2.8.2
### Added
- Added missing GFPGAN link to Automatic1111 packages
### Fixed
- Fixed Inference Image to Image Denoise setting becoming hidden after changing schedulers
- Fixed Inference ControlNet models showing as downloadable even when they are already installed
- Fixed Inference Sampler Addon conditioning not applying (i.e. ControlNet)
- Fixed extension modification dialog not showing any progress messages
## v2.8.1 ## v2.8.1
### Fixed ### Fixed
- Fixed model links not working in RuinedFooocus for new installations - Fixed model links not working in RuinedFooocus for new installations

8
StabilityMatrix.Avalonia/Controls/Inference/SamplerCard.axaml

@ -123,7 +123,13 @@
<StackPanel> <StackPanel>
<!-- Denoise Strength --> <!-- Denoise Strength -->
<StackPanel IsVisible="{Binding IsDenoiseStrengthEnabled}"> <StackPanel>
<StackPanel.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.Or}">
<Binding Path="IsDenoiseStrengthEnabled"/>
<Binding Path="IsDenoiseStrengthTempEnabled"/>
</MultiBinding>
</StackPanel.IsVisible>
<Grid ColumnDefinitions="*,Auto"> <Grid ColumnDefinitions="*,Auto">
<TextBlock <TextBlock
VerticalAlignment="Center" VerticalAlignment="Center"

77
StabilityMatrix.Avalonia/Services/InferenceClientManager.cs

@ -56,7 +56,8 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
private readonly SourceCache<HybridModelFile, string> modelsSource = new(p => p.GetId()); private readonly SourceCache<HybridModelFile, string> modelsSource = new(p => p.GetId());
public IObservableCollection<HybridModelFile> Models { get; } = new ObservableCollectionExtended<HybridModelFile>(); public IObservableCollection<HybridModelFile> Models { get; } =
new ObservableCollectionExtended<HybridModelFile>();
private readonly SourceCache<HybridModelFile, string> vaeModelsSource = new(p => p.GetId()); private readonly SourceCache<HybridModelFile, string> vaeModelsSource = new(p => p.GetId());
@ -67,14 +68,16 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
private readonly SourceCache<HybridModelFile, string> controlNetModelsSource = new(p => p.GetId()); private readonly SourceCache<HybridModelFile, string> controlNetModelsSource = new(p => p.GetId());
private readonly SourceCache<HybridModelFile, string> downloadableControlNetModelsSource = new(p => p.GetId()); private readonly SourceCache<HybridModelFile, string> downloadableControlNetModelsSource =
new(p => p.GetId());
public IObservableCollection<HybridModelFile> ControlNetModels { get; } = public IObservableCollection<HybridModelFile> ControlNetModels { get; } =
new ObservableCollectionExtended<HybridModelFile>(); new ObservableCollectionExtended<HybridModelFile>();
private readonly SourceCache<ComfySampler, string> samplersSource = new(p => p.Name); private readonly SourceCache<ComfySampler, string> samplersSource = new(p => p.Name);
public IObservableCollection<ComfySampler> Samplers { get; } = new ObservableCollectionExtended<ComfySampler>(); public IObservableCollection<ComfySampler> Samplers { get; } =
new ObservableCollectionExtended<ComfySampler>();
private readonly SourceCache<ComfyUpscaler, string> modelUpscalersSource = new(p => p.Name); private readonly SourceCache<ComfyUpscaler, string> modelUpscalersSource = new(p => p.Name);
@ -82,7 +85,8 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
private readonly SourceCache<ComfyUpscaler, string> downloadableUpscalersSource = new(p => p.Name); private readonly SourceCache<ComfyUpscaler, string> downloadableUpscalersSource = new(p => p.Name);
public IObservableCollection<ComfyUpscaler> Upscalers { get; } = new ObservableCollectionExtended<ComfyUpscaler>(); public IObservableCollection<ComfyUpscaler> Upscalers { get; } =
new ObservableCollectionExtended<ComfyUpscaler>();
private readonly SourceCache<ComfyScheduler, string> schedulersSource = new(p => p.Name); private readonly SourceCache<ComfyScheduler, string> schedulersSource = new(p => p.Name);
@ -105,7 +109,11 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
modelsSource modelsSource
.Connect() .Connect()
.SortBy(f => f.ShortDisplayName, SortDirection.Ascending, SortOptimisations.ComparesImmutableValuesOnly) .SortBy(
f => f.ShortDisplayName,
SortDirection.Ascending,
SortOptimisations.ComparesImmutableValuesOnly
)
.DeferUntilLoaded() .DeferUntilLoaded()
.Bind(Models) .Bind(Models)
.Subscribe(); .Subscribe();
@ -114,7 +122,9 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
.Connect() .Connect()
.Or(downloadableControlNetModelsSource.Connect()) .Or(downloadableControlNetModelsSource.Connect())
.Sort( .Sort(
SortExpressionComparer<HybridModelFile>.Ascending(f => f.Type).ThenByAscending(f => f.ShortDisplayName) SortExpressionComparer<HybridModelFile>
.Ascending(f => f.Type)
.ThenByAscending(f => f.ShortDisplayName)
) )
.DeferUntilLoaded() .DeferUntilLoaded()
.Bind(ControlNetModels) .Bind(ControlNetModels)
@ -153,7 +163,9 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
if (IsConnected) if (IsConnected)
{ {
LoadSharedPropertiesAsync() LoadSharedPropertiesAsync()
.SafeFireAndForget(onException: ex => logger.LogError(ex, "Error loading shared properties")); .SafeFireAndForget(
onException: ex => logger.LogError(ex, "Error loading shared properties")
);
} }
}; };
} }
@ -176,7 +188,10 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
} }
// Get control net model names // Get control net model names
if (await Client.GetNodeOptionNamesAsync("ControlNetLoader", "control_net_name") is { } controlNetModelNames) if (
await Client.GetNodeOptionNamesAsync("ControlNetLoader", "control_net_name") is
{ } controlNetModelNames
)
{ {
controlNetModelsSource.EditDiff( controlNetModelsSource.EditDiff(
controlNetModelNames.Select(HybridModelFile.FromRemote), controlNetModelNames.Select(HybridModelFile.FromRemote),
@ -187,13 +202,18 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
// Fetch sampler names from KSampler node // Fetch sampler names from KSampler node
if (await Client.GetSamplerNamesAsync() is { } samplerNames) if (await Client.GetSamplerNamesAsync() is { } samplerNames)
{ {
samplersSource.EditDiff(samplerNames.Select(name => new ComfySampler(name)), ComfySampler.Comparer); samplersSource.EditDiff(
samplerNames.Select(name => new ComfySampler(name)),
ComfySampler.Comparer
);
} }
// Upscalers is latent and esrgan combined // Upscalers is latent and esrgan combined
// Add latent upscale methods from LatentUpscale node // Add latent upscale methods from LatentUpscale node
if (await Client.GetNodeOptionNamesAsync("LatentUpscale", "upscale_method") is { } latentUpscalerNames) if (
await Client.GetNodeOptionNamesAsync("LatentUpscale", "upscale_method") is { } latentUpscalerNames
)
{ {
latentUpscalersSource.EditDiff( latentUpscalersSource.EditDiff(
latentUpscalerNames.Select(s => new ComfyUpscaler(s, ComfyUpscalerType.Latent)), latentUpscalerNames.Select(s => new ComfyUpscaler(s, ComfyUpscalerType.Latent)),
@ -204,7 +224,9 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
} }
// Add Model upscale methods // Add Model upscale methods
if (await Client.GetNodeOptionNamesAsync("UpscaleModelLoader", "model_name") is { } modelUpscalerNames) if (
await Client.GetNodeOptionNamesAsync("UpscaleModelLoader", "model_name") is { } modelUpscalerNames
)
{ {
modelUpscalersSource.EditDiff( modelUpscalersSource.EditDiff(
modelUpscalerNames.Select(s => new ComfyUpscaler(s, ComfyUpscalerType.ESRGAN)), modelUpscalerNames.Select(s => new ComfyUpscaler(s, ComfyUpscalerType.ESRGAN)),
@ -219,7 +241,9 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
schedulersSource.Edit(updater => schedulersSource.Edit(updater =>
{ {
updater.AddOrUpdate( updater.AddOrUpdate(
schedulerNames.Where(n => !schedulersSource.Keys.Contains(n)).Select(s => new ComfyScheduler(s)) schedulerNames
.Where(n => !schedulersSource.Keys.Contains(n))
.Select(s => new ComfyScheduler(s))
); );
}); });
logger.LogTrace("Loaded scheduler methods: {@Schedulers}", schedulerNames); logger.LogTrace("Loaded scheduler methods: {@Schedulers}", schedulerNames);
@ -233,20 +257,24 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
{ {
// Load local models // Load local models
modelsSource.EditDiff( modelsSource.EditDiff(
modelIndexService.GetFromModelIndex(SharedFolderType.StableDiffusion).Select(HybridModelFile.FromLocal), modelIndexService
.GetFromModelIndex(SharedFolderType.StableDiffusion)
.Select(HybridModelFile.FromLocal),
HybridModelFile.Comparer HybridModelFile.Comparer
); );
// Load local control net models // Load local control net models
controlNetModelsSource.EditDiff( controlNetModelsSource.EditDiff(
modelIndexService.GetFromModelIndex(SharedFolderType.ControlNet).Select(HybridModelFile.FromLocal), modelIndexService
.GetFromModelIndex(SharedFolderType.ControlNet)
.Select(HybridModelFile.FromLocal),
HybridModelFile.Comparer HybridModelFile.Comparer
); );
// Downloadable ControlNet models // Downloadable ControlNet models
var downloadableControlNets = RemoteModels var downloadableControlNets = RemoteModels.ControlNetModels.Where(
.ControlNetModels u => !controlNetModelsSource.Lookup(u.GetId()).HasValue
.Where(u => !modelUpscalersSource.Lookup(u.GetId()).HasValue); );
downloadableControlNetModelsSource.EditDiff(downloadableControlNets, HybridModelFile.Comparer); downloadableControlNetModelsSource.EditDiff(downloadableControlNets, HybridModelFile.Comparer);
// Load local VAE models // Load local VAE models
@ -264,15 +292,17 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
// Load Upscalers // Load Upscalers
modelUpscalersSource.EditDiff( modelUpscalersSource.EditDiff(
modelIndexService modelIndexService
.GetFromModelIndex(SharedFolderType.ESRGAN | SharedFolderType.RealESRGAN | SharedFolderType.SwinIR) .GetFromModelIndex(
SharedFolderType.ESRGAN | SharedFolderType.RealESRGAN | SharedFolderType.SwinIR
)
.Select(m => new ComfyUpscaler(m.FileName, ComfyUpscalerType.ESRGAN)), .Select(m => new ComfyUpscaler(m.FileName, ComfyUpscalerType.ESRGAN)),
ComfyUpscaler.Comparer ComfyUpscaler.Comparer
); );
// Remote upscalers // Remote upscalers
var remoteUpscalers = ComfyUpscaler var remoteUpscalers = ComfyUpscaler.DefaultDownloadableModels.Where(
.DefaultDownloadableModels u => !modelUpscalersSource.Lookup(u.Name).HasValue
.Where(u => !modelUpscalersSource.Lookup(u.Name).HasValue); );
downloadableUpscalersSource.EditDiff(remoteUpscalers, ComfyUpscaler.Comparer); downloadableUpscalersSource.EditDiff(remoteUpscalers, ComfyUpscaler.Comparer);
} }
@ -322,7 +352,10 @@ public partial class InferenceClientManager : ObservableObject, IInferenceClient
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task WriteImageToInputAsync(ImageSource imageSource, CancellationToken cancellationToken = default) public async Task WriteImageToInputAsync(
ImageSource imageSource,
CancellationToken cancellationToken = default
)
{ {
if (!IsConnected) if (!IsConnected)
return; return;

2
StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj

@ -17,7 +17,7 @@
<ApplicationManifest>app.manifest</ApplicationManifest> <ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<ApplicationIcon>./Assets/Icon.ico</ApplicationIcon> <ApplicationIcon>./Assets/Icon.ico</ApplicationIcon>
<Version>2.8.0-dev.999</Version> <Version>2.9.0-dev.999</Version>
<InformationalVersion>$(Version)</InformationalVersion> <InformationalVersion>$(Version)</InformationalVersion>
<EnableWindowsTargeting>true</EnableWindowsTargeting> <EnableWindowsTargeting>true</EnableWindowsTargeting>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>

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

@ -8,6 +8,7 @@ using CommunityToolkit.Mvvm.Input;
using DynamicData; using DynamicData;
using DynamicData.Binding; using DynamicData.Binding;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Refit;
using StabilityMatrix.Avalonia.Services; using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Base; using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Core.Api; using StabilityMatrix.Core.Api;
@ -86,21 +87,34 @@ public partial class RecommendedModelsViewModel : ContentDialogViewModelBase
IsLoading = true; IsLoading = true;
var recommendedModels = await lykosApi.GetRecommendedModels(); try
{
CivitModels.AddOrUpdate( var recommendedModels = await lykosApi.GetRecommendedModels();
recommendedModels.Items.Select(
model => CivitModels.AddOrUpdate(
new RecommendedModelItemViewModel recommendedModels.Items.Select(
{ model =>
ModelVersion = model.ModelVersions.First( new RecommendedModelItemViewModel
x => !x.BaseModel.Contains("Turbo", StringComparison.OrdinalIgnoreCase) {
), ModelVersion = model.ModelVersions.First(
Author = $"by {model.Creator.Username}", x => !x.BaseModel.Contains("Turbo", StringComparison.OrdinalIgnoreCase)
CivitModel = model ),
} Author = $"by {model.Creator.Username}",
) CivitModel = model
); }
)
);
}
catch (ApiException e)
{
// hide dialog and show error msg
logger.LogError(e, "Failed to get recommended models");
notificationService.Show(
"Failed to get recommended models",
"Please try again later or check the Model Browser tab for more models."
);
OnCloseButtonClick();
}
IsLoading = false; IsLoading = false;
} }

8
StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs

@ -114,14 +114,6 @@ public class InferenceTextToImageViewModel : InferenceGenerationViewModelBase, I
SamplerCardViewModel.IsRefinerStepsEnabled = SamplerCardViewModel.IsRefinerStepsEnabled =
e.Sender is { IsRefinerSelectionEnabled: true, SelectedRefiner: not null }; e.Sender is { IsRefinerSelectionEnabled: true, SelectedRefiner: not null };
}); });
SamplerCardViewModel
.WhenPropertyChanged(x => x.SelectedScheduler)
.Subscribe(e =>
{
e.Sender.IsDenoiseStrengthEnabled =
e.Sender.SelectedScheduler?.DisplayName.Equals("SD Turbo") ?? false;
});
} }
/// <inheritdoc /> /// <inheritdoc />

28
StabilityMatrix.Avalonia/ViewModels/Inference/SamplerCardViewModel.cs

@ -42,6 +42,12 @@ public partial class SamplerCardViewModel : LoadableViewModelBase, IParametersLo
[ObservableProperty] [ObservableProperty]
private bool isDenoiseStrengthEnabled; private bool isDenoiseStrengthEnabled;
/// <summary>
/// Temporary enable for denoise strength, used for SDTurbo.
/// Denoise will be enabled if either this or <see cref="IsDenoiseStrengthEnabled"/> is true.
/// </summary>
public bool IsDenoiseStrengthTempEnabled => SelectedScheduler == ComfyScheduler.SDTurbo;
[ObservableProperty] [ObservableProperty]
private double denoiseStrength = 0.7f; private double denoiseStrength = 0.7f;
@ -77,6 +83,7 @@ public partial class SamplerCardViewModel : LoadableViewModelBase, IParametersLo
private bool isSchedulerSelectionEnabled; private bool isSchedulerSelectionEnabled;
[ObservableProperty] [ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsDenoiseStrengthTempEnabled))]
[Required] [Required]
private ComfyScheduler? selectedScheduler = ComfyScheduler.Normal; private ComfyScheduler? selectedScheduler = ComfyScheduler.Normal;
@ -154,6 +161,10 @@ public partial class SamplerCardViewModel : LoadableViewModelBase, IParametersLo
var primaryScheduler = SelectedScheduler ?? throw new ValidationException("Scheduler not selected"); var primaryScheduler = SelectedScheduler ?? throw new ValidationException("Scheduler not selected");
e.Builder.Connections.PrimaryScheduler = primaryScheduler; e.Builder.Connections.PrimaryScheduler = primaryScheduler;
// Use Temp Conditioning that may be modified by addons
var conditioning = e.Temp.Conditioning.Unwrap();
var refinerConditioning = e.Temp.RefinerConditioning;
// Use custom sampler if SDTurbo scheduler is selected // Use custom sampler if SDTurbo scheduler is selected
if (e.Builder.Connections.PrimaryScheduler == ComfyScheduler.SDTurbo) if (e.Builder.Connections.PrimaryScheduler == ComfyScheduler.SDTurbo)
{ {
@ -189,8 +200,8 @@ public partial class SamplerCardViewModel : LoadableViewModelBase, IParametersLo
AddNoise = true, AddNoise = true,
NoiseSeed = e.Builder.Connections.Seed, NoiseSeed = e.Builder.Connections.Seed,
Cfg = CfgScale, Cfg = CfgScale,
Positive = e.Temp.Conditioning?.Positive!, Positive = conditioning.Positive,
Negative = e.Temp.Conditioning?.Negative!, Negative = conditioning.Negative,
Sampler = kSamplerSelect.Output, Sampler = kSamplerSelect.Output,
Sigmas = turboScheduler.Output, Sigmas = turboScheduler.Output,
LatentImage = primaryLatent LatentImage = primaryLatent
@ -218,8 +229,8 @@ public partial class SamplerCardViewModel : LoadableViewModelBase, IParametersLo
Scheduler = primaryScheduler.Name, Scheduler = primaryScheduler.Name,
Steps = Steps, Steps = Steps,
Cfg = CfgScale, Cfg = CfgScale,
Positive = baseConditioning.Positive, Positive = conditioning.Positive,
Negative = baseConditioning.Negative, Negative = conditioning.Negative,
LatentImage = primaryLatent, LatentImage = primaryLatent,
Denoise = DenoiseStrength, Denoise = DenoiseStrength,
} }
@ -229,9 +240,6 @@ public partial class SamplerCardViewModel : LoadableViewModelBase, IParametersLo
} }
else else
{ {
var baseConditioning = e.Builder.Connections.Base.Conditioning.Unwrap();
var refinerConditioning = e.Builder.Connections.Refiner.Conditioning.Unwrap();
// Advanced base sampler for refiner // Advanced base sampler for refiner
var sampler = e.Nodes.AddTypedNode( var sampler = e.Nodes.AddTypedNode(
new ComfyNodeBuilder.KSamplerAdvanced new ComfyNodeBuilder.KSamplerAdvanced
@ -244,8 +252,8 @@ public partial class SamplerCardViewModel : LoadableViewModelBase, IParametersLo
Cfg = CfgScale, Cfg = CfgScale,
SamplerName = primarySampler.Name, SamplerName = primarySampler.Name,
Scheduler = primaryScheduler.Name, Scheduler = primaryScheduler.Name,
Positive = baseConditioning.Positive, Positive = conditioning.Positive,
Negative = baseConditioning.Negative, Negative = conditioning.Negative,
LatentImage = primaryLatent, LatentImage = primaryLatent,
StartAtStep = 0, StartAtStep = 0,
EndAtStep = Steps, EndAtStep = Steps,
@ -265,7 +273,7 @@ public partial class SamplerCardViewModel : LoadableViewModelBase, IParametersLo
Cfg = CfgScale, Cfg = CfgScale,
SamplerName = primarySampler.Name, SamplerName = primarySampler.Name,
Scheduler = primaryScheduler.Name, Scheduler = primaryScheduler.Name,
Positive = refinerConditioning.Positive, Positive = refinerConditioning!.Positive,
Negative = refinerConditioning.Negative, Negative = refinerConditioning.Negative,
// Connect to previous sampler // Connect to previous sampler
LatentImage = sampler.Output, LatentImage = sampler.Output,

21
StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageExtensionBrowserViewModel.cs

@ -179,7 +179,12 @@ public partial class PackageExtensionBrowserViewModel : ViewModelBase, IDisposab
.Cast<IPackageStep>() .Cast<IPackageStep>()
.ToArray(); .ToArray();
var runner = new PackageModificationRunner { ShowDialogOnStart = true }; var runner = new PackageModificationRunner
{
ShowDialogOnStart = true,
ModificationCompleteTitle = "Installed Extensions",
ModificationCompleteMessage = "Finished installing extensions"
};
EventManager.Instance.OnPackageInstallProgressAdded(runner); EventManager.Instance.OnPackageInstallProgressAdded(runner);
await runner.ExecuteSteps(steps); await runner.ExecuteSteps(steps);
@ -209,7 +214,12 @@ public partial class PackageExtensionBrowserViewModel : ViewModelBase, IDisposab
.Cast<IPackageStep>() .Cast<IPackageStep>()
.ToArray(); .ToArray();
var runner = new PackageModificationRunner { ShowDialogOnStart = true }; var runner = new PackageModificationRunner
{
ShowDialogOnStart = true,
ModificationCompleteTitle = "Updated Extensions",
ModificationCompleteMessage = "Finished updating extensions"
};
EventManager.Instance.OnPackageInstallProgressAdded(runner); EventManager.Instance.OnPackageInstallProgressAdded(runner);
await runner.ExecuteSteps(steps); await runner.ExecuteSteps(steps);
@ -239,7 +249,12 @@ public partial class PackageExtensionBrowserViewModel : ViewModelBase, IDisposab
.Cast<IPackageStep>() .Cast<IPackageStep>()
.ToArray(); .ToArray();
var runner = new PackageModificationRunner { ShowDialogOnStart = true }; var runner = new PackageModificationRunner
{
ShowDialogOnStart = true,
ModificationCompleteTitle = "Uninstalled Extensions",
ModificationCompleteMessage = "Finished uninstalling extensions"
};
EventManager.Instance.OnPackageInstallProgressAdded(runner); EventManager.Instance.OnPackageInstallProgressAdded(runner);
await runner.ExecuteSteps(steps); await runner.ExecuteSteps(steps);

5
StabilityMatrix.Core/Models/PackageModification/PackageModificationRunner.cs

@ -15,6 +15,11 @@ public class PackageModificationRunner : IPackageModificationRunner
ConsoleOutput.Add(report.Message); ConsoleOutput.Add(report.Message);
} }
if (!string.IsNullOrWhiteSpace(report.Title))
{
ConsoleOutput.Add(report.Title);
}
OnProgressChanged(report); OnProgressChanged(report);
}); });

1
StabilityMatrix.Core/Models/Packages/A3WebUI.cs

@ -48,6 +48,7 @@ public class A3WebUI(
{ {
[SharedFolderType.StableDiffusion] = new[] { "models/Stable-diffusion" }, [SharedFolderType.StableDiffusion] = new[] { "models/Stable-diffusion" },
[SharedFolderType.ESRGAN] = new[] { "models/ESRGAN" }, [SharedFolderType.ESRGAN] = new[] { "models/ESRGAN" },
[SharedFolderType.GFPGAN] = new[] { "models/GFPGAN" },
[SharedFolderType.RealESRGAN] = new[] { "models/RealESRGAN" }, [SharedFolderType.RealESRGAN] = new[] { "models/RealESRGAN" },
[SharedFolderType.SwinIR] = new[] { "models/SwinIR" }, [SharedFolderType.SwinIR] = new[] { "models/SwinIR" },
[SharedFolderType.Lora] = new[] { "models/Lora" }, [SharedFolderType.Lora] = new[] { "models/Lora" },

16
StabilityMatrix.Core/Models/Packages/Extensions/GitPackageExtensionManager.cs

@ -155,13 +155,15 @@ public abstract class GitPackageExtensionManager(IPrerequisiteHelper prerequisit
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
progress?.Report(new ProgressReport(0f, $"Cloning {repositoryUri}", isIndeterminate: true)); progress?.Report(
new ProgressReport(0f, message: $"Cloning {repositoryUri}", isIndeterminate: true)
);
await prerequisiteHelper await prerequisiteHelper
.CloneGitRepository(cloneRoot, repositoryUri.ToString(), version) .CloneGitRepository(cloneRoot, repositoryUri.ToString(), version)
.ConfigureAwait(false); .ConfigureAwait(false);
progress?.Report(new ProgressReport(1f, $"Cloned {repositoryUri}")); progress?.Report(new ProgressReport(1f, message: $"Cloned {repositoryUri}"));
} }
} }
@ -191,7 +193,11 @@ public abstract class GitPackageExtensionManager(IPrerequisiteHelper prerequisit
.ConfigureAwait(false); .ConfigureAwait(false);
progress?.Report( progress?.Report(
new ProgressReport(0f, $"Updating git repository {repoPath.Name}", isIndeterminate: true) new ProgressReport(
0f,
message: $"Updating git repository {repoPath.Name}",
isIndeterminate: true
)
); );
// If version not provided, use current branch // If version not provided, use current branch
@ -206,7 +212,7 @@ public abstract class GitPackageExtensionManager(IPrerequisiteHelper prerequisit
.UpdateGitRepository(repoPath, remoteUrlResult.StandardOutput!.Trim(), version) .UpdateGitRepository(repoPath, remoteUrlResult.StandardOutput!.Trim(), version)
.ConfigureAwait(false); .ConfigureAwait(false);
progress?.Report(new ProgressReport(1f, $"Updated git repository {repoPath.Name}")); progress?.Report(new ProgressReport(1f, message: $"Updated git repository {repoPath.Name}"));
} }
} }
@ -233,5 +239,7 @@ public abstract class GitPackageExtensionManager(IPrerequisiteHelper prerequisit
await path.DeleteAsync().ConfigureAwait(false); await path.DeleteAsync().ConfigureAwait(false);
} }
} }
progress?.Report(new ProgressReport(1f, message: "Uninstalled extension"));
} }
} }

Loading…
Cancel
Save