From 1879c57e333eb9158409de60de30c59ea0f58d3b Mon Sep 17 00:00:00 2001 From: JT Date: Thu, 23 Nov 2023 23:15:02 -0800 Subject: [PATCH 01/22] Added category teaching tip, added MotionModule CivitModelType, and updated TI description to indicate that it is also embeddings --- .../Languages/Resources.Designer.cs | 9 +++++++++ StabilityMatrix.Avalonia/Languages/Resources.resx | 3 +++ .../CheckpointManager/CheckpointFolder.cs | 4 ++-- .../ViewModels/CheckpointsPageViewModel.cs | 14 ++++++++++++++ .../Views/CheckpointBrowserPage.axaml | 4 +++- .../Views/CheckpointsPage.axaml | 9 ++++++++- StabilityMatrix.Core/Models/Api/CivitModelType.cs | 9 ++++++++- StabilityMatrix.Core/Models/Packages/A3WebUI.cs | 2 +- .../Models/Settings/TeachingTip.cs | 1 + StabilityMatrix.Core/Models/SharedFolderType.cs | 3 +++ 10 files changed, 52 insertions(+), 6 deletions(-) diff --git a/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs b/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs index bec75635..efb0216f 100644 --- a/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs +++ b/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs @@ -2039,6 +2039,15 @@ namespace StabilityMatrix.Avalonia.Languages { } } + /// + /// Looks up a localized string similar to Additional folders such as IPAdapters and TextualInversions (embeddings) can be enabled here. + /// + public static string TeachingTip_MoreCheckpointCategories { + get { + return ResourceManager.GetString("TeachingTip_MoreCheckpointCategories", resourceCulture); + } + } + /// /// Looks up a localized string similar to The app will relaunch after updating. /// diff --git a/StabilityMatrix.Avalonia/Languages/Resources.resx b/StabilityMatrix.Avalonia/Languages/Resources.resx index bc1d4502..76da7ad6 100644 --- a/StabilityMatrix.Avalonia/Languages/Resources.resx +++ b/StabilityMatrix.Avalonia/Languages/Resources.resx @@ -810,4 +810,7 @@ Trigger words: + + Additional folders such as IPAdapters and TextualInversions (embeddings) can be enabled here + diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs index b5fc8d53..d267ce3b 100644 --- a/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs +++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs @@ -90,8 +90,8 @@ public partial class CheckpointFolder : ViewModelBase public string TitleWithFilesCount => CheckpointFiles.Any() || SubFolders.Any(f => f.CheckpointFiles.Any()) - ? $"{Title} ({CheckpointFiles.Count + SubFolders.Sum(folder => folder.CheckpointFiles.Count)})" - : Title; + ? $"{FolderType.GetDescription() ?? FolderType.GetStringValue()} ({CheckpointFiles.Count + SubFolders.Sum(folder => folder.CheckpointFiles.Count)})" + : FolderType.GetDescription() ?? FolderType.GetStringValue(); public ProgressViewModel Progress { get; } = new(); diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs index fdfa01a0..3ef10603 100644 --- a/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs @@ -20,6 +20,7 @@ using StabilityMatrix.Core.Processes; using StabilityMatrix.Core.Services; using Symbol = FluentIcons.Common.Symbol; using SymbolIconSource = FluentIcons.FluentAvalonia.SymbolIconSource; +using TeachingTip = StabilityMatrix.Core.Models.Settings.TeachingTip; namespace StabilityMatrix.Avalonia.ViewModels; @@ -55,6 +56,9 @@ public partial class CheckpointsPageViewModel : PageViewModelBase [ObservableProperty] private string searchFilter = string.Empty; + [ObservableProperty] + private bool isCategoryTipOpen; + partial void OnIsImportAsConnectedChanged(bool value) { if ( @@ -114,6 +118,16 @@ public partial class CheckpointsPageViewModel : PageViewModelBase if (Design.IsDesignMode) return; + if ( + !settingsManager.Settings.SeenTeachingTips.Contains(TeachingTip.CheckpointCategoriesTip) + ) + { + IsCategoryTipOpen = true; + settingsManager.Transaction( + s => s.SeenTeachingTips.Add(TeachingTip.CheckpointCategoriesTip) + ); + } + IsLoading = CheckpointFolders.Count == 0; IsIndexing = CheckpointFolders.Count > 0; // GetStuff(); diff --git a/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml b/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml index ff15c70a..7bf3dde6 100644 --- a/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml +++ b/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml @@ -406,7 +406,9 @@ Grid.Row="1" Margin="8,0,8,0" ScrollChanged="ScrollViewer_OnScrollChanged"> - + diff --git a/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml b/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml index 5c0c9fa5..0ae40150 100644 --- a/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml +++ b/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml @@ -433,6 +433,7 @@ - + + + (SharedFolderType.StableDiffusion)] Checkpoint, + [ConvertTo(SharedFolderType.TextualInversion)] TextualInversion, + [ConvertTo(SharedFolderType.Hypernetwork)] Hypernetwork, + [ConvertTo(SharedFolderType.Lora)] LORA, + [ConvertTo(SharedFolderType.ControlNet)] Controlnet, + [ConvertTo(SharedFolderType.LyCORIS)] LoCon, + [ConvertTo(SharedFolderType.VAE)] VAE, - + // Unused/obsolete/unknown/meta options AestheticGradient, Model, + MotionModule, Poses, Upscaler, Wildcards, diff --git a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs index fb580ff3..bad8db64 100644 --- a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs +++ b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs @@ -149,7 +149,7 @@ public class A3WebUI : BaseGitPackage Name = "No Half", Type = LaunchOptionType.Bool, Description = "Do not switch the model to 16-bit floats", - InitialValue = HardwareHelper.HasAmdGpu(), + InitialValue = HardwareHelper.PreferRocm() || HardwareHelper.PreferDirectML(), Options = new() { "--no-half" } }, new() diff --git a/StabilityMatrix.Core/Models/Settings/TeachingTip.cs b/StabilityMatrix.Core/Models/Settings/TeachingTip.cs index 140bbafd..04dcd720 100644 --- a/StabilityMatrix.Core/Models/Settings/TeachingTip.cs +++ b/StabilityMatrix.Core/Models/Settings/TeachingTip.cs @@ -11,6 +11,7 @@ public record TeachingTip(string Value) : StringValue(Value) { public static TeachingTip AccountsCredentialsStorageNotice => new("AccountsCredentialsStorageNotice"); + public static TeachingTip CheckpointCategoriesTip => new("CheckpointCategoriesTip"); /// public override string ToString() diff --git a/StabilityMatrix.Core/Models/SharedFolderType.cs b/StabilityMatrix.Core/Models/SharedFolderType.cs index e4f830fb..4cc66439 100644 --- a/StabilityMatrix.Core/Models/SharedFolderType.cs +++ b/StabilityMatrix.Core/Models/SharedFolderType.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using StabilityMatrix.Core.Extensions; namespace StabilityMatrix.Core.Models; @@ -21,6 +22,8 @@ public enum SharedFolderType ApproxVAE = 1 << 11, Karlo = 1 << 12, DeepDanbooru = 1 << 13, + + [Description("TextualInversion (Embeddings)")] TextualInversion = 1 << 14, Hypernetwork = 1 << 15, ControlNet = 1 << 16, From e6b6a929c5285227030c8a025474c5ecf1952d41 Mon Sep 17 00:00:00 2001 From: JT Date: Fri, 24 Nov 2023 13:55:22 -0800 Subject: [PATCH 02/22] Add MotionModule CivitModelType to fix model browser errors --- CHANGELOG.md | 4 ++++ StabilityMatrix.Core/Models/Api/CivitModelType.cs | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2aa402d..022bd130 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ 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/), and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). +## v2.6.4 +### Fixed +- Fixed errors preventing Model Browser from finding results with certain search queries + ## v2.6.3 ### Fixed - Fixed InvalidOperationException during prerequisite installs on certain platforms where process name and duration reporting are not supported diff --git a/StabilityMatrix.Core/Models/Api/CivitModelType.cs b/StabilityMatrix.Core/Models/Api/CivitModelType.cs index 0331e252..447ec92d 100644 --- a/StabilityMatrix.Core/Models/Api/CivitModelType.cs +++ b/StabilityMatrix.Core/Models/Api/CivitModelType.cs @@ -11,22 +11,29 @@ public enum CivitModelType { [ConvertTo(SharedFolderType.StableDiffusion)] Checkpoint, + [ConvertTo(SharedFolderType.TextualInversion)] TextualInversion, + [ConvertTo(SharedFolderType.Hypernetwork)] Hypernetwork, + [ConvertTo(SharedFolderType.Lora)] LORA, + [ConvertTo(SharedFolderType.ControlNet)] Controlnet, + [ConvertTo(SharedFolderType.LyCORIS)] LoCon, + [ConvertTo(SharedFolderType.VAE)] VAE, - + // Unused/obsolete/unknown/meta options AestheticGradient, Model, + MotionModule, Poses, Upscaler, Wildcards, From d1e80ee60405a2cca82607107a12d4fc2758648f Mon Sep 17 00:00:00 2001 From: JT Date: Fri, 24 Nov 2023 14:03:13 -0800 Subject: [PATCH 03/22] also fix enum converter for CivitModelType --- StabilityMatrix.Avalonia/App.axaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/StabilityMatrix.Avalonia/App.axaml.cs b/StabilityMatrix.Avalonia/App.axaml.cs index d15dc543..475d50f8 100644 --- a/StabilityMatrix.Avalonia/App.axaml.cs +++ b/StabilityMatrix.Avalonia/App.axaml.cs @@ -423,6 +423,7 @@ public sealed class App : Application }; jsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter()); jsonSerializerOptions.Converters.Add(new DefaultUnknownEnumConverter()); + jsonSerializerOptions.Converters.Add(new DefaultUnknownEnumConverter()); jsonSerializerOptions.Converters.Add( new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) ); From 0eada0e5b3a1866b2b60a9f8b846fe33bdc8e991 Mon Sep 17 00:00:00 2001 From: Ionite Date: Fri, 24 Nov 2023 18:47:29 -0500 Subject: [PATCH 04/22] DefaultUnknownEnumConverter support for EnumMember values and caching --- .../Json/DefaultUnknownEnumConverter.cs | 122 +++++++++++------- .../Models/Api/CivitFileType.cs | 9 +- .../Models/Api/CivitModelType.cs | 5 +- 3 files changed, 84 insertions(+), 52 deletions(-) diff --git a/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs b/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs index 2de1f45d..7422eebb 100644 --- a/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs +++ b/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs @@ -1,38 +1,95 @@ -using System.Text.Json; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using System.Runtime.Serialization; +using System.Text.Json; using System.Text.Json.Serialization; -using StabilityMatrix.Core.Extensions; namespace StabilityMatrix.Core.Converters.Json; -public class DefaultUnknownEnumConverter : JsonConverter +public class DefaultUnknownEnumConverter< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T +> : JsonConverter where T : Enum { + /// + /// Lazy initialization for . + /// + private readonly Lazy> _enumMemberValuesLazy = + new( + () => + typeof(T) + .GetFields() + .Where(field => field.IsStatic) + .Select( + field => + new + { + FieldName = field.Name, + FieldValue = (T)field.GetValue(null)!, + EnumMemberValue = field + .GetCustomAttributes(false) + .FirstOrDefault() + ?.Value?.ToString() + } + ) + .ToDictionary(x => x.EnumMemberValue ?? x.FieldName, x => x.FieldValue) + ); + + /// + /// Gets a dictionary of enum member values, keyed by the EnumMember attribute value, or the field name if no EnumMember attribute is present. + /// + private Dictionary EnumMemberValues => _enumMemberValuesLazy.Value; + + /// + /// Lazy initialization for . + /// + private readonly Lazy> _enumMemberNamesLazy; + + /// + /// Gets a dictionary of enum member names, keyed by the enum member value. + /// + private Dictionary EnumMemberNames => _enumMemberNamesLazy.Value; + + /// + /// Gets the value of the "Unknown" enum member, or the 0 value if no "Unknown" member is present. + /// + private T UnknownValue => + EnumMemberValues.TryGetValue("Unknown", out var res) ? res : (T)Enum.ToObject(typeof(T), 0); + + /// + public override bool HandleNull => true; + + public DefaultUnknownEnumConverter() + { + _enumMemberNamesLazy = new Lazy>( + () => EnumMemberValues.ToDictionary(x => x.Value, x => x.Key) + ); + } + + /// public override T Read( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options ) { - if (reader.TokenType != JsonTokenType.String) - { - throw new JsonException(); - } - - var enumText = reader.GetString()?.Replace(" ", "_"); - if (Enum.TryParse(typeof(T), enumText, true, out var result)) + if (reader.TokenType is not (JsonTokenType.String or JsonTokenType.PropertyName)) { - return (T)result!; + throw new JsonException("Expected String or PropertyName token"); } - // Unknown value handling - if (Enum.TryParse(typeof(T), "Unknown", true, out var unknownResult)) + if (reader.GetString() is { } readerString) { - return (T)unknownResult!; + if (EnumMemberValues.TryGetValue(readerString, out var enumMemberValue)) + { + return enumMemberValue; + } } - throw new JsonException($"Unable to parse '{enumText}' to enum '{typeof(T)}'."); + return UnknownValue; } + /// public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options) { if (value == null) @@ -41,7 +98,7 @@ public class DefaultUnknownEnumConverter : JsonConverter return; } - writer.WriteStringValue(value.GetStringValue().Replace("_", " ")); + writer.WriteStringValue(EnumMemberNames[value]); } /// @@ -49,41 +106,12 @@ public class DefaultUnknownEnumConverter : JsonConverter ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options - ) - { - if (reader.TokenType != JsonTokenType.PropertyName) - { - throw new JsonException(); - } - - var enumText = reader.GetString()?.Replace(" ", "_"); - if (Enum.TryParse(typeof(T), enumText, true, out var result)) - { - return (T)result!; - } - - // Unknown value handling - if (Enum.TryParse(typeof(T), "Unknown", true, out var unknownResult)) - { - return (T)unknownResult!; - } - - throw new JsonException($"Unable to parse '{enumText}' to enum '{typeof(T)}'."); - } + ) => Read(ref reader, typeToConvert, options); /// public override void WriteAsPropertyName( Utf8JsonWriter writer, T? value, JsonSerializerOptions options - ) - { - if (value == null) - { - writer.WriteNullValue(); - return; - } - - writer.WritePropertyName(value.GetStringValue().Replace("_", " ")); - } + ) => Write(writer, value, options); } diff --git a/StabilityMatrix.Core/Models/Api/CivitFileType.cs b/StabilityMatrix.Core/Models/Api/CivitFileType.cs index a2a59fda..b4108924 100644 --- a/StabilityMatrix.Core/Models/Api/CivitFileType.cs +++ b/StabilityMatrix.Core/Models/Api/CivitFileType.cs @@ -1,4 +1,5 @@ -using System.Text.Json.Serialization; +using System.Runtime.Serialization; +using System.Text.Json.Serialization; using StabilityMatrix.Core.Converters.Json; namespace StabilityMatrix.Core.Models.Api; @@ -6,8 +7,10 @@ namespace StabilityMatrix.Core.Models.Api; [JsonConverter(typeof(DefaultUnknownEnumConverter))] public enum CivitFileType { + Unknown, Model, VAE, - Training_Data, - Unknown, + + [EnumMember(Value = "Training Data")] + TrainingData } diff --git a/StabilityMatrix.Core/Models/Api/CivitModelType.cs b/StabilityMatrix.Core/Models/Api/CivitModelType.cs index 447ec92d..8cead165 100644 --- a/StabilityMatrix.Core/Models/Api/CivitModelType.cs +++ b/StabilityMatrix.Core/Models/Api/CivitModelType.cs @@ -9,6 +9,8 @@ namespace StabilityMatrix.Core.Models.Api; [SuppressMessage("ReSharper", "InconsistentNaming")] public enum CivitModelType { + Unknown, + [ConvertTo(SharedFolderType.StableDiffusion)] Checkpoint, @@ -39,6 +41,5 @@ public enum CivitModelType Wildcards, Workflows, Other, - All, - Unknown + All } From 4e4be50bb70c0bbf1a9de4f3a215dd5771167f5e Mon Sep 17 00:00:00 2001 From: Ionite Date: Fri, 24 Nov 2023 18:47:52 -0500 Subject: [PATCH 05/22] Unit tests for DefaultUnknownEnumConverter --- .../Core/DefaultUnknownEnumConverterTests.cs | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 StabilityMatrix.Tests/Core/DefaultUnknownEnumConverterTests.cs diff --git a/StabilityMatrix.Tests/Core/DefaultUnknownEnumConverterTests.cs b/StabilityMatrix.Tests/Core/DefaultUnknownEnumConverterTests.cs new file mode 100644 index 00000000..b0930376 --- /dev/null +++ b/StabilityMatrix.Tests/Core/DefaultUnknownEnumConverterTests.cs @@ -0,0 +1,81 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using StabilityMatrix.Core.Converters.Json; + +namespace StabilityMatrix.Tests.Core; + +[TestClass] +public class DefaultUnknownEnumConverterTests +{ + [TestMethod] + [ExpectedException(typeof(JsonException))] + public void TestDeserialize_NormalEnum_ShouldError() + { + const string json = "\"SomeUnknownValue\""; + + JsonSerializer.Deserialize(json); + } + + [TestMethod] + public void TestDeserialize_UnknownEnum_ShouldConvert() + { + const string json = "\"SomeUnknownValue\""; + + var result = JsonSerializer.Deserialize(json); + + Assert.AreEqual(UnknownEnum.Unknown, result); + } + + [TestMethod] + public void TestDeserialize_DefaultEnum_ShouldConvert() + { + const string json = "\"SomeUnknownValue\""; + + var result = JsonSerializer.Deserialize(json); + + Assert.AreEqual(DefaultEnum.CustomDefault, result); + } + + [TestMethod] + public void TestSerialize_UnknownEnum_ShouldConvert() + { + const string expected = "\"Unknown\""; + + var result = JsonSerializer.Serialize(UnknownEnum.Unknown); + + Assert.AreEqual(expected, result); + } + + [TestMethod] + public void TestSerialize_DefaultEnum_ShouldConvert() + { + const string expected = "\"CustomDefault\""; + + var result = JsonSerializer.Serialize(DefaultEnum.CustomDefault); + + Assert.AreEqual(expected, result); + } + + private enum NormalEnum + { + Unknown, + Value1, + Value2 + } + + [JsonConverter(typeof(DefaultUnknownEnumConverter))] + private enum UnknownEnum + { + Unknown, + Value1, + Value2 + } + + [JsonConverter(typeof(DefaultUnknownEnumConverter))] + private enum DefaultEnum + { + CustomDefault, + Value1, + Value2 + } +} From 90b5f5b6f174eebd14ccc6b40e2ccac2fc67a423 Mon Sep 17 00:00:00 2001 From: Ionite Date: Fri, 24 Nov 2023 19:19:34 -0500 Subject: [PATCH 06/22] Fix WaitForExitConditionAsync errors --- StabilityMatrix.Core/Helper/ArchiveHelper.cs | 30 ++++----- .../Processes/ProcessRunner.cs | 66 ++++++------------- 2 files changed, 34 insertions(+), 62 deletions(-) diff --git a/StabilityMatrix.Core/Helper/ArchiveHelper.cs b/StabilityMatrix.Core/Helper/ArchiveHelper.cs index 8321f214..40c5d53b 100644 --- a/StabilityMatrix.Core/Helper/ArchiveHelper.cs +++ b/StabilityMatrix.Core/Helper/ArchiveHelper.cs @@ -86,22 +86,16 @@ public static partial class ArchiveHelper public static async Task Extract7Z(string archivePath, string extractDirectory) { - var args = - $"x {ProcessRunner.Quote(archivePath)} -o{ProcessRunner.Quote(extractDirectory)} -y"; + var result = await ProcessRunner + .GetProcessResultAsync( + SevenZipPath, + new[] { "x", archivePath, "-o" + ProcessRunner.Quote(extractDirectory), "-y" } + ) + .ConfigureAwait(false); - Logger.Debug($"Starting process '{SevenZipPath}' with arguments '{args}'"); + result.EnsureSuccessExitCode(); - using var process = new Process(); - process.StartInfo = new ProcessStartInfo(SevenZipPath, args) - { - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - CreateNoWindow = true - }; - process.Start(); - await ProcessRunner.WaitForExitConditionAsync(process); - var output = await process.StandardOutput.ReadToEndAsync(); + var output = result.StandardOutput ?? ""; try { @@ -153,8 +147,12 @@ public static partial class ArchiveHelper $"x {ProcessRunner.Quote(archivePath)} -o{ProcessRunner.Quote(extractDirectory)} -y -bsp1"; Logger.Debug($"Starting process '{SevenZipPath}' with arguments '{args}'"); - var process = ProcessRunner.StartProcess(SevenZipPath, args, outputDataReceived: onOutput); - await ProcessRunner.WaitForExitConditionAsync(process); + using var process = ProcessRunner.StartProcess( + SevenZipPath, + args, + outputDataReceived: onOutput + ); + await ProcessRunner.WaitForExitConditionAsync(process).ConfigureAwait(false); progress.Report(new ProgressReport(1f, "Finished extracting", type: ProgressType.Extract)); diff --git a/StabilityMatrix.Core/Processes/ProcessRunner.cs b/StabilityMatrix.Core/Processes/ProcessRunner.cs index 74b906bc..f29fc72c 100644 --- a/StabilityMatrix.Core/Processes/ProcessRunner.cs +++ b/StabilityMatrix.Core/Processes/ProcessRunner.cs @@ -401,35 +401,6 @@ public static class ProcessRunner return inner.Contains(' ') ? $"\"{inner}\"" : argument; } - /// - /// Check if the process exited with the expected exit code. - /// - /// Process to check. - /// Expected exit code. - /// Process stdout. - /// Process stderr. - /// Thrown if exit code does not match expected value. - // ReSharper disable once MemberCanBePrivate.Global - public static Task ValidateExitConditionAsync( - Process process, - int expectedExitCode = 0, - string? stdout = null, - string? stderr = null - ) - { - var exitCode = process.ExitCode; - if (exitCode == expectedExitCode) - { - return Task.CompletedTask; - } - - var pName = process.StartInfo.FileName; - var msg = - $"Process {pName} failed with exit-code {exitCode}. stdout: '{stdout}', stderr: '{stderr}'"; - Logger.Error(msg); - throw new ProcessException(msg); - } - /// /// Waits for process to exit, then validates exit code. /// @@ -443,25 +414,28 @@ public static class ProcessRunner CancellationToken cancelToken = default ) { - if (process is AnsiProcess) + if (!process.HasExited) { - throw new ArgumentException( - $"{nameof(WaitForExitConditionAsync)} does not support AnsiProcess, which uses custom async data reading", - nameof(process) - ); + await process.WaitForExitAsync(cancelToken).ConfigureAwait(false); } - var stdout = new StringBuilder(); - var stderr = new StringBuilder(); - process.OutputDataReceived += (_, args) => stdout.Append(args.Data); - process.ErrorDataReceived += (_, args) => stderr.Append(args.Data); - await process.WaitForExitAsync(cancelToken).ConfigureAwait(false); - await ValidateExitConditionAsync( - process, - expectedExitCode, - stdout.ToString(), - stderr.ToString() - ) - .ConfigureAwait(false); + if (process.ExitCode == expectedExitCode) + { + return; + } + + // Accessing ProcessName may error on some platforms + string? processName = null; + try + { + processName = process.ProcessName; + } + catch (SystemException) { } + + throw new ProcessException( + "Process " + + (processName == null ? "" : processName + " ") + + $"failed with exit-code {process.ExitCode}." + ); } } From 3fdeb76b5b45e4ad89ae376c6c43bc6bdcd5eda9 Mon Sep 17 00:00:00 2001 From: Ionite Date: Fri, 24 Nov 2023 19:21:15 -0500 Subject: [PATCH 07/22] Add changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 022bd130..51fbff1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ 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/), and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). +## v2.6.5 +### Fixed +- Fixed process errors when installing or updating Pip packages using the Python packages dialog + ## v2.6.4 ### Fixed - Fixed errors preventing Model Browser from finding results with certain search queries From 7d61e15d81070487e0c9ea40e79e5c28b96324d5 Mon Sep 17 00:00:00 2001 From: JT Date: Sat, 25 Nov 2023 14:36:39 -0800 Subject: [PATCH 08/22] Add RuinedFooocus & update version numbers in UI to not show commit hash if not debug build --- .../Settings/MainSettingsViewModel.cs | 4 +- .../Views/MainWindow.axaml.cs | 2 +- .../Models/Packages/FocusControlNet.cs | 2 - .../Models/Packages/RuinedFooocus.cs | 72 +++++++++++++++++++ 4 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs diff --git a/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs index 8ef5c63f..a42dfbda 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs @@ -78,7 +78,9 @@ public partial class MainSettingsViewModel : PageViewModelBase // ReSharper disable once MemberCanBeMadeStatic.Global public string AppVersion => - $"Version {Compat.AppVersion.ToDisplayString()}" + (Program.IsDebugBuild ? " (Debug)" : ""); + Program.IsDebugBuild + ? $"Version {Compat.AppVersion.ToDisplayString()} (Debug)" + : $"Version {Compat.AppVersion.WithoutMetadata()}"; // Theme section [ObservableProperty] diff --git a/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs b/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs index a1f930ba..20b4b8f0 100644 --- a/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs +++ b/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs @@ -183,7 +183,7 @@ public partial class MainWindow : AppWindowBase var tip = this.FindControl("UpdateAvailableTeachingTip")!; tip.Target = target; - tip.Subtitle = $"{Compat.AppVersion} -> {updateInfo.Version}"; + tip.Subtitle = $"{Compat.AppVersion.WithoutMetadata()} -> {updateInfo.Version}"; tip.IsOpen = true; } }); diff --git a/StabilityMatrix.Core/Models/Packages/FocusControlNet.cs b/StabilityMatrix.Core/Models/Packages/FocusControlNet.cs index f4cc8238..001b6156 100644 --- a/StabilityMatrix.Core/Models/Packages/FocusControlNet.cs +++ b/StabilityMatrix.Core/Models/Packages/FocusControlNet.cs @@ -27,10 +27,8 @@ public class FocusControlNet : Fooocus public override string Author => "fenneishi"; public override string Blurb => "Fooocus-ControlNet adds more control to the original Fooocus software."; - public override string LicenseType => "GPL-3.0"; public override string LicenseUrl => "https://github.com/fenneishi/Fooocus-ControlNet-SDXL/blob/main/LICENSE"; - public override string LaunchCommand => "launch.py"; public override Uri PreviewImageUri => new("https://github.com/fenneishi/Fooocus-ControlNet-SDXL/raw/main/asset/canny/snip.png"); public override PackageDifficulty InstallerSortOrder => PackageDifficulty.Expert; diff --git a/StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs b/StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs new file mode 100644 index 00000000..6300b259 --- /dev/null +++ b/StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs @@ -0,0 +1,72 @@ +using System.Diagnostics; +using System.Text.RegularExpressions; +using StabilityMatrix.Core.Attributes; +using StabilityMatrix.Core.Helper; +using StabilityMatrix.Core.Helper.Cache; +using StabilityMatrix.Core.Models.FileInterfaces; +using StabilityMatrix.Core.Models.Progress; +using StabilityMatrix.Core.Processes; +using StabilityMatrix.Core.Python; +using StabilityMatrix.Core.Services; + +namespace StabilityMatrix.Core.Models.Packages; + +[Singleton(typeof(BasePackage))] +public class RuinedFooocus : Fooocus +{ + public RuinedFooocus( + IGithubApiCache githubApi, + ISettingsManager settingsManager, + IDownloadService downloadService, + IPrerequisiteHelper prerequisiteHelper + ) + : base(githubApi, settingsManager, downloadService, prerequisiteHelper) { } + + public override string Name => "RuinedFooocus"; + public override string DisplayName { get; set; } = "RuinedFooocus"; + public override string Author => "runew0lf"; + public override string Blurb => + "RuinedFooocus combines the best aspects of Stable Diffusion and Midjourney into one seamless, cutting-edge experience"; + public override string LicenseUrl => + "https://github.com/runew0lf/RuinedFooocus/blob/main/LICENSE"; + public override Uri PreviewImageUri => + new("https://raw.githubusercontent.com/runew0lf/pmmconfigs/main/RuinedFooocus_ss.png"); + public override PackageDifficulty InstallerSortOrder => PackageDifficulty.Expert; + + public override async Task InstallPackage( + string installLocation, + TorchVersion torchVersion, + SharedFolderMethod selectedSharedFolderMethod, + DownloadPackageVersionOptions versionOptions, + IProgress? progress = null, + Action? onConsoleOutput = null + ) + { + if (torchVersion == TorchVersion.Cuda) + { + var venvRunner = await SetupVenv(installLocation, forceRecreate: true) + .ConfigureAwait(false); + + progress?.Report(new ProgressReport(-1f, "Installing torch...", isIndeterminate: true)); + + await InstallCudaTorch(venvRunner, progress, onConsoleOutput).ConfigureAwait(false); + + var requirements = new FilePath(installLocation, "requirements_versions.txt"); + await venvRunner + .PipInstallFromRequirements(requirements, onConsoleOutput, excludes: "torch") + .ConfigureAwait(false); + } + else + { + await base.InstallPackage( + installLocation, + torchVersion, + selectedSharedFolderMethod, + versionOptions, + progress, + onConsoleOutput + ) + .ConfigureAwait(false); + } + } +} From d2feb27d2f127ede7cf8499da429775ab0e5cae4 Mon Sep 17 00:00:00 2001 From: JT Date: Sat, 25 Nov 2023 14:37:48 -0800 Subject: [PATCH 09/22] chagenlog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index af766645..1e60a65c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2 ## v2.7.0-dev.3 ### Added +- New package: [RuinedFooocus](https://github.com/runew0lf/RuinedFooocus) #### Model Browser - Right clicking anywhere on the model card will open the same menu as the three-dots button - New model downloads will save trigger words in metadata, if available From 5a36d8831c5eca3663ffbf4402bb464539c25116 Mon Sep 17 00:00:00 2001 From: JT Date: Sat, 25 Nov 2023 14:52:29 -0800 Subject: [PATCH 10/22] use ToDisplayString --- .../ViewModels/Settings/MainSettingsViewModel.cs | 4 +--- StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs index a42dfbda..8ef5c63f 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs @@ -78,9 +78,7 @@ public partial class MainSettingsViewModel : PageViewModelBase // ReSharper disable once MemberCanBeMadeStatic.Global public string AppVersion => - Program.IsDebugBuild - ? $"Version {Compat.AppVersion.ToDisplayString()} (Debug)" - : $"Version {Compat.AppVersion.WithoutMetadata()}"; + $"Version {Compat.AppVersion.ToDisplayString()}" + (Program.IsDebugBuild ? " (Debug)" : ""); // Theme section [ObservableProperty] diff --git a/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs b/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs index 20b4b8f0..971d7c9a 100644 --- a/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs +++ b/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs @@ -32,6 +32,7 @@ using StabilityMatrix.Avalonia.Services; using StabilityMatrix.Avalonia.ViewModels; using StabilityMatrix.Avalonia.ViewModels.Base; using StabilityMatrix.Core.Attributes; +using StabilityMatrix.Core.Extensions; using StabilityMatrix.Core.Helper; using StabilityMatrix.Core.Models.Update; using StabilityMatrix.Core.Processes; @@ -183,7 +184,7 @@ public partial class MainWindow : AppWindowBase var tip = this.FindControl("UpdateAvailableTeachingTip")!; tip.Target = target; - tip.Subtitle = $"{Compat.AppVersion.WithoutMetadata()} -> {updateInfo.Version}"; + tip.Subtitle = $"{Compat.AppVersion.ToDisplayString()} -> {updateInfo.Version}"; tip.IsOpen = true; } }); From 57303be06c02b90ed43aefc0b17b1db0cd3f4822 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 26 Nov 2023 15:40:37 -0500 Subject: [PATCH 11/22] Add IOCommands for shared OpenUrlCommand --- .../Helpers/IOCommands.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 StabilityMatrix.Avalonia/Helpers/IOCommands.cs diff --git a/StabilityMatrix.Avalonia/Helpers/IOCommands.cs b/StabilityMatrix.Avalonia/Helpers/IOCommands.cs new file mode 100644 index 00000000..d60c7725 --- /dev/null +++ b/StabilityMatrix.Avalonia/Helpers/IOCommands.cs @@ -0,0 +1,19 @@ +using CommunityToolkit.Mvvm.Input; +using StabilityMatrix.Core.Processes; + +namespace StabilityMatrix.Avalonia.Helpers; + +public static class IOCommands +{ + public static RelayCommand OpenUrlCommand { get; } = + new( + url => + { + if (string.IsNullOrWhiteSpace(url)) + return; + + ProcessRunner.OpenUrl(url); + }, + url => !string.IsNullOrWhiteSpace(url) + ); +} From a54d17905a71e92493bf4eddff06a09bb49bf36a Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 26 Nov 2023 15:41:20 -0500 Subject: [PATCH 12/22] CivitCreator to record, add computed ProfileUrl --- StabilityMatrix.Core/Models/Api/CivitCreator.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/StabilityMatrix.Core/Models/Api/CivitCreator.cs b/StabilityMatrix.Core/Models/Api/CivitCreator.cs index 00ecc6a6..3cbb7ccc 100644 --- a/StabilityMatrix.Core/Models/Api/CivitCreator.cs +++ b/StabilityMatrix.Core/Models/Api/CivitCreator.cs @@ -2,11 +2,14 @@ namespace StabilityMatrix.Core.Models.Api; -public class CivitCreator +public record CivitCreator { [JsonPropertyName("username")] - public string Username { get; set; } - + public string? Username { get; init; } + [JsonPropertyName("image")] - public string? Image { get; set; } + public string? Image { get; init; } + + [JsonIgnore] + public string? ProfileUrl => Username is null ? null : $"https://civitai.com/user/{Username}"; } From b9e4c6dac6fe64603893e88497f8351dc2d33d48 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 26 Nov 2023 15:41:52 -0500 Subject: [PATCH 13/22] Add notification handler for cache fetch errors --- .../ViewModels/CheckpointBrowserViewModel.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserViewModel.cs index c3b97ec2..9c1f88c3 100644 --- a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserViewModel.cs @@ -470,12 +470,14 @@ public partial class CheckpointBrowserViewModel : PageViewModelBase } // See if query is cached - var cachedQuery = await liteDbContext.CivitModelQueryCache - .IncludeAll() - .FindByIdAsync(ObjectHash.GetMd5Guid(modelRequest)); + var cachedQueryResult = await notificationService.TryAsync( + liteDbContext.CivitModelQueryCache + .IncludeAll() + .FindByIdAsync(ObjectHash.GetMd5Guid(modelRequest)) + ); // If cached, update model cards - if (cachedQuery is not null) + if (cachedQueryResult.Result is { } cachedQuery) { var elapsed = timer.Elapsed; Logger.Debug( From 2763f9d866457ab2dc64a87a9b640c1dc80aa027 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 26 Nov 2023 15:42:13 -0500 Subject: [PATCH 14/22] Design data for usernames --- StabilityMatrix.Avalonia/DesignData/DesignData.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/StabilityMatrix.Avalonia/DesignData/DesignData.cs b/StabilityMatrix.Avalonia/DesignData/DesignData.cs index e1b3bb9f..09f3a993 100644 --- a/StabilityMatrix.Avalonia/DesignData/DesignData.cs +++ b/StabilityMatrix.Avalonia/DesignData/DesignData.cs @@ -310,7 +310,12 @@ public static class DesignData Stats = new CivitModelStats { Rating = 3.5, RatingCount = 24 }, ModelVersions = [ new() { Name = "v1.2.2-Inpainting" } - ] + ], + Creator = new CivitCreator + { + Image = "https://gravatar.com/avatar/fe74084ae8a081dc2283f5bde4736756ad?f=y&d=retro", + Username = "creator-1" + } }; }), dialogFactory.Get(vm => @@ -334,7 +339,12 @@ public static class DesignData } } } - ] + ], + Creator = new CivitCreator + { + Image = "https://gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50?f=y&d=retro", + Username = "creator-2" + } }; }) }; From 5d1a8d04f4b726cd67d3171ed50f65b224677396 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 26 Nov 2023 15:49:18 -0500 Subject: [PATCH 15/22] Use OnInitialLoadedAsync for main window OnLoadedAsync was firing when dialogs are closed, not just on startup --- .../ViewModels/Base/ViewModelBase.cs | 20 +++++++++++-------- .../ViewModels/MainWindowViewModel.cs | 7 +++++-- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/StabilityMatrix.Avalonia/ViewModels/Base/ViewModelBase.cs b/StabilityMatrix.Avalonia/ViewModels/Base/ViewModelBase.cs index 0d9899cc..35a620ee 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Base/ViewModelBase.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Base/ViewModelBase.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using AsyncAwaitBestPractices; +using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using JetBrains.Annotations; using StabilityMatrix.Avalonia.Models; @@ -39,7 +40,10 @@ public class ViewModelBase : ObservableValidator, IRemovableListItem if (!ViewModelState.HasFlag(ViewModelState.InitialLoaded)) { ViewModelState |= ViewModelState.InitialLoaded; + OnInitialLoaded(); + + Dispatcher.UIThread.InvokeAsync(OnInitialLoadedAsync).SafeFireAndForget(); } } @@ -54,10 +58,13 @@ public class ViewModelBase : ObservableValidator, IRemovableListItem /// Runs on the UI thread via Dispatcher.UIThread.InvokeAsync. /// The view loading will not wait for this to complete. /// - public virtual Task OnLoadedAsync() - { - return Task.CompletedTask; - } + public virtual Task OnLoadedAsync() => Task.CompletedTask; + + /// + /// Called the first time the view's LoadedEvent is fired. + /// Sets the flag. + /// + protected virtual Task OnInitialLoadedAsync() => Task.CompletedTask; /// /// Called when the view's UnloadedEvent is fired. @@ -69,8 +76,5 @@ public class ViewModelBase : ObservableValidator, IRemovableListItem /// Runs on the UI thread via Dispatcher.UIThread.InvokeAsync. /// The view loading will not wait for this to complete. /// - public virtual Task OnUnloadedAsync() - { - return Task.CompletedTask; - } + public virtual Task OnUnloadedAsync() => Task.CompletedTask; } diff --git a/StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs index c8c8befe..a9614457 100644 --- a/StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs @@ -78,7 +78,7 @@ public partial class MainWindowViewModel : ViewModelBase SelectedCategory ??= Pages.FirstOrDefault(); } - public override async Task OnLoadedAsync() + protected override async Task OnInitialLoadedAsync() { await base.OnLoadedAsync(); @@ -111,7 +111,10 @@ public partial class MainWindowViewModel : ViewModelBase var startupTime = CodeTimer.FormatTime(Program.StartupTimer.Elapsed); Logger.Info($"App started ({startupTime})"); - if (Program.Args.DebugOneClickInstall || !settingsManager.Settings.InstalledPackages.Any()) + if ( + Program.Args.DebugOneClickInstall + || settingsManager.Settings.InstalledPackages.Count == 0 + ) { var viewModel = dialogFactory.Get(); var dialog = new BetterContentDialog From bcbbcdcfcef6c973de669eb6ed5a06c3362da66e Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 26 Nov 2023 15:49:31 -0500 Subject: [PATCH 16/22] Disable view preloading --- StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs index a9614457..842df99e 100644 --- a/StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs @@ -102,10 +102,11 @@ public partial class MainWindowViewModel : ViewModelBase // Index checkpoints if we dont have Task.Run(() => settingsManager.IndexCheckpoints()).SafeFireAndForget(); - if (!App.IsHeadlessMode) + // Disable preload for now, might be causing https://github.com/LykosAI/StabilityMatrix/issues/249 + /*if (!App.IsHeadlessMode) { PreloadPages(); - } + }*/ Program.StartupTimer.Stop(); var startupTime = CodeTimer.FormatTime(Program.StartupTimer.Elapsed); From 553b31143cbf90cd8f6babc939a1618d16a5343b Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 26 Nov 2023 15:50:01 -0500 Subject: [PATCH 17/22] Add username cards to checkpoints browser --- .../Views/CheckpointBrowserPage.axaml | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml b/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml index 7bf3dde6..2d883b55 100644 --- a/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml +++ b/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml @@ -14,6 +14,7 @@ xmlns:vm="clr-namespace:StabilityMatrix.Avalonia.ViewModels.CheckpointManager" xmlns:converters="clr-namespace:StabilityMatrix.Avalonia.Converters" xmlns:asyncImageLoader="clr-namespace:AsyncImageLoader;assembly=AsyncImageLoader.Avalonia" + xmlns:helpers="clr-namespace:StabilityMatrix.Avalonia.Helpers" d:DataContext="{x:Static designData:DesignData.CheckpointBrowserViewModel}" d:DesignHeight="700" d:DesignWidth="800" @@ -137,7 +138,49 @@ - + + + + + + + + + Date: Sun, 26 Nov 2023 18:38:09 -0500 Subject: [PATCH 18/22] chagenlog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e60a65c..58f8a152 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2 #### Model Browser - Right clicking anywhere on the model card will open the same menu as the three-dots button - New model downloads will save trigger words in metadata, if available +- Model author username and avatar display, with clickable link to their profile #### Checkpoints Page - Added "Copy Trigger Words" option to the three-dots menu on the Checkpoints page (when data is available) - Added trigger words on checkpoint card and tooltip @@ -20,6 +21,8 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2 - Animated zoom effect on hovering over model images #### Checkpoints Page - Rearranged top row layout to use CommandBar +### Fixed +- Improved startup time and window load time after exiting dialogs ## v2.7.0-dev.2 ### Added From dc582bb9cdd70e035fc556a9f18f8111d5d6b52a Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 26 Nov 2023 21:23:11 -0500 Subject: [PATCH 19/22] Add debug logging for unknown enum converter --- .../Converters/Json/DefaultUnknownEnumConverter.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs b/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs index 7422eebb..eb94c00c 100644 --- a/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs +++ b/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs @@ -1,4 +1,5 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.Serialization; using System.Text.Json; @@ -84,6 +85,8 @@ public class DefaultUnknownEnumConverter< { return enumMemberValue; } + + Debug.WriteLine($"Unknown enum member value for {typeToConvert}: {readerString}"); } return UnknownValue; From 9e3e6a9c29f64696796930fe238ad3168e54ca84 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 26 Nov 2023 21:23:29 -0500 Subject: [PATCH 20/22] Add Diffusers model format and unknown handling --- StabilityMatrix.Avalonia/App.axaml.cs | 1 + StabilityMatrix.Core/Models/Api/CivitModelFormat.cs | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/StabilityMatrix.Avalonia/App.axaml.cs b/StabilityMatrix.Avalonia/App.axaml.cs index 475d50f8..c37002f2 100644 --- a/StabilityMatrix.Avalonia/App.axaml.cs +++ b/StabilityMatrix.Avalonia/App.axaml.cs @@ -424,6 +424,7 @@ public sealed class App : Application jsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter()); jsonSerializerOptions.Converters.Add(new DefaultUnknownEnumConverter()); jsonSerializerOptions.Converters.Add(new DefaultUnknownEnumConverter()); + jsonSerializerOptions.Converters.Add(new DefaultUnknownEnumConverter()); jsonSerializerOptions.Converters.Add( new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) ); diff --git a/StabilityMatrix.Core/Models/Api/CivitModelFormat.cs b/StabilityMatrix.Core/Models/Api/CivitModelFormat.cs index 50b5c689..d2e910bf 100644 --- a/StabilityMatrix.Core/Models/Api/CivitModelFormat.cs +++ b/StabilityMatrix.Core/Models/Api/CivitModelFormat.cs @@ -1,12 +1,14 @@ using System.Text.Json.Serialization; +using StabilityMatrix.Core.Converters.Json; namespace StabilityMatrix.Core.Models.Api; - -[JsonConverter(typeof(JsonStringEnumConverter))] +[JsonConverter(typeof(DefaultUnknownEnumConverter))] public enum CivitModelFormat { + Unknown, SafeTensor, PickleTensor, + Diffusers, Other } From 375f6d55cc323c7b3b0a6f3b42e66d0cd2a3dd91 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 26 Nov 2023 21:24:23 -0500 Subject: [PATCH 21/22] Add changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51fbff1d..3aa83f67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ 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/), and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). +## v2.6.6 +### Fixed +- Fixed error when receiving unknown model format values from the Model Browser + ## v2.6.5 ### Fixed - Fixed process errors when installing or updating Pip packages using the Python packages dialog From ed3b115df29be28697ecacabfe2bb6bf75bd2132 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 26 Nov 2023 23:29:06 -0500 Subject: [PATCH 22/22] Add case insensitive enum match fallback --- .../Converters/Json/DefaultUnknownEnumConverter.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs b/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs index eb94c00c..55ce6914 100644 --- a/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs +++ b/StabilityMatrix.Core/Converters/Json/DefaultUnknownEnumConverter.cs @@ -81,11 +81,23 @@ public class DefaultUnknownEnumConverter< if (reader.GetString() is { } readerString) { + // First try get exact match if (EnumMemberValues.TryGetValue(readerString, out var enumMemberValue)) { return enumMemberValue; } + // Otherwise try get case-insensitive match + if ( + EnumMemberValues.Keys.FirstOrDefault( + key => key.Equals(readerString, StringComparison.OrdinalIgnoreCase) + ) is + { } enumMemberName + ) + { + return EnumMemberValues[enumMemberName]; + } + Debug.WriteLine($"Unknown enum member value for {typeToConvert}: {readerString}"); }