From 2998ceee2122c17630e633fc611dec9df8fec6f2 Mon Sep 17 00:00:00 2001
From: JT
Date: Sat, 10 Feb 2024 22:35:50 -0800
Subject: [PATCH 01/34] Added models & refit interface for openart stuff
---
StabilityMatrix.Core/Api/IOpenArtApi.cs | 17 ++++++++
.../Models/Api/OpenArt/NodesCount.cs | 15 +++++++
.../Models/Api/OpenArt/OpenArtCreator.cs | 24 ++++++++++++
.../Api/OpenArt/OpenArtDownloadRequest.cs | 15 +++++++
.../Api/OpenArt/OpenArtDownloadResponse.cs | 12 ++++++
.../Models/Api/OpenArt/OpenArtFeedRequest.cs | 18 +++++++++
.../Api/OpenArt/OpenArtSearchRequest.cs | 18 +++++++++
.../Api/OpenArt/OpenArtSearchResponse.cs | 15 +++++++
.../Models/Api/OpenArt/OpenArtSearchResult.cs | 39 +++++++++++++++++++
.../Models/Api/OpenArt/OpenArtStats.cs | 33 ++++++++++++++++
.../Models/Api/OpenArt/OpenArtThumbnail.cs | 15 +++++++
11 files changed, 221 insertions(+)
create mode 100644 StabilityMatrix.Core/Api/IOpenArtApi.cs
create mode 100644 StabilityMatrix.Core/Models/Api/OpenArt/NodesCount.cs
create mode 100644 StabilityMatrix.Core/Models/Api/OpenArt/OpenArtCreator.cs
create mode 100644 StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDownloadRequest.cs
create mode 100644 StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDownloadResponse.cs
create mode 100644 StabilityMatrix.Core/Models/Api/OpenArt/OpenArtFeedRequest.cs
create mode 100644 StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchRequest.cs
create mode 100644 StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResponse.cs
create mode 100644 StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResult.cs
create mode 100644 StabilityMatrix.Core/Models/Api/OpenArt/OpenArtStats.cs
create mode 100644 StabilityMatrix.Core/Models/Api/OpenArt/OpenArtThumbnail.cs
diff --git a/StabilityMatrix.Core/Api/IOpenArtApi.cs b/StabilityMatrix.Core/Api/IOpenArtApi.cs
new file mode 100644
index 00000000..e13c8623
--- /dev/null
+++ b/StabilityMatrix.Core/Api/IOpenArtApi.cs
@@ -0,0 +1,17 @@
+using Refit;
+using StabilityMatrix.Core.Models.Api.OpenArt;
+
+namespace StabilityMatrix.Core.Api;
+
+[Headers("User-Agent: StabilityMatrix")]
+public interface IOpenArtApi
+{
+ [Get("/feed")]
+ Task GetFeedAsync([Query] OpenArtFeedRequest request);
+
+ [Get("/list")]
+ Task SearchAsync([Query] OpenArtFeedRequest request);
+
+ [Post("/download")]
+ Task DownloadWorkflowAsync([Body] OpenArtDownloadRequest request);
+}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/NodesCount.cs b/StabilityMatrix.Core/Models/Api/OpenArt/NodesCount.cs
new file mode 100644
index 00000000..2509dcd7
--- /dev/null
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/NodesCount.cs
@@ -0,0 +1,15 @@
+using System.Text.Json.Serialization;
+
+namespace StabilityMatrix.Core.Models.Api.OpenArt;
+
+public class NodesCount
+{
+ [JsonPropertyName("total")]
+ public long Total { get; set; }
+
+ [JsonPropertyName("primitive")]
+ public long Primitive { get; set; }
+
+ [JsonPropertyName("custom")]
+ public long Custom { get; set; }
+}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtCreator.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtCreator.cs
new file mode 100644
index 00000000..1f16dc14
--- /dev/null
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtCreator.cs
@@ -0,0 +1,24 @@
+using System.Text.Json.Serialization;
+
+namespace StabilityMatrix.Core.Models.Api.OpenArt;
+
+public class OpenArtCreator
+{
+ [JsonPropertyName("uid")]
+ public string Uid { get; set; }
+
+ [JsonPropertyName("name")]
+ public string Name { get; set; }
+
+ [JsonPropertyName("bio")]
+ public string Bio { get; set; }
+
+ [JsonPropertyName("avatar")]
+ public Uri Avatar { get; set; }
+
+ [JsonPropertyName("username")]
+ public string Username { get; set; }
+
+ [JsonPropertyName("dev_profile_url")]
+ public Uri DevProfileUrl { get; set; }
+}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDownloadRequest.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDownloadRequest.cs
new file mode 100644
index 00000000..cdf07d27
--- /dev/null
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDownloadRequest.cs
@@ -0,0 +1,15 @@
+using System.Text.Json.Serialization;
+using Refit;
+
+namespace StabilityMatrix.Core.Models.Api.OpenArt;
+
+public class OpenArtDownloadRequest
+{
+ [AliasAs("workflow_id")]
+ [JsonPropertyName("workflow_id")]
+ public required string WorkflowId { get; set; }
+
+ [AliasAs("version_tag")]
+ [JsonPropertyName("version_tag")]
+ public string VersionTag { get; set; } = "latest";
+}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDownloadResponse.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDownloadResponse.cs
new file mode 100644
index 00000000..3cb61d79
--- /dev/null
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDownloadResponse.cs
@@ -0,0 +1,12 @@
+using System.Text.Json.Serialization;
+
+namespace StabilityMatrix.Core.Models.Api.OpenArt;
+
+public class OpenArtDownloadResponse
+{
+ [JsonPropertyName("filename")]
+ public string Filename { get; set; }
+
+ [JsonPropertyName("payload")]
+ public string Payload { get; set; }
+}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtFeedRequest.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtFeedRequest.cs
new file mode 100644
index 00000000..a3f334d9
--- /dev/null
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtFeedRequest.cs
@@ -0,0 +1,18 @@
+using Refit;
+
+namespace StabilityMatrix.Core.Models.Api.OpenArt;
+
+public class OpenArtFeedRequest
+{
+ [AliasAs("category")]
+ public string Category { get; set; }
+
+ [AliasAs("sort")]
+ public string Sort { get; set; }
+
+ [AliasAs("custom_node")]
+ public string CustomNode { get; set; }
+
+ [AliasAs("cursor")]
+ public string Cursor { get; set; }
+}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchRequest.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchRequest.cs
new file mode 100644
index 00000000..27d944e3
--- /dev/null
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchRequest.cs
@@ -0,0 +1,18 @@
+using Refit;
+
+namespace StabilityMatrix.Core.Models.Api.OpenArt;
+
+public class OpenArtSearchRequest
+{
+ [AliasAs("keyword")]
+ public required string Keyword { get; set; }
+
+ [AliasAs("pageSize")]
+ public int PageSize { get; set; } = 30;
+
+ ///
+ /// 0-based index of the page to retrieve
+ ///
+ [AliasAs("currentPage")]
+ public int CurrentPage { get; set; } = 0;
+}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResponse.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResponse.cs
new file mode 100644
index 00000000..c58e308a
--- /dev/null
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResponse.cs
@@ -0,0 +1,15 @@
+using System.Text.Json.Serialization;
+
+namespace StabilityMatrix.Core.Models.Api.OpenArt;
+
+public class OpenArtSearchResponse
+{
+ [JsonPropertyName("items")]
+ public IEnumerable Items { get; set; }
+
+ [JsonPropertyName("total")]
+ public int Total { get; set; }
+
+ [JsonPropertyName("nextCursor")]
+ public string? NextCursor { get; set; }
+}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResult.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResult.cs
new file mode 100644
index 00000000..7db9bb4a
--- /dev/null
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResult.cs
@@ -0,0 +1,39 @@
+using System.Text.Json.Serialization;
+
+namespace StabilityMatrix.Core.Models.Api.OpenArt;
+
+public class OpenArtSearchResult
+{
+ [JsonPropertyName("id")]
+ public string Id { get; set; }
+
+ [JsonPropertyName("creator")]
+ public OpenArtCreator Creator { get; set; }
+
+ [JsonPropertyName("updated_at")]
+ public DateTimeOffset UpdatedAt { get; set; }
+
+ [JsonPropertyName("stats")]
+ public OpenArtStats Stats { get; set; }
+
+ [JsonPropertyName("nodes_index")]
+ public IEnumerable NodesIndex { get; set; }
+
+ [JsonPropertyName("name")]
+ public string Name { get; set; }
+
+ [JsonPropertyName("description")]
+ public string Description { get; set; }
+
+ [JsonPropertyName("created_at")]
+ public DateTimeOffset CreatedAt { get; set; }
+
+ [JsonPropertyName("categories")]
+ public IEnumerable Categories { get; set; }
+
+ [JsonPropertyName("thumbnails")]
+ public IEnumerable Thumbnails { get; set; }
+
+ [JsonPropertyName("nodes_count")]
+ public NodesCount NodesCount { get; set; }
+}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtStats.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtStats.cs
new file mode 100644
index 00000000..381db723
--- /dev/null
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtStats.cs
@@ -0,0 +1,33 @@
+using System.Text.Json.Serialization;
+
+namespace StabilityMatrix.Core.Models.Api.OpenArt;
+
+public class OpenArtStats
+{
+ [JsonPropertyName("num_shares")]
+ public int NumShares { get; set; }
+
+ [JsonPropertyName("num_bookmarks")]
+ public int NumBookmarks { get; set; }
+
+ [JsonPropertyName("num_reviews")]
+ public int NumReviews { get; set; }
+
+ [JsonPropertyName("rating")]
+ public int Rating { get; set; }
+
+ [JsonPropertyName("num_comments")]
+ public int NumComments { get; set; }
+
+ [JsonPropertyName("num_likes")]
+ public int NumLikes { get; set; }
+
+ [JsonPropertyName("num_downloads")]
+ public int NumDownloads { get; set; }
+
+ [JsonPropertyName("num_runs")]
+ public int NumRuns { get; set; }
+
+ [JsonPropertyName("num_views")]
+ public int NumViews { get; set; }
+}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtThumbnail.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtThumbnail.cs
new file mode 100644
index 00000000..05bfc22f
--- /dev/null
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtThumbnail.cs
@@ -0,0 +1,15 @@
+using System.Text.Json.Serialization;
+
+namespace StabilityMatrix.Core.Models.Api.OpenArt;
+
+public class OpenArtThumbnail
+{
+ [JsonPropertyName("width")]
+ public int Width { get; set; }
+
+ [JsonPropertyName("url")]
+ public Uri Url { get; set; }
+
+ [JsonPropertyName("height")]
+ public int Height { get; set; }
+}
From c26960ce1f8457e6ed228dc6e4c687734c03c95c Mon Sep 17 00:00:00 2001
From: JT
Date: Sun, 11 Feb 2024 18:35:51 -0800
Subject: [PATCH 02/34] added basic card UI, searching, and infiniscroll
---
Avalonia.Gif/Avalonia.Gif.csproj | 2 +-
...tabilityMatrix.Avalonia.Diagnostics.csproj | 4 +-
StabilityMatrix.Avalonia/App.axaml.cs | 16 +-
.../Models/IInfinitelyScroll.cs | 8 +
.../StabilityMatrix.Avalonia.csproj | 15 +-
.../ViewModels/OpenArtBrowserViewModel.cs | 175 +++++++++
.../Views/OpenArtBrowserPage.axaml | 340 ++++++++++++++++++
.../Views/OpenArtBrowserPage.axaml.cs | 32 ++
StabilityMatrix.Core/Api/IOpenArtApi.cs | 2 +-
.../Models/Api/OpenArt/OpenArtCreator.cs | 2 +-
.../Models/Api/OpenArt/OpenArtDateTime.cs | 14 +
.../Models/Api/OpenArt/OpenArtFeedRequest.cs | 3 +
.../Models/Api/OpenArt/OpenArtSearchResult.cs | 2 +-
.../Models/Api/OpenArt/OpenArtStats.cs | 2 +-
.../Models/Packages/SDWebForge.cs | 13 +
.../StabilityMatrix.UITests.csproj | 2 +-
16 files changed, 614 insertions(+), 18 deletions(-)
create mode 100644 StabilityMatrix.Avalonia/Models/IInfinitelyScroll.cs
create mode 100644 StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
create mode 100644 StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml
create mode 100644 StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs
create mode 100644 StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDateTime.cs
diff --git a/Avalonia.Gif/Avalonia.Gif.csproj b/Avalonia.Gif/Avalonia.Gif.csproj
index 858b974e..6a363589 100644
--- a/Avalonia.Gif/Avalonia.Gif.csproj
+++ b/Avalonia.Gif/Avalonia.Gif.csproj
@@ -10,7 +10,7 @@
true
-
+
diff --git a/StabilityMatrix.Avalonia.Diagnostics/StabilityMatrix.Avalonia.Diagnostics.csproj b/StabilityMatrix.Avalonia.Diagnostics/StabilityMatrix.Avalonia.Diagnostics.csproj
index e635ad2f..71efd8bb 100644
--- a/StabilityMatrix.Avalonia.Diagnostics/StabilityMatrix.Avalonia.Diagnostics.csproj
+++ b/StabilityMatrix.Avalonia.Diagnostics/StabilityMatrix.Avalonia.Diagnostics.csproj
@@ -19,8 +19,8 @@
-
-
+
+
diff --git a/StabilityMatrix.Avalonia/App.axaml.cs b/StabilityMatrix.Avalonia/App.axaml.cs
index f1c10ddd..05e54065 100644
--- a/StabilityMatrix.Avalonia/App.axaml.cs
+++ b/StabilityMatrix.Avalonia/App.axaml.cs
@@ -333,7 +333,8 @@ public sealed class App : Application
provider.GetRequiredService(),
provider.GetRequiredService(),
provider.GetRequiredService(),
- provider.GetRequiredService()
+ provider.GetRequiredService(),
+ provider.GetRequiredService()
},
FooterPages = { provider.GetRequiredService() }
}
@@ -556,7 +557,7 @@ public sealed class App : Application
.ConfigureHttpClient(c =>
{
c.BaseAddress = new Uri("https://civitai.com");
- c.Timeout = TimeSpan.FromSeconds(15);
+ c.Timeout = TimeSpan.FromSeconds(30);
})
.AddPolicyHandler(retryPolicy);
@@ -565,7 +566,7 @@ public sealed class App : Application
.ConfigureHttpClient(c =>
{
c.BaseAddress = new Uri("https://civitai.com");
- c.Timeout = TimeSpan.FromSeconds(15);
+ c.Timeout = TimeSpan.FromSeconds(30);
})
.AddPolicyHandler(retryPolicy);
@@ -583,6 +584,15 @@ public sealed class App : Application
new TokenAuthHeaderHandler(serviceProvider.GetRequiredService())
);
+ services
+ .AddRefitClient(defaultRefitSettings)
+ .ConfigureHttpClient(c =>
+ {
+ c.BaseAddress = new Uri("https://openart.ai/api/public/workflows");
+ c.Timeout = TimeSpan.FromSeconds(30);
+ })
+ .AddPolicyHandler(retryPolicy);
+
// Add Refit client managers
services.AddHttpClient("A3Client").AddPolicyHandler(localTimeout.WrapAsync(localRetryPolicy));
diff --git a/StabilityMatrix.Avalonia/Models/IInfinitelyScroll.cs b/StabilityMatrix.Avalonia/Models/IInfinitelyScroll.cs
new file mode 100644
index 00000000..59373816
--- /dev/null
+++ b/StabilityMatrix.Avalonia/Models/IInfinitelyScroll.cs
@@ -0,0 +1,8 @@
+using System.Threading.Tasks;
+
+namespace StabilityMatrix.Avalonia.Models;
+
+public interface IInfinitelyScroll
+{
+ Task LoadNextPageAsync();
+}
diff --git a/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj b/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
index 1190f686..63e08450 100644
--- a/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
+++ b/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
@@ -39,13 +39,14 @@
-
+
+
-
-
-
+
+
+
-
+
@@ -65,8 +66,8 @@
-
-
+
+
diff --git a/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
new file mode 100644
index 00000000..c8463037
--- /dev/null
+++ b/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
@@ -0,0 +1,175 @@
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using DynamicData;
+using DynamicData.Binding;
+using FluentAvalonia.UI.Controls;
+using Refit;
+using StabilityMatrix.Avalonia.Models;
+using StabilityMatrix.Avalonia.Services;
+using StabilityMatrix.Avalonia.ViewModels.Base;
+using StabilityMatrix.Avalonia.Views;
+using StabilityMatrix.Core.Api;
+using StabilityMatrix.Core.Attributes;
+using StabilityMatrix.Core.Models.Api.OpenArt;
+using StabilityMatrix.Core.Processes;
+using Symbol = FluentIcons.Common.Symbol;
+using SymbolIconSource = FluentIcons.Avalonia.Fluent.SymbolIconSource;
+
+namespace StabilityMatrix.Avalonia.ViewModels;
+
+[View(typeof(OpenArtBrowserPage))]
+[Singleton]
+public partial class OpenArtBrowserViewModel(IOpenArtApi openArtApi, INotificationService notificationService)
+ : PageViewModelBase,
+ IInfinitelyScroll
+{
+ private const int PageSize = 20;
+
+ public override string Title => "Workflows";
+ public override IconSource IconSource => new SymbolIconSource { Symbol = Symbol.Whiteboard };
+
+ private SourceCache searchResultsCache = new(x => x.Id);
+
+ [ObservableProperty]
+ [NotifyPropertyChangedFor(nameof(PageCount), nameof(CanGoBack), nameof(CanGoForward), nameof(CanGoToEnd))]
+ private OpenArtSearchResponse? latestSearchResponse;
+
+ [ObservableProperty]
+ private IObservableCollection searchResults =
+ new ObservableCollectionExtended();
+
+ [ObservableProperty]
+ private string searchQuery = string.Empty;
+
+ [ObservableProperty]
+ private bool isLoading;
+
+ [ObservableProperty]
+ [NotifyPropertyChangedFor(nameof(InternalPageNumber), nameof(CanGoBack))]
+ private int displayedPageNumber = 1;
+
+ public int InternalPageNumber => DisplayedPageNumber - 1;
+
+ public int PageCount =>
+ Math.Max(
+ 1,
+ Convert.ToInt32(Math.Ceiling((LatestSearchResponse?.Total ?? 0) / Convert.ToDouble(PageSize)))
+ );
+
+ public bool CanGoBack => InternalPageNumber > 0;
+
+ public bool CanGoForward => PageCount > InternalPageNumber + 1;
+
+ public bool CanGoToEnd => PageCount > InternalPageNumber + 1;
+
+ protected override void OnInitialLoaded()
+ {
+ searchResultsCache.Connect().DeferUntilLoaded().Bind(SearchResults).Subscribe();
+ }
+
+ public override async Task OnLoadedAsync()
+ {
+ if (SearchResults.Any())
+ return;
+
+ await DoSearch();
+ }
+
+ [RelayCommand]
+ private async Task FirstPage()
+ {
+ DisplayedPageNumber = 1;
+ await DoSearch();
+ }
+
+ [RelayCommand]
+ private async Task PreviousPage()
+ {
+ DisplayedPageNumber--;
+ await DoSearch(InternalPageNumber);
+ }
+
+ [RelayCommand]
+ private async Task NextPage()
+ {
+ DisplayedPageNumber++;
+ await DoSearch(InternalPageNumber);
+ }
+
+ [RelayCommand]
+ private async Task LastPage()
+ {
+ DisplayedPageNumber = PageCount;
+ await DoSearch(PageCount - 1);
+ }
+
+ [Localizable(false)]
+ [RelayCommand]
+ private void OpenModel(OpenArtSearchResult workflow)
+ {
+ ProcessRunner.OpenUrl($"https://openart.ai/workflows/{workflow.Id}");
+ }
+
+ [RelayCommand]
+ private async Task SearchButton()
+ {
+ DisplayedPageNumber = 1;
+ await DoSearch();
+ }
+
+ private async Task DoSearch(int page = 0)
+ {
+ IsLoading = true;
+
+ try
+ {
+ var response = await openArtApi.SearchAsync(
+ new OpenArtSearchRequest
+ {
+ Keyword = SearchQuery,
+ PageSize = PageSize,
+ CurrentPage = page
+ }
+ );
+
+ searchResultsCache.EditDiff(response.Items, (a, b) => a.Id == b.Id);
+ LatestSearchResponse = response;
+ }
+ catch (ApiException e)
+ {
+ notificationService.Show("Error retrieving workflows", e.Message);
+ }
+ finally
+ {
+ IsLoading = false;
+ }
+ }
+
+ public async Task LoadNextPageAsync()
+ {
+ try
+ {
+ DisplayedPageNumber++;
+ var response = await openArtApi.SearchAsync(
+ new OpenArtSearchRequest
+ {
+ Keyword = SearchQuery,
+ PageSize = PageSize,
+ CurrentPage = InternalPageNumber
+ }
+ );
+
+ searchResultsCache.AddOrUpdate(response.Items);
+ LatestSearchResponse = response;
+ }
+ catch (ApiException e)
+ {
+ notificationService.Show("Unable to load the next page", e.Message);
+ }
+ }
+}
diff --git a/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml
new file mode 100644
index 00000000..8e7a621e
--- /dev/null
+++ b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml
@@ -0,0 +1,340 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs
new file mode 100644
index 00000000..aceb5db4
--- /dev/null
+++ b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs
@@ -0,0 +1,32 @@
+using System;
+using AsyncAwaitBestPractices;
+using Avalonia.Controls;
+using StabilityMatrix.Avalonia.Controls;
+using StabilityMatrix.Avalonia.Models;
+using StabilityMatrix.Core.Attributes;
+
+namespace StabilityMatrix.Avalonia.Views;
+
+[Singleton]
+public partial class OpenArtBrowserPage : UserControlBase
+{
+ public OpenArtBrowserPage()
+ {
+ InitializeComponent();
+ }
+
+ private void ScrollViewer_OnScrollChanged(object? sender, ScrollChangedEventArgs e)
+ {
+ if (sender is not ScrollViewer scrollViewer)
+ return;
+
+ if (scrollViewer.Offset.Y == 0)
+ return;
+
+ var isAtEnd = Math.Abs(scrollViewer.Offset.Y - scrollViewer.ScrollBarMaximum.Y) < 0.1f;
+ if (isAtEnd && DataContext is IInfinitelyScroll scroll)
+ {
+ scroll.LoadNextPageAsync().SafeFireAndForget();
+ }
+ }
+}
diff --git a/StabilityMatrix.Core/Api/IOpenArtApi.cs b/StabilityMatrix.Core/Api/IOpenArtApi.cs
index e13c8623..f7e9ae19 100644
--- a/StabilityMatrix.Core/Api/IOpenArtApi.cs
+++ b/StabilityMatrix.Core/Api/IOpenArtApi.cs
@@ -10,7 +10,7 @@ public interface IOpenArtApi
Task GetFeedAsync([Query] OpenArtFeedRequest request);
[Get("/list")]
- Task SearchAsync([Query] OpenArtFeedRequest request);
+ Task SearchAsync([Query] OpenArtSearchRequest request);
[Post("/download")]
Task DownloadWorkflowAsync([Body] OpenArtDownloadRequest request);
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtCreator.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtCreator.cs
index 1f16dc14..173d1cef 100644
--- a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtCreator.cs
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtCreator.cs
@@ -20,5 +20,5 @@ public class OpenArtCreator
public string Username { get; set; }
[JsonPropertyName("dev_profile_url")]
- public Uri DevProfileUrl { get; set; }
+ public string DevProfileUrl { get; set; }
}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDateTime.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDateTime.cs
new file mode 100644
index 00000000..5f45a232
--- /dev/null
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtDateTime.cs
@@ -0,0 +1,14 @@
+using System.Text.Json.Serialization;
+
+namespace StabilityMatrix.Core.Models.Api.OpenArt;
+
+public class OpenArtDateTime
+{
+ [JsonPropertyName("_seconds")]
+ public long Seconds { get; set; }
+
+ public DateTimeOffset ToDateTimeOffset()
+ {
+ return DateTimeOffset.FromUnixTimeSeconds(Seconds);
+ }
+}
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtFeedRequest.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtFeedRequest.cs
index a3f334d9..f8dd5255 100644
--- a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtFeedRequest.cs
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtFeedRequest.cs
@@ -2,6 +2,9 @@
namespace StabilityMatrix.Core.Models.Api.OpenArt;
+///
+/// Note that parameters Category, Custom Node and Sort should be used separately
+///
public class OpenArtFeedRequest
{
[AliasAs("category")]
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResult.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResult.cs
index 7db9bb4a..9b007ced 100644
--- a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResult.cs
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResult.cs
@@ -32,7 +32,7 @@ public class OpenArtSearchResult
public IEnumerable Categories { get; set; }
[JsonPropertyName("thumbnails")]
- public IEnumerable Thumbnails { get; set; }
+ public List Thumbnails { get; set; }
[JsonPropertyName("nodes_count")]
public NodesCount NodesCount { get; set; }
diff --git a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtStats.cs b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtStats.cs
index 381db723..4afa6118 100644
--- a/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtStats.cs
+++ b/StabilityMatrix.Core/Models/Api/OpenArt/OpenArtStats.cs
@@ -14,7 +14,7 @@ public class OpenArtStats
public int NumReviews { get; set; }
[JsonPropertyName("rating")]
- public int Rating { get; set; }
+ public double Rating { get; set; }
[JsonPropertyName("num_comments")]
public int NumComments { get; set; }
diff --git a/StabilityMatrix.Core/Models/Packages/SDWebForge.cs b/StabilityMatrix.Core/Models/Packages/SDWebForge.cs
index 1e6fd16a..b58c7ec8 100644
--- a/StabilityMatrix.Core/Models/Packages/SDWebForge.cs
+++ b/StabilityMatrix.Core/Models/Packages/SDWebForge.cs
@@ -79,6 +79,19 @@ public class SDWebForge(
TorchVersion.Mps
};
+ public override Dictionary> SharedOutputFolders =>
+ new()
+ {
+ [SharedOutputType.Extras] = new[] { "output/extras-images" },
+ [SharedOutputType.Saved] = new[] { "log/images" },
+ [SharedOutputType.Img2Img] = new[] { "output/img2img-images" },
+ [SharedOutputType.Text2Img] = new[] { "output/txt2img-images" },
+ [SharedOutputType.Img2ImgGrids] = new[] { "output/img2img-grids" },
+ [SharedOutputType.Text2ImgGrids] = new[] { "output/txt2img-grids" }
+ };
+
+ public override string OutputFolderName => "output";
+
public override async Task InstallPackage(
string installLocation,
TorchVersion torchVersion,
diff --git a/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj b/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj
index 90484174..47cee6c9 100644
--- a/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj
+++ b/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj
@@ -15,7 +15,7 @@
-
+
From e87b5032beb11e3d2d57cddbe99de5ee7aa5d48c Mon Sep 17 00:00:00 2001
From: JT
Date: Sun, 11 Feb 2024 19:24:44 -0800
Subject: [PATCH 03/34] rearrange settings & add System.Drawing.Common
reference?
---
.../StabilityMatrix.Avalonia.csproj | 1 +
.../ViewModels/OpenArtBrowserViewModel.cs | 1 -
.../Settings/MainSettingsViewModel.cs | 9 +
.../Views/OpenArtBrowserPage.axaml.cs | 2 +-
.../Views/Settings/MainSettingsPage.axaml | 188 +++++++++---------
.../Models/Settings/Settings.cs | 1 +
.../StabilityMatrix.UITests.csproj | 1 +
7 files changed, 107 insertions(+), 96 deletions(-)
diff --git a/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj b/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
index 63e08450..fa070fbd 100644
--- a/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
+++ b/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
@@ -95,6 +95,7 @@
+
diff --git a/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
index c8463037..6f290e70 100644
--- a/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
diff --git a/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs
index 55b6c896..2a28e275 100644
--- a/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs
@@ -129,6 +129,9 @@ public partial class MainSettingsViewModel : PageViewModelBase
[ObservableProperty]
private HolidayMode holidayModeSetting;
+ [ObservableProperty]
+ private bool infinitelyScrollWorkflowBrowser;
+
#region System Info
private static Lazy> GpuInfosLazy { get; } =
@@ -217,6 +220,12 @@ public partial class MainSettingsViewModel : PageViewModelBase
settings => settings.HolidayModeSetting
);
+ settingsManager.RelayPropertyFor(
+ this,
+ vm => vm.InfinitelyScrollWorkflowBrowser,
+ settings => settings.IsWorkflowInfiniteScrollEnabled
+ );
+
DebugThrowAsyncExceptionCommand.WithNotificationErrorHandler(notificationService, LogLevel.Warn);
hardwareInfoUpdateTimer.Tick += OnHardwareInfoUpdateTimerTick;
diff --git a/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs
index aceb5db4..c80793c2 100644
--- a/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs
+++ b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs
@@ -23,7 +23,7 @@ public partial class OpenArtBrowserPage : UserControlBase
if (scrollViewer.Offset.Y == 0)
return;
- var isAtEnd = Math.Abs(scrollViewer.Offset.Y - scrollViewer.ScrollBarMaximum.Y) < 0.1f;
+ var isAtEnd = Math.Abs(scrollViewer.Offset.Y - scrollViewer.ScrollBarMaximum.Y) < 1f;
if (isAtEnd && DataContext is IInfinitelyScroll scroll)
{
scroll.LoadNextPageAsync().SafeFireAndForget();
diff --git a/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml b/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml
index 369c3f9a..2b846cc0 100644
--- a/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml
+++ b/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml
@@ -45,77 +45,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -204,40 +195,49 @@
-
-
-
+
+
+
+ Text="{x:Static lang:Resources.Label_Appearance}" />
-
-
-
+ Margin="8,0,8,4"
+ Header="{x:Static lang:Resources.Label_Theme}"
+ IconSource="WeatherMoon">
+
+
+
-
-
-
+ Header="{x:Static lang:Resources.Label_Language}"
+ IconSource="Character">
-
+
-
+
+
diff --git a/StabilityMatrix.Core/Models/Settings/Settings.cs b/StabilityMatrix.Core/Models/Settings/Settings.cs
index 50f34f11..fb72ac43 100644
--- a/StabilityMatrix.Core/Models/Settings/Settings.cs
+++ b/StabilityMatrix.Core/Models/Settings/Settings.cs
@@ -120,6 +120,7 @@ public class Settings
public Size InferenceImageSize { get; set; } = new(150, 190);
public Size OutputsImageSize { get; set; } = new(300, 300);
public HolidayMode HolidayModeSetting { get; set; } = HolidayMode.Automatic;
+ public bool IsWorkflowInfiniteScrollEnabled { get; set; } = true;
[JsonIgnore]
public bool IsHolidayModeActive =>
diff --git a/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj b/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj
index 47cee6c9..b1cc9ba9 100644
--- a/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj
+++ b/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj
@@ -19,6 +19,7 @@
+
From 9f430ecb652c9682d040253459f8e3b98893a0e2 Mon Sep 17 00:00:00 2001
From: JT
Date: Mon, 12 Feb 2024 21:43:38 -0800
Subject: [PATCH 04/34] settings n bug fixes
---
.../Languages/Resources.Designer.cs | 27 +++++++++++++++++++
.../Languages/Resources.resx | 9 +++++++
.../ViewModels/OpenArtBrowserViewModel.cs | 3 +++
.../Settings/MainSettingsViewModel.cs | 3 ++-
.../Views/OpenArtBrowserPage.axaml.cs | 13 +++++++--
.../Views/Settings/MainSettingsPage.axaml | 18 +++++++++++++
6 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs b/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs
index 1ff7b216..58714c39 100644
--- a/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs
+++ b/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs
@@ -1391,6 +1391,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
+ ///
+ /// Looks up a localized string similar to Infinite Scrolling.
+ ///
+ public static string Label_InfiniteScrolling {
+ get {
+ return ResourceManager.GetString("Label_InfiniteScrolling", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Inner exception.
///
@@ -2408,6 +2417,24 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
+ ///
+ /// Looks up a localized string similar to Workflow Browser.
+ ///
+ public static string Label_WorkflowBrowser {
+ get {
+ return ResourceManager.GetString("Label_WorkflowBrowser", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Workflows.
+ ///
+ public static string Label_Workflows {
+ get {
+ return ResourceManager.GetString("Label_Workflows", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to You're up to date.
///
diff --git a/StabilityMatrix.Avalonia/Languages/Resources.resx b/StabilityMatrix.Avalonia/Languages/Resources.resx
index 45e700aa..09a64ca3 100644
--- a/StabilityMatrix.Avalonia/Languages/Resources.resx
+++ b/StabilityMatrix.Avalonia/Languages/Resources.resx
@@ -972,4 +972,13 @@
Select Download Location:
+
+ Workflows
+
+
+ Infinite Scrolling
+
+
+ Workflow Browser
+
diff --git a/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
index 6f290e70..c983ef94 100644
--- a/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
@@ -151,6 +151,9 @@ public partial class OpenArtBrowserViewModel(IOpenArtApi openArtApi, INotificati
public async Task LoadNextPageAsync()
{
+ if (!CanGoForward)
+ return;
+
try
{
DisplayedPageNumber++;
diff --git a/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs
index 2a28e275..cf46f2c6 100644
--- a/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs
@@ -223,7 +223,8 @@ public partial class MainSettingsViewModel : PageViewModelBase
settingsManager.RelayPropertyFor(
this,
vm => vm.InfinitelyScrollWorkflowBrowser,
- settings => settings.IsWorkflowInfiniteScrollEnabled
+ settings => settings.IsWorkflowInfiniteScrollEnabled,
+ true
);
DebugThrowAsyncExceptionCommand.WithNotificationErrorHandler(notificationService, LogLevel.Warn);
diff --git a/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs
index c80793c2..b6a615f3 100644
--- a/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs
+++ b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml.cs
@@ -4,14 +4,18 @@ using Avalonia.Controls;
using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.Models;
using StabilityMatrix.Core.Attributes;
+using StabilityMatrix.Core.Services;
namespace StabilityMatrix.Avalonia.Views;
[Singleton]
public partial class OpenArtBrowserPage : UserControlBase
{
- public OpenArtBrowserPage()
+ private readonly ISettingsManager settingsManager;
+
+ public OpenArtBrowserPage(ISettingsManager settingsManager)
{
+ this.settingsManager = settingsManager;
InitializeComponent();
}
@@ -24,7 +28,12 @@ public partial class OpenArtBrowserPage : UserControlBase
return;
var isAtEnd = Math.Abs(scrollViewer.Offset.Y - scrollViewer.ScrollBarMaximum.Y) < 1f;
- if (isAtEnd && DataContext is IInfinitelyScroll scroll)
+
+ if (
+ isAtEnd
+ && settingsManager.Settings.IsWorkflowInfiniteScrollEnabled
+ && DataContext is IInfinitelyScroll scroll
+ )
{
scroll.LoadNextPageAsync().SafeFireAndForget();
}
diff --git a/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml b/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml
index 2b846cc0..5fb2d8a4 100644
--- a/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml
+++ b/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml
@@ -196,6 +196,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
Date: Sun, 18 Feb 2024 02:22:05 -0800
Subject: [PATCH 05/34] just put the whole json in there (for now)
---
CHANGELOG.md | 3 +
.../DesignData/DesignData.cs | 56 +
.../Languages/Resources.Designer.cs | 27 +
.../Languages/Resources.resx | 9 +
.../Models/OpenArtCustomNode.cs | 10 +
.../CheckpointBrowserCardViewModel.cs | 20 +-
.../Dialogs/OpenArtWorkflowViewModel.cs | 93 +
.../ViewModels/OpenArtBrowserViewModel.cs | 47 +-
.../Views/Dialogs/OpenArtWorkflowDialog.axaml | 100 +
.../Dialogs/OpenArtWorkflowDialog.axaml.cs | 13 +
.../Views/OpenArtBrowserPage.axaml | 14 +-
StabilityMatrix.Core/Helper/Utilities.cs | 23 +-
.../Models/Api/OpenArt/OpenArtSearchResult.cs | 6 -
StabilityMatrix.Core/Models/ComfyNodeMap.cs | 8420 +++++++++++++++++
14 files changed, 8806 insertions(+), 35 deletions(-)
create mode 100644 StabilityMatrix.Avalonia/Models/OpenArtCustomNode.cs
create mode 100644 StabilityMatrix.Avalonia/ViewModels/Dialogs/OpenArtWorkflowViewModel.cs
create mode 100644 StabilityMatrix.Avalonia/Views/Dialogs/OpenArtWorkflowDialog.axaml
create mode 100644 StabilityMatrix.Avalonia/Views/Dialogs/OpenArtWorkflowDialog.axaml.cs
create mode 100644 StabilityMatrix.Core/Models/ComfyNodeMap.cs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2e207ed4..7cefa26e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,8 +6,11 @@ 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.9.0-dev.3
+### Added
+- Added OpenArt.AI workflow browser for ComfyUI workflows
### Fixed
- Fixed StableSwarmUI not installing properly on macOS
+- Fixed output sharing for Stable Diffusion WebUI Forge
## v2.9.0-dev.2
### Added
diff --git a/StabilityMatrix.Avalonia/DesignData/DesignData.cs b/StabilityMatrix.Avalonia/DesignData/DesignData.cs
index 77d5a384..31d10d8d 100644
--- a/StabilityMatrix.Avalonia/DesignData/DesignData.cs
+++ b/StabilityMatrix.Avalonia/DesignData/DesignData.cs
@@ -36,6 +36,7 @@ using StabilityMatrix.Core.Helper.Factory;
using StabilityMatrix.Core.Models;
using StabilityMatrix.Core.Models.Api;
using StabilityMatrix.Core.Models.Api.Comfy;
+using StabilityMatrix.Core.Models.Api.OpenArt;
using StabilityMatrix.Core.Models.Database;
using StabilityMatrix.Core.Models.FileInterfaces;
using StabilityMatrix.Core.Models.PackageModification;
@@ -51,6 +52,7 @@ using HuggingFacePageViewModel = StabilityMatrix.Avalonia.ViewModels.CheckpointB
namespace StabilityMatrix.Avalonia.DesignData;
+[Localizable(false)]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
public static class DesignData
{
@@ -1008,6 +1010,60 @@ The gallery images are often inpainted, but you will get something very similar
public static ControlNetCardViewModel ControlNetCardViewModel =>
DialogFactory.Get();
+ public static OpenArtWorkflowViewModel OpenArtWorkflowViewModel =>
+ new()
+ {
+ Workflow = new OpenArtSearchResult
+ {
+ Name = "Test Workflow",
+ Creator = new OpenArtCreator
+ {
+ Name = "Test Creator Name",
+ Username = "Test Creator Username"
+ },
+ Thumbnails =
+ [
+ new OpenArtThumbnail
+ {
+ Url = new Uri(
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/a318ac1f-3ad0-48ac-98cc-79126febcc17/width=1500"
+ )
+ }
+ ],
+ NodesIndex =
+ [
+ "Anything Everywhere",
+ "Reroute",
+ "Note",
+ ".",
+ "ComfyUI's ControlNet Auxiliary Preprocessors",
+ "DWPreprocessor",
+ "PixelPerfectResolution",
+ "AIO_Preprocessor",
+ ",",
+ "ComfyUI",
+ "PreviewImage",
+ "CLIPTextEncode",
+ "EmptyLatentImage",
+ "SplitImageWithAlpha",
+ "ControlNetApplyAdvanced",
+ "JoinImageWithAlpha",
+ "LatentUpscaleBy",
+ "VAEEncode",
+ "LoadImage",
+ "ControlNetLoader",
+ "CLIPVisionLoader",
+ "SaveImage",
+ ",",
+ "ComfyUI Impact Pack",
+ "SAMLoader",
+ "UltralyticsDetectorProvider",
+ "FaceDetailer",
+ ","
+ ]
+ }
+ };
+
public static string CurrentDirectory => Directory.GetCurrentDirectory();
public static Indexer Types { get; } = new();
diff --git a/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs b/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs
index 01451192..e96ebd24 100644
--- a/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs
+++ b/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs
@@ -374,6 +374,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
+ ///
+ /// Looks up a localized string similar to Open on OpenArt.
+ ///
+ public static string Action_OpenOnOpenArt {
+ get {
+ return ResourceManager.GetString("Action_OpenOnOpenArt", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Open Project....
///
@@ -1688,6 +1697,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
+ ///
+ /// Looks up a localized string similar to Node Details.
+ ///
+ public static string Label_NodeDetails {
+ get {
+ return ResourceManager.GetString("Label_NodeDetails", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to No extensions found..
///
@@ -2435,6 +2453,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
+ ///
+ /// Looks up a localized string similar to Workflow Description.
+ ///
+ public static string Label_WorkflowDescription {
+ get {
+ return ResourceManager.GetString("Label_WorkflowDescription", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Workflows.
///
diff --git a/StabilityMatrix.Avalonia/Languages/Resources.resx b/StabilityMatrix.Avalonia/Languages/Resources.resx
index e8f7ed3f..91666c7c 100644
--- a/StabilityMatrix.Avalonia/Languages/Resources.resx
+++ b/StabilityMatrix.Avalonia/Languages/Resources.resx
@@ -984,4 +984,13 @@
Config
+
+ Open on OpenArt
+
+
+ Node Details
+
+
+ Workflow Description
+
diff --git a/StabilityMatrix.Avalonia/Models/OpenArtCustomNode.cs b/StabilityMatrix.Avalonia/Models/OpenArtCustomNode.cs
new file mode 100644
index 00000000..b075758d
--- /dev/null
+++ b/StabilityMatrix.Avalonia/Models/OpenArtCustomNode.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace StabilityMatrix.Avalonia.Models;
+
+public class OpenArtCustomNode
+{
+ public required string Title { get; set; }
+ public List Children { get; set; } = [];
+ public bool IsInstalled { get; set; }
+}
diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs
index 148712c0..bcb2ae62 100644
--- a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs
@@ -19,6 +19,7 @@ using StabilityMatrix.Avalonia.ViewModels.Dialogs;
using StabilityMatrix.Avalonia.Views.Dialogs;
using StabilityMatrix.Core.Attributes;
using StabilityMatrix.Core.Extensions;
+using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Models;
using StabilityMatrix.Core.Models.Api;
using StabilityMatrix.Core.Models.Database;
@@ -216,7 +217,7 @@ public partial class CheckpointBrowserCardViewModel : Base.ProgressViewModel
MaxDialogHeight = 950,
};
- var prunedDescription = PruneDescription(model);
+ var prunedDescription = Utilities.RemoveHtml(model.Description);
var viewModel = dialogFactory.Get();
viewModel.Dialog = dialog;
@@ -263,23 +264,6 @@ public partial class CheckpointBrowserCardViewModel : Base.ProgressViewModel
await DoImport(model, downloadPath, selectedVersion, selectedFile);
}
- private static string PruneDescription(CivitModel model)
- {
- var prunedDescription =
- model
- .Description?.Replace("
", $"{Environment.NewLine}{Environment.NewLine}")
- .Replace("
", $"{Environment.NewLine}{Environment.NewLine}")
- .Replace("
", $"{Environment.NewLine}{Environment.NewLine}")
- .Replace("", $"{Environment.NewLine}{Environment.NewLine}")
- .Replace("", $"{Environment.NewLine}{Environment.NewLine}")
- .Replace("", $"{Environment.NewLine}{Environment.NewLine}")
- .Replace("", $"{Environment.NewLine}{Environment.NewLine}")
- .Replace("", $"{Environment.NewLine}{Environment.NewLine}")
- .Replace("", $"{Environment.NewLine}{Environment.NewLine}") ?? string.Empty;
- prunedDescription = HtmlRegex().Replace(prunedDescription, string.Empty);
- return prunedDescription;
- }
-
private static async Task SaveCmInfo(
CivitModel model,
CivitModelVersion modelVersion,
diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/OpenArtWorkflowViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/OpenArtWorkflowViewModel.cs
new file mode 100644
index 00000000..94ebf773
--- /dev/null
+++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/OpenArtWorkflowViewModel.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+using CommunityToolkit.Mvvm.ComponentModel;
+using StabilityMatrix.Avalonia.Models;
+using StabilityMatrix.Avalonia.ViewModels.Base;
+using StabilityMatrix.Avalonia.Views.Dialogs;
+using StabilityMatrix.Core.Attributes;
+using StabilityMatrix.Core.Helper;
+using StabilityMatrix.Core.Models;
+using StabilityMatrix.Core.Models.Api.Comfy.Nodes;
+using StabilityMatrix.Core.Models.Api.OpenArt;
+
+namespace StabilityMatrix.Avalonia.ViewModels.Dialogs;
+
+[View(typeof(OpenArtWorkflowDialog))]
+[ManagedService]
+[Transient]
+public partial class OpenArtWorkflowViewModel : ContentDialogViewModelBase
+{
+ public required OpenArtSearchResult Workflow { get; init; }
+ public string? InstalledComfyPath { get; init; }
+
+ [ObservableProperty]
+ private ObservableCollection customNodes = [];
+
+ [ObservableProperty]
+ private string prunedDescription = string.Empty;
+
+ public override void OnLoaded()
+ {
+ CustomNodes = new ObservableCollection(ParseNodes(Workflow.NodesIndex.ToList()));
+ PrunedDescription = Utilities.RemoveHtml(Workflow.Description);
+ }
+
+ [Localizable(false)]
+ private List ParseNodes(List nodes)
+ {
+ var indexOfFirstDot = nodes.IndexOf(".");
+ if (indexOfFirstDot != -1)
+ {
+ nodes = nodes[(indexOfFirstDot + 1)..];
+ }
+
+ var installedNodes = new List();
+ if (!string.IsNullOrWhiteSpace(InstalledComfyPath))
+ {
+ installedNodes = Directory
+ .EnumerateDirectories(InstalledComfyPath)
+ .Select(
+ x => x.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries).Last()
+ )
+ .Where(x => ComfyNodeMap.Lookup.Values.FirstOrDefault(y => y.EndsWith(x)) != null)
+ .ToList();
+ }
+
+ var sections = new List();
+ OpenArtCustomNode? currentSection = null;
+
+ foreach (var node in nodes)
+ {
+ if (node is "." or ",")
+ {
+ currentSection = null; // End of the current section
+ continue;
+ }
+
+ if (currentSection == null)
+ {
+ currentSection = new OpenArtCustomNode
+ {
+ Title = node,
+ IsInstalled = installedNodes.Contains(node)
+ };
+ sections.Add(currentSection);
+ }
+ else
+ {
+ currentSection.Children.Add(node);
+ }
+ }
+
+ if (sections.FirstOrDefault(x => x.Title == "ComfyUI") != null)
+ {
+ sections = sections.Where(x => x.Title != "ComfyUI").ToList();
+ }
+
+ return sections;
+ }
+}
diff --git a/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
index c983ef94..6897ee23 100644
--- a/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
@@ -8,14 +9,18 @@ using DynamicData;
using DynamicData.Binding;
using FluentAvalonia.UI.Controls;
using Refit;
+using StabilityMatrix.Avalonia.Controls;
+using StabilityMatrix.Avalonia.Languages;
using StabilityMatrix.Avalonia.Models;
using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Base;
+using StabilityMatrix.Avalonia.ViewModels.Dialogs;
using StabilityMatrix.Avalonia.Views;
using StabilityMatrix.Core.Api;
using StabilityMatrix.Core.Attributes;
using StabilityMatrix.Core.Models.Api.OpenArt;
using StabilityMatrix.Core.Processes;
+using StabilityMatrix.Core.Services;
using Symbol = FluentIcons.Common.Symbol;
using SymbolIconSource = FluentIcons.Avalonia.Fluent.SymbolIconSource;
@@ -23,16 +28,18 @@ namespace StabilityMatrix.Avalonia.ViewModels;
[View(typeof(OpenArtBrowserPage))]
[Singleton]
-public partial class OpenArtBrowserViewModel(IOpenArtApi openArtApi, INotificationService notificationService)
- : PageViewModelBase,
- IInfinitelyScroll
+public partial class OpenArtBrowserViewModel(
+ IOpenArtApi openArtApi,
+ INotificationService notificationService,
+ ISettingsManager settingsManager
+) : PageViewModelBase, IInfinitelyScroll
{
private const int PageSize = 20;
- public override string Title => "Workflows";
+ public override string Title => Resources.Label_Workflows;
public override IconSource IconSource => new SymbolIconSource { Symbol = Symbol.Whiteboard };
- private SourceCache searchResultsCache = new(x => x.Id);
+ private readonly SourceCache searchResultsCache = new(x => x.Id);
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(PageCount), nameof(CanGoBack), nameof(CanGoForward), nameof(CanGoToEnd))]
@@ -121,6 +128,36 @@ public partial class OpenArtBrowserViewModel(IOpenArtApi openArtApi, INotificati
await DoSearch();
}
+ [RelayCommand]
+ private async Task OpenWorkflow(OpenArtSearchResult workflow)
+ {
+ var existingComfy = settingsManager.Settings.InstalledPackages.FirstOrDefault(
+ x => x.PackageName is "ComfyUI"
+ );
+
+ var dialog = new BetterContentDialog
+ {
+ IsPrimaryButtonEnabled = true,
+ IsSecondaryButtonEnabled = true,
+ PrimaryButtonText = Resources.Action_Import,
+ SecondaryButtonText = Resources.Action_Cancel,
+ DefaultButton = ContentDialogButton.Primary,
+ IsFooterVisible = true,
+ MaxDialogWidth = 750,
+ MaxDialogHeight = 850,
+ CloseOnClickOutside = true,
+ Content = new OpenArtWorkflowViewModel
+ {
+ Workflow = workflow,
+ InstalledComfyPath = existingComfy is null
+ ? null
+ : Path.Combine(settingsManager.LibraryDir, existingComfy.LibraryPath!, "custom_nodes")
+ },
+ };
+
+ await dialog.ShowAsync();
+ }
+
private async Task DoSearch(int page = 0)
{
IsLoading = true;
diff --git a/StabilityMatrix.Avalonia/Views/Dialogs/OpenArtWorkflowDialog.axaml b/StabilityMatrix.Avalonia/Views/Dialogs/OpenArtWorkflowDialog.axaml
new file mode 100644
index 00000000..af014bf1
--- /dev/null
+++ b/StabilityMatrix.Avalonia/Views/Dialogs/OpenArtWorkflowDialog.axaml
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/StabilityMatrix.Avalonia/Views/Dialogs/OpenArtWorkflowDialog.axaml.cs b/StabilityMatrix.Avalonia/Views/Dialogs/OpenArtWorkflowDialog.axaml.cs
new file mode 100644
index 00000000..e0ed1d00
--- /dev/null
+++ b/StabilityMatrix.Avalonia/Views/Dialogs/OpenArtWorkflowDialog.axaml.cs
@@ -0,0 +1,13 @@
+using StabilityMatrix.Avalonia.Controls;
+using StabilityMatrix.Core.Attributes;
+
+namespace StabilityMatrix.Avalonia.Views.Dialogs;
+
+[Transient]
+public partial class OpenArtWorkflowDialog : UserControlBase
+{
+ public OpenArtWorkflowDialog()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml
index 8e7a621e..75a6f54c 100644
--- a/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml
+++ b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml
@@ -66,6 +66,11 @@
+
+
+
-
-
-
+ CornerRadius="8"
+ Command="{StaticResource OpenWorkflowCommand}"
+ CommandParameter="{Binding }">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/StabilityMatrix.Core/Models/Settings/Settings.cs b/StabilityMatrix.Core/Models/Settings/Settings.cs
index fb72ac43..e8556ba8 100644
--- a/StabilityMatrix.Core/Models/Settings/Settings.cs
+++ b/StabilityMatrix.Core/Models/Settings/Settings.cs
@@ -34,6 +34,19 @@ public class Settings
set => ActiveInstalledPackageId = value?.Id;
}
+ [JsonPropertyName("PreferredWorkflowPackage")]
+ public Guid? PreferredWorkflowPackageId { get; set; }
+
+ [JsonIgnore]
+ public InstalledPackage? PreferredWorkflowPackage
+ {
+ get =>
+ PreferredWorkflowPackageId == null
+ ? null
+ : InstalledPackages.FirstOrDefault(x => x.Id == PreferredWorkflowPackageId);
+ set => PreferredWorkflowPackageId = value?.Id;
+ }
+
public bool HasSeenWelcomeNotification { get; set; }
public List? PathExtensions { get; set; }
public string? WebApiHost { get; set; }
From b28aef1e7bbb996e01c48f2d949fbd4c50c92e38 Mon Sep 17 00:00:00 2001
From: JT
Date: Tue, 12 Mar 2024 21:46:18 -0700
Subject: [PATCH 16/34] Update for headless kohya cli arg
---
.../Models/Packages/KohyaSs.cs | 23 ++++---------------
1 file changed, 5 insertions(+), 18 deletions(-)
diff --git a/StabilityMatrix.Core/Models/Packages/KohyaSs.cs b/StabilityMatrix.Core/Models/Packages/KohyaSs.cs
index ee197ac2..594f95ec 100644
--- a/StabilityMatrix.Core/Models/Packages/KohyaSs.cs
+++ b/StabilityMatrix.Core/Models/Packages/KohyaSs.cs
@@ -132,32 +132,19 @@ public class KohyaSs(
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
// Extra dep needed before running setup since v23.0.x
- await venvRunner.PipInstall("packaging").ConfigureAwait(false);
+ await venvRunner.PipInstall(["rich", "packaging"]).ConfigureAwait(false);
if (Compat.IsWindows)
{
- var setupSmPath = Path.Combine(installLocation, "setup", "setup_sm.py");
- var setupText = """
- import setup_windows
- import setup_common
-
- setup_common.install_requirements('requirements_windows_torch2.txt', check_no_verify_flag=False)
- setup_windows.sync_bits_and_bytes_files()
- setup_common.configure_accelerate(run_accelerate=False)
- """;
- await File.WriteAllTextAsync(setupSmPath, setupText).ConfigureAwait(false);
-
// Install
- await venvRunner.CustomInstall("setup/setup_sm.py", onConsoleOutput).ConfigureAwait(false);
- await venvRunner.PipInstall("bitsandbytes-windows").ConfigureAwait(false);
+ await venvRunner
+ .CustomInstall("setup/setup_windows.py --headless", onConsoleOutput)
+ .ConfigureAwait(false);
}
else if (Compat.IsLinux)
{
await venvRunner
- .CustomInstall(
- "setup/setup_linux.py --platform-requirements-file=requirements_linux.txt --no_run_accelerate",
- onConsoleOutput
- )
+ .CustomInstall("setup/setup_linux.py --headless", onConsoleOutput)
.ConfigureAwait(false);
}
}
From 76cf8fbd41be62778dae0a55d2bc51a6306b2521 Mon Sep 17 00:00:00 2001
From: JT
Date: Fri, 15 Mar 2024 18:04:55 -0700
Subject: [PATCH 17/34] Fix star ratings for civitai stuff
(cherry picked from commit 38013c16d6665f3401c891de8225306a84942446)
---
.../ViewModels/Dialogs/RecommendedModelsViewModel.cs | 6 ++++--
StabilityMatrix.Avalonia/Views/CivitAiBrowserPage.axaml | 6 +++---
.../Views/Dialogs/RecommendedModelsDialog.axaml | 4 ++--
StabilityMatrix.Core/Models/Api/CivitModel.cs | 7 ++++---
4 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/RecommendedModelsViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/RecommendedModelsViewModel.cs
index 41750364..e037408e 100644
--- a/StabilityMatrix.Avalonia/ViewModels/Dialogs/RecommendedModelsViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/RecommendedModelsViewModel.cs
@@ -97,9 +97,11 @@ public partial class RecommendedModelsViewModel : ContentDialogViewModelBase
new RecommendedModelItemViewModel
{
ModelVersion = model.ModelVersions.First(
- x => !x.BaseModel.Contains("Turbo", StringComparison.OrdinalIgnoreCase)
+ x =>
+ !x.BaseModel.Contains("Turbo", StringComparison.OrdinalIgnoreCase)
+ && !x.BaseModel.Contains("Lightning", StringComparison.OrdinalIgnoreCase)
),
- Author = $"by {model.Creator.Username}",
+ Author = $"by {model.Creator?.Username}",
CivitModel = model
}
)
diff --git a/StabilityMatrix.Avalonia/Views/CivitAiBrowserPage.axaml b/StabilityMatrix.Avalonia/Views/CivitAiBrowserPage.axaml
index ff25d806..ad14d1a4 100644
--- a/StabilityMatrix.Avalonia/Views/CivitAiBrowserPage.axaml
+++ b/StabilityMatrix.Avalonia/Views/CivitAiBrowserPage.axaml
@@ -319,11 +319,11 @@
Background="#66000000"
FontSize="16"
Foreground="{DynamicResource ThemeEldenRingOrangeColor}"
- Value="{Binding CivitModel.Stats.Rating}" />
+ Value="{Binding CivitModel.ModelVersionStats.Rating}" />
@@ -336,7 +336,7 @@
+ Text="{Binding CivitModel.ModelVersionStats.FavoriteCount, Converter={StaticResource KiloFormatterConverter}}" />
+ Value="{Binding ModelVersion.Stats.Rating}" />
diff --git a/StabilityMatrix.Core/Models/Api/CivitModel.cs b/StabilityMatrix.Core/Models/Api/CivitModel.cs
index 26e1afb2..be381d0c 100644
--- a/StabilityMatrix.Core/Models/Api/CivitModel.cs
+++ b/StabilityMatrix.Core/Models/Api/CivitModel.cs
@@ -48,9 +48,7 @@ public class CivitModel
var latestVersion = ModelVersions?.FirstOrDefault();
if (latestVersion?.Files != null && latestVersion.Files.Any())
{
- var latestModelFile = latestVersion.Files.FirstOrDefault(
- x => x.Type == CivitFileType.Model
- );
+ var latestModelFile = latestVersion.Files.FirstOrDefault(x => x.Type == CivitFileType.Model);
kbs = latestModelFile?.SizeKb ?? 0;
}
fullFilesSize = new FileSizeType(kbs);
@@ -65,4 +63,7 @@ public class CivitModel
ModelVersions != null && ModelVersions.Any()
? ModelVersions[0].BaseModel?.Replace("SD", "").Trim()
: string.Empty;
+
+ public CivitModelStats ModelVersionStats =>
+ ModelVersions != null && ModelVersions.Any() ? ModelVersions[0].Stats : new CivitModelStats();
}
From cbc37fb4669baeb1eb2e9d17f4b7cc8c658efdb1 Mon Sep 17 00:00:00 2001
From: JT
Date: Sat, 16 Mar 2024 19:17:29 -0700
Subject: [PATCH 18/34] backport some bug fixes from dev
---
CHANGELOG.md | 14 ++
StabilityMatrix.Avalonia/App.axaml | 2 +
.../DesignData/DesignData.cs | 3 +-
.../Models/IInfinitelyScroll.cs | 8 +
.../CivitAiBrowserViewModel.cs | 178 +++++++-----------
.../CheckpointManager/CheckpointFile.cs | 6 +
.../Dialogs/NewOneClickInstallViewModel.cs | 5 +
.../Dialogs/OneClickInstallViewModel.cs | 7 +-
.../Dialogs/SelectModelVersionViewModel.cs | 19 +-
.../Views/CivitAiBrowserPage.axaml | 82 +++-----
.../Views/CivitAiBrowserPage.axaml.cs | 16 +-
.../Dialogs/NewOneClickInstallDialog.axaml | 39 ++++
.../Views/MainWindow.axaml | 4 +-
.../Models/Api/CivitMetadata.cs | 14 +-
.../Models/Api/CivitModelStats.cs | 5 +-
.../Models/Api/CivitModelVersion.cs | 21 ++-
.../Models/Api/CivitModelsRequest.cs | 60 +++---
.../Models/PackageDifficulty.cs | 12 +-
.../IPackageModificationRunner.cs | 2 +-
.../PackageModificationRunner.cs | 2 +-
.../Models/Packages/ComfyUI.cs | 2 +-
.../Models/Packages/SDWebForge.cs | 2 +
22 files changed, 262 insertions(+), 241 deletions(-)
create mode 100644 StabilityMatrix.Avalonia/Models/IInfinitelyScroll.cs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 25b313af..90a0f515 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,20 @@ 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.9.2
+### Changed
+- Due to changes on the CivitAI API, you can no longer select a specific page in the CivitAI Model Browser
+- Due to the above API changes, new pages are now loaded via "infinite scrolling
+### Fixed
+- Fixed models not being removed from the installed models cache when deleting them from the Checkpoints page
+- Fixed model download location options for VAEs in the CivitAI Model Browser
+- Fixed One-Click install progress dialog not disappearing after completion
+- Fixed ComfyUI with Inference pop-up during one-click install appearing below the visible scroll area
+- Fixed no packages being available for one-click install on PCs without a GPU
+- Fixed missing ratings on some models in the CivitAI Model Browser
+- Fixed missing favorite count in the CivitAI Model Browser
+- Fixed recommended models not showing all SDXL models
+
## v2.9.1
### Added
- Fixed [#498](https://github.com/LykosAI/StabilityMatrix/issues/498) Added "Pony" category to CivitAI Model Browser
diff --git a/StabilityMatrix.Avalonia/App.axaml b/StabilityMatrix.Avalonia/App.axaml
index 1f039a8a..cbe8b808 100644
--- a/StabilityMatrix.Avalonia/App.axaml
+++ b/StabilityMatrix.Avalonia/App.axaml
@@ -4,6 +4,7 @@
xmlns:local="using:StabilityMatrix.Avalonia"
xmlns:idcr="using:Dock.Avalonia.Controls.Recycling"
xmlns:styling="clr-namespace:FluentAvalonia.Styling;assembly=FluentAvalonia"
+ xmlns:controls="clr-namespace:Avalonia.Labs.Controls;assembly=Avalonia.Labs.Controls"
Name="Stability Matrix"
RequestedThemeVariant="Dark">
@@ -79,6 +80,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+ Margin="8,0" />
+ VerticalAlignment="Center" />
@@ -96,7 +113,7 @@
-
+
+
+
+
+
+
+
+
-
-
+ Stretch="UniformToFill" />
+
+ Grid.RowSpan="2"
+ CornerRadius="8"
+ Width="330"
+ Height="400"
+ FontSize="100"
+ IsVisible="{Binding FirstThumbnail, Converter={x:Static ObjectConverters.IsNull}, FallbackValue=False}"
+ Value="fa-regular fa-file-code" />
+
-
+
+
+
+
+
+
+ Text="{Binding Workflow.Name}"
+ ToolTip.Tip="{Binding Workflow.Name}" />
diff --git a/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml
index 2d377dd1..867d2a62 100644
--- a/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml
+++ b/StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml
@@ -12,6 +12,7 @@
xmlns:avalonia="https://github.com/projektanker/icons.avalonia"
xmlns:input="clr-namespace:FluentAvalonia.UI.Input;assembly=FluentAvalonia"
xmlns:viewModels="clr-namespace:StabilityMatrix.Avalonia.ViewModels"
+ xmlns:labs="clr-namespace:Avalonia.Labs.Controls;assembly=Avalonia.Labs.Controls"
x:DataType="viewModels:OpenArtBrowserViewModel"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="StabilityMatrix.Avalonia.Views.OpenArtBrowserPage">
@@ -23,7 +24,7 @@
-
+
diff --git a/StabilityMatrix.Avalonia/Controls/Inference/ImageFolderCard.axaml b/StabilityMatrix.Avalonia/Controls/Inference/ImageFolderCard.axaml
index 86c40520..67b75973 100644
--- a/StabilityMatrix.Avalonia/Controls/Inference/ImageFolderCard.axaml
+++ b/StabilityMatrix.Avalonia/Controls/Inference/ImageFolderCard.axaml
@@ -9,6 +9,7 @@
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:vmInference="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Inference"
xmlns:scroll="clr-namespace:StabilityMatrix.Avalonia.Controls.Scroll"
+ xmlns:labs="clr-namespace:Avalonia.Labs.Controls;assembly=Avalonia.Labs.Controls"
x:DataType="vmInference:ImageFolderCardViewModel">
@@ -195,12 +196,11 @@
-
+ Stretch="UniformToFill" />
@@ -115,12 +116,11 @@
-
+ Source="{Binding Uri}"
+ Stretch="Uniform" />
diff --git a/StabilityMatrix.Avalonia/Models/ImageSource.cs b/StabilityMatrix.Avalonia/Models/ImageSource.cs
index 973b0bf6..0da5749d 100644
--- a/StabilityMatrix.Avalonia/Models/ImageSource.cs
+++ b/StabilityMatrix.Avalonia/Models/ImageSource.cs
@@ -58,6 +58,8 @@ public record ImageSource : IDisposable, ITemplateKey
Bitmap = bitmap;
}
+ public Uri? Uri => LocalFile?.FullPath != null ? new Uri(LocalFile.FullPath) : RemoteUrl;
+
///
public ImageSourceTemplateType TemplateKey { get; private set; }
diff --git a/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj b/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
index cda7adcd..b3fba009 100644
--- a/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
+++ b/StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
@@ -39,17 +39,17 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
-
+
+
@@ -58,10 +58,10 @@
-
-
-
-
+
+
+
+
@@ -78,25 +78,25 @@
-
+
-
+
-
+
-
-
+
+
-
+
diff --git a/StabilityMatrix.Avalonia/Styles/ControlThemes/BetterComboBoxStyles.axaml b/StabilityMatrix.Avalonia/Styles/ControlThemes/BetterComboBoxStyles.axaml
index 61d77d82..652a4ade 100644
--- a/StabilityMatrix.Avalonia/Styles/ControlThemes/BetterComboBoxStyles.axaml
+++ b/StabilityMatrix.Avalonia/Styles/ControlThemes/BetterComboBoxStyles.axaml
@@ -6,7 +6,8 @@
xmlns:mocks="using:StabilityMatrix.Avalonia.DesignData"
xmlns:models="clr-namespace:StabilityMatrix.Core.Models;assembly=StabilityMatrix.Core"
xmlns:sg="clr-namespace:SpacedGridControl.Avalonia;assembly=SpacedGridControl.Avalonia"
- xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia">
+ xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
+ xmlns:labs="clr-namespace:Avalonia.Labs.Controls;assembly=Avalonia.Labs.Controls">
@@ -42,15 +43,14 @@
ColumnSpacing="6"
RowSpacing="0">
-
+ Stretch="UniformToFill"/>
-
-
-
-
-
+ Stretch="UniformToFill"/>
-
-
-
-
-
+ Stretch="UniformToFill">
+
{
NumItemsSelected = Outputs.Count(o => o.IsSelected);
+ Console.WriteLine($"Subscribe called");
});
categoriesCache.Connect().DeferUntilLoaded().Bind(Categories).Subscribe();
@@ -395,12 +396,13 @@ public partial class OutputsPageViewModel : PageViewModelBase
var selected = Outputs.Where(o => o.IsSelected).ToList();
Debug.Assert(selected.Count == NumItemsSelected);
+
+ var imagesToRemove = new List();
foreach (var output in selected)
{
// Delete the file
var imageFile = new FilePath(output.ImageFile.AbsolutePath);
var result = await notificationService.TryAsync(imageFile.DeleteAsync());
-
if (!result.IsSuccessful)
{
continue;
@@ -413,15 +415,10 @@ public partial class OutputsPageViewModel : PageViewModelBase
await notificationService.TryAsync(sideCar.DeleteAsync());
}
- OutputsCache.Remove(output.ImageFile);
-
- // Invalidate cache
- if (ImageLoader.AsyncImageLoader is FallbackRamCachedWebImageLoader loader)
- {
- loader.RemoveAllNamesFromCache(imageFile.Name);
- }
+ imagesToRemove.Add(output.ImageFile);
}
+ OutputsCache.Remove(imagesToRemove);
NumItemsSelected = 0;
ClearSelection();
}
diff --git a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs
index 93f3534a..71d624ec 100644
--- a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs
@@ -54,7 +54,7 @@ public partial class PackageCardViewModel(
private InstalledPackage? package;
[ObservableProperty]
- private string? cardImageSource;
+ private Uri? cardImageSource;
[ObservableProperty]
private bool isUpdateAvailable;
@@ -127,7 +127,7 @@ public partial class PackageCardViewModel(
)
{
IsUnknownPackage = true;
- CardImageSource = "";
+ CardImageSource = null;
InstalledVersion = "Unknown";
}
else
@@ -135,7 +135,7 @@ public partial class PackageCardViewModel(
IsUnknownPackage = false;
var basePackage = packageFactory[value.PackageName];
- CardImageSource = basePackage?.PreviewImageUri.ToString() ?? Assets.NoImage.ToString();
+ CardImageSource = basePackage?.PreviewImageUri ?? Assets.NoImage;
InstalledVersion = value.Version?.DisplayVersion ?? "Unknown";
CanUseConfigMethod =
basePackage?.AvailableSharedFolderMethods.Contains(SharedFolderMethod.Configuration) ?? false;
diff --git a/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml b/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml
index c2831986..bbb08dae 100644
--- a/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml
+++ b/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml
@@ -13,6 +13,7 @@
xmlns:api="clr-namespace:StabilityMatrix.Core.Models.Api;assembly=StabilityMatrix.Core"
xmlns:generic="clr-namespace:System.Collections.Generic;assembly=System.Collections"
xmlns:converters="clr-namespace:StabilityMatrix.Avalonia.Converters"
+ xmlns:labs="clr-namespace:Avalonia.Labs.Controls;assembly=Avalonia.Labs.Controls"
d:DataContext="{x:Static mocks:DesignData.CheckpointsPageViewModel}"
x:CompileBindings="True"
x:DataType="vm:CheckpointsPageViewModel"
@@ -138,7 +139,7 @@
TextWrapping="WrapWithOverflow"
IsVisible="{Binding IsConnectedModel}" />
-
-
+
-
@@ -60,7 +60,7 @@
@@ -103,7 +103,7 @@
CommandParameter="{Binding CivitModel}"
IsEnabled="{Binding !IsImporting}">
- -->
-
-
+
-
+ Source="{Binding CivitModel.Creator.Image}">
+
-
-
-
@@ -52,7 +52,7 @@
@@ -121,6 +121,7 @@
CornerRadius="16"
Margin="4"
Grid.Row="0"
+ ClipToBounds="True"
HorizontalAlignment="Left"
VerticalAlignment="Bottom">
@@ -142,14 +143,16 @@
Classes="transparent"
Padding="10,4">
-
+ Source="{Binding Creator.Avatar}">
+
diff --git a/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallBrowserView.axaml.cs b/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallBrowserView.axaml.cs
index 5abbe50b..08436b3b 100644
--- a/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallBrowserView.axaml.cs
+++ b/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallBrowserView.axaml.cs
@@ -1,4 +1,6 @@
-using Avalonia.Input;
+using System.Diagnostics;
+using Avalonia.Input;
+using Avalonia.Labs.Controls;
using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.ViewModels.PackageManager;
using StabilityMatrix.Core.Attributes;
@@ -20,4 +22,9 @@ public partial class PackageInstallBrowserView : UserControlBase
vm.ClearSearchQuery();
}
}
+
+ private void AsyncImage_OnFailed(object? sender, AsyncImage.AsyncImageFailedEventArgs e)
+ {
+ Debug.WriteLine($"Failed to load image: {e.ErrorException?.Message}");
+ }
}
diff --git a/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml b/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml
index 91b2e671..7bf74c46 100644
--- a/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml
+++ b/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml
@@ -2,7 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:viewModels="clr-namespace:StabilityMatrix.Avalonia.ViewModels"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:designData="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
@@ -10,24 +9,26 @@
xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:models="clr-namespace:StabilityMatrix.Core.Models;assembly=StabilityMatrix.Core"
xmlns:database="clr-namespace:StabilityMatrix.Core.Models.Database;assembly=StabilityMatrix.Core"
- xmlns:extensions="clr-namespace:StabilityMatrix.Core.Models.Packages.Extensions;assembly=StabilityMatrix.Core"
xmlns:packageManager="clr-namespace:StabilityMatrix.Avalonia.ViewModels.PackageManager"
+ xmlns:labs="clr-namespace:Avalonia.Labs.Controls;assembly=Avalonia.Labs.Controls"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="packageManager:PackageInstallDetailViewModel"
x:CompileBindings="True"
d:DataContext="{x:Static designData:DesignData.PackageInstallDetailViewModel}"
x:Class="StabilityMatrix.Avalonia.Views.PackageManager.PackageInstallDetailView">
-
+
-
+ Margin="16, 16, 8, 8"
+ CornerRadius="8"
+ Source="{Binding SelectedPackage.PreviewImageUri}">
+
+
diff --git a/StabilityMatrix.Avalonia/Views/PackageManagerPage.axaml b/StabilityMatrix.Avalonia/Views/PackageManagerPage.axaml
index 81c912e6..ee2099d9 100644
--- a/StabilityMatrix.Avalonia/Views/PackageManagerPage.axaml
+++ b/StabilityMatrix.Avalonia/Views/PackageManagerPage.axaml
@@ -13,6 +13,7 @@
xmlns:converters="clr-namespace:StabilityMatrix.Avalonia.Converters"
xmlns:avalonia="clr-namespace:SpacedGridControl.Avalonia;assembly=SpacedGridControl.Avalonia"
xmlns:markupExtensions="clr-namespace:StabilityMatrix.Avalonia.MarkupExtensions"
+ xmlns:labs="clr-namespace:Avalonia.Labs.Controls;assembly=Avalonia.Labs.Controls"
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="450"
x:DataType="viewModels:PackageManagerViewModel"
x:CompileBindings="True"
@@ -44,15 +45,13 @@
-
diff --git a/StabilityMatrix.Core/StabilityMatrix.Core.csproj b/StabilityMatrix.Core/StabilityMatrix.Core.csproj
index de135217..5005b1bd 100644
--- a/StabilityMatrix.Core/StabilityMatrix.Core.csproj
+++ b/StabilityMatrix.Core/StabilityMatrix.Core.csproj
@@ -17,8 +17,8 @@
-
-
+
+
@@ -27,10 +27,10 @@
-
+
-
+
@@ -45,7 +45,7 @@
-
+
@@ -53,7 +53,7 @@
-
+
diff --git a/StabilityMatrix.Tests/StabilityMatrix.Tests.csproj b/StabilityMatrix.Tests/StabilityMatrix.Tests.csproj
index 6283704a..257b8f93 100644
--- a/StabilityMatrix.Tests/StabilityMatrix.Tests.csproj
+++ b/StabilityMatrix.Tests/StabilityMatrix.Tests.csproj
@@ -17,18 +17,18 @@
-
+
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj b/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj
index d4c1e79e..eb592e08 100644
--- a/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj
+++ b/StabilityMatrix.UITests/StabilityMatrix.UITests.csproj
@@ -15,16 +15,16 @@
-
+
-
-
+
+
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
From b2a76056afd02b244143b5a3f47fd14568dde92b Mon Sep 17 00:00:00 2001
From: JT
Date: Mon, 25 Mar 2024 23:30:57 -0700
Subject: [PATCH 26/34] phrasing
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 2787d790..8f66aa16 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,7 @@ Multi-Platform Package Manager and Inference UI for Stable Diffusion
- Embedded Git and Python dependencies, with no need for either to be globally installed
- Fully portable - move Stability Matrix's Data Directory to a new drive or computer at any time
-### ✨ Inference - A Reimagined Stable Diffusion Interface, Built-In to Stability Matrix
+### ✨ Inference - A Reimagined Interface for Stable Diffusion, Built-In to Stability Matrix
- Powerful auto-completion and syntax highlighting using a formal language grammar
- Workspaces open in tabs that save and load from `.smproj` project files
From 3af08e04f3d021c08a34c000ebe382475dcd24db Mon Sep 17 00:00:00 2001
From: JT
Date: Mon, 25 Mar 2024 23:36:58 -0700
Subject: [PATCH 27/34] more chagenlog
---
CHANGELOG.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ba1236d8..b1487a44 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,8 +10,10 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2
### Added
- Added OpenArt.AI workflow browser for ComfyUI workflows
### Changed
-- Updated to Avalonia 11.0.10
- Changed to a new image control for pages with many images
+- (Internal) Updated to Avalonia 11.0.10
+### Fixed
+- Improved performance when deleting many images from the Outputs page
## v2.10.0-dev.3
### Added
From 73771a29c16c11f298ac200dd05be4b0490df90c Mon Sep 17 00:00:00 2001
From: JT
Date: Mon, 25 Mar 2024 23:44:34 -0700
Subject: [PATCH 28/34] change PackageInstallDetailView back to
BetterAdvancedImage since the image should be cached from the previous page
---
.../Views/PackageManager/PackageInstallDetailView.axaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml b/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml
index 7bf74c46..84499d89 100644
--- a/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml
+++ b/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml
@@ -19,7 +19,7 @@
-
-
+
Date: Mon, 25 Mar 2024 23:46:33 -0700
Subject: [PATCH 29/34] remove console write
---
StabilityMatrix.Avalonia/ViewModels/OutputsPageViewModel.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/StabilityMatrix.Avalonia/ViewModels/OutputsPageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/OutputsPageViewModel.cs
index df39dd3d..da48a2e8 100644
--- a/StabilityMatrix.Avalonia/ViewModels/OutputsPageViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/OutputsPageViewModel.cs
@@ -145,7 +145,6 @@ public partial class OutputsPageViewModel : PageViewModelBase
.Subscribe(_ =>
{
NumItemsSelected = Outputs.Count(o => o.IsSelected);
- Console.WriteLine($"Subscribe called");
});
categoriesCache.Connect().DeferUntilLoaded().Bind(Categories).Subscribe();
From 597c4c9aec7f956b614ed922931fa6c989f18885 Mon Sep 17 00:00:00 2001
From: JT
Date: Tue, 26 Mar 2024 00:44:23 -0700
Subject: [PATCH 30/34] jsonignore uri & remove unused event handler
---
StabilityMatrix.Avalonia/Models/ImageSource.cs | 1 +
.../PackageManager/PackageInstallBrowserView.axaml.cs | 9 +--------
2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/StabilityMatrix.Avalonia/Models/ImageSource.cs b/StabilityMatrix.Avalonia/Models/ImageSource.cs
index 0da5749d..331a9c09 100644
--- a/StabilityMatrix.Avalonia/Models/ImageSource.cs
+++ b/StabilityMatrix.Avalonia/Models/ImageSource.cs
@@ -58,6 +58,7 @@ public record ImageSource : IDisposable, ITemplateKey
Bitmap = bitmap;
}
+ [JsonIgnore]
public Uri? Uri => LocalFile?.FullPath != null ? new Uri(LocalFile.FullPath) : RemoteUrl;
///
diff --git a/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallBrowserView.axaml.cs b/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallBrowserView.axaml.cs
index 08436b3b..5abbe50b 100644
--- a/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallBrowserView.axaml.cs
+++ b/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallBrowserView.axaml.cs
@@ -1,6 +1,4 @@
-using System.Diagnostics;
-using Avalonia.Input;
-using Avalonia.Labs.Controls;
+using Avalonia.Input;
using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.ViewModels.PackageManager;
using StabilityMatrix.Core.Attributes;
@@ -22,9 +20,4 @@ public partial class PackageInstallBrowserView : UserControlBase
vm.ClearSearchQuery();
}
}
-
- private void AsyncImage_OnFailed(object? sender, AsyncImage.AsyncImageFailedEventArgs e)
- {
- Debug.WriteLine($"Failed to load image: {e.ErrorException?.Message}");
- }
}
From 870aa20a80e4b48768020535549277fd17dd73e1 Mon Sep 17 00:00:00 2001
From: JT
Date: Mon, 1 Apr 2024 21:41:39 -0700
Subject: [PATCH 31/34] output sharing by default & invokeai fixes & some torch
version updates
---
CHANGELOG.md | 6 +
.../Dialogs/RecommendedModelsViewModel.cs | 2 +-
.../PackageInstallDetailViewModel.cs | 15 +-
.../Views/MainWindow.axaml | 4 +-
.../Views/MainWindow.axaml.cs | 5 +
.../PackageInstallDetailView.axaml | 128 +++++++++---------
.../Views/PackageManagerPage.axaml | 3 +-
.../SetupOutputSharingStep.cs | 15 ++
.../Models/Packages/ComfyUI.cs | 5 +-
.../Models/Packages/InvokeAI.cs | 57 +-------
.../Models/Packages/RuinedFooocus.cs | 8 +-
StabilityMatrix.Core/Python/PyVenvRunner.cs | 2 +-
12 files changed, 123 insertions(+), 127 deletions(-)
create mode 100644 StabilityMatrix.Core/Models/PackageModification/SetupOutputSharingStep.cs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b1487a44..cea82fd2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,11 +9,17 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2
## v2.10.0-preview.1
### Added
- Added OpenArt.AI workflow browser for ComfyUI workflows
+- Added Output Sharing toggle in Advanced Options during install flow
### Changed
- Changed to a new image control for pages with many images
+- Removed Symlink option for InvokeAI due to changes with InvokeAI v4.0+
+- Output sharing is now enabled by default for new installations
- (Internal) Updated to Avalonia 11.0.10
### Fixed
- Improved performance when deleting many images from the Outputs page
+- Fixed ComfyUI torch downgrading to 2.1.2 when updating
+- Fixed [#529](https://github.com/LykosAI/StabilityMatrix/issues/529) - OneTrainer requesting input during update
+- Fixed "Could not find entry point for InvokeAI" error on InvokeAI v4.0+
## v2.10.0-dev.3
### Added
diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/RecommendedModelsViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/RecommendedModelsViewModel.cs
index e037408e..a2aa480e 100644
--- a/StabilityMatrix.Avalonia/ViewModels/Dialogs/RecommendedModelsViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/RecommendedModelsViewModel.cs
@@ -75,7 +75,7 @@ public partial class RecommendedModelsViewModel : ContentDialogViewModelBase
CivitModels
.Connect()
.DeferUntilLoaded()
- .Filter(f => f.ModelVersion.BaseModel == "SDXL 1.0")
+ .Filter(f => f.ModelVersion.BaseModel == "SDXL 1.0" || f.ModelVersion.BaseModel == "Pony")
.Bind(SdxlModels)
.Subscribe();
}
diff --git a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs
index 9172d5c5..4e9b7fa2 100644
--- a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs
@@ -85,6 +85,9 @@ public partial class PackageInstallDetailViewModel(
[ObservableProperty]
private GitCommit? selectedCommit;
+ [ObservableProperty]
+ private bool isOutputSharingEnabled = true;
+
[ObservableProperty]
private bool canInstall;
@@ -97,6 +100,8 @@ public partial class PackageInstallDetailViewModel(
OnInstallNameChanged(InstallName);
+ CanInstall = false;
+
SelectedTorchVersion = SelectedPackage.GetRecommendedTorchVersion();
SelectedSharedFolderMethod = SelectedPackage.RecommendedSharedFolderMethod;
@@ -224,6 +229,8 @@ public partial class PackageInstallDetailViewModel(
installLocation
);
+ var setupOutputSharingStep = new SetupOutputSharingStep(SelectedPackage, installLocation);
+
var package = new InstalledPackage
{
DisplayName = InstallName,
@@ -234,7 +241,8 @@ public partial class PackageInstallDetailViewModel(
LaunchCommand = SelectedPackage.LaunchCommand,
LastUpdateCheck = DateTimeOffset.Now,
PreferredTorchVersion = SelectedTorchVersion,
- PreferredSharedFolderMethod = SelectedSharedFolderMethod
+ PreferredSharedFolderMethod = SelectedSharedFolderMethod,
+ UseSharedOutputFolder = IsOutputSharingEnabled
};
var addInstalledPackageStep = new AddInstalledPackageStep(settingsManager, package);
@@ -249,6 +257,11 @@ public partial class PackageInstallDetailViewModel(
addInstalledPackageStep
};
+ if (IsOutputSharingEnabled)
+ {
+ steps.Insert(steps.IndexOf(addInstalledPackageStep), setupOutputSharingStep);
+ }
+
var packageName = SelectedPackage.Name;
var runner = new PackageModificationRunner
diff --git a/StabilityMatrix.Avalonia/Views/MainWindow.axaml b/StabilityMatrix.Avalonia/Views/MainWindow.axaml
index 75613afc..306a1a37 100644
--- a/StabilityMatrix.Avalonia/Views/MainWindow.axaml
+++ b/StabilityMatrix.Avalonia/Views/MainWindow.axaml
@@ -70,11 +70,13 @@
Grid.RowSpan="2"
Name="NavigationView"
ItemInvoked="NavigationView_OnItemInvoked"
+ BackRequested="NavigationView_OnBackRequested"
PaneDisplayMode="Left"
IsPaneOpen="False"
OpenPaneLength="{Binding PaneWidth}"
IsSettingsVisible="False"
- IsBackEnabled="False"
+ IsBackEnabled="True"
+ IsBackButtonVisible="True"
MenuItemsSource="{Binding Pages, Mode=OneWay}"
FooterMenuItemsSource="{Binding FooterPages, Mode=OneWay}"
SelectedItem="{Binding SelectedCategory}">
diff --git a/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs b/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs
index c720f37b..eba477f8 100644
--- a/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs
+++ b/StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs
@@ -446,4 +446,9 @@ public partial class MainWindow : AppWindowBase
e.Handled = true;
navigationService.GoBack();
}
+
+ private void NavigationView_OnBackRequested(object? sender, NavigationViewBackRequestedEventArgs e)
+ {
+ navigationService.GoBack();
+ }
}
diff --git a/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml b/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml
index 84499d89..594b03eb 100644
--- a/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml
+++ b/StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallDetailView.axaml
@@ -16,7 +16,7 @@
x:CompileBindings="True"
d:DataContext="{x:Static designData:DesignData.PackageInstallDetailViewModel}"
x:Class="StabilityMatrix.Avalonia.Views.PackageManager.PackageInstallDetailView">
-
+
-
+
-
+
+ Content="{Binding SelectedPackage.LicenseType}" />
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/StabilityMatrix.Core/Models/PackageModification/SetupOutputSharingStep.cs b/StabilityMatrix.Core/Models/PackageModification/SetupOutputSharingStep.cs
new file mode 100644
index 00000000..f92ff7ef
--- /dev/null
+++ b/StabilityMatrix.Core/Models/PackageModification/SetupOutputSharingStep.cs
@@ -0,0 +1,15 @@
+using StabilityMatrix.Core.Models.Packages;
+using StabilityMatrix.Core.Models.Progress;
+
+namespace StabilityMatrix.Core.Models.PackageModification;
+
+public class SetupOutputSharingStep(BasePackage package, string installPath) : IPackageStep
+{
+ public Task ExecuteAsync(IProgress? progress = null)
+ {
+ package.SetupOutputFolderLinks(installPath);
+ return Task.CompletedTask;
+ }
+
+ public string ProgressTitle => "Setting up output sharing...";
+}
diff --git a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs
index da47bbb6..19843e75 100644
--- a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs
+++ b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs
@@ -213,7 +213,7 @@ public class ComfyUI(
_
=> pipArgs
.AddArg("--upgrade")
- .WithTorch("~=2.1.0")
+ .WithTorch()
.WithTorchVision()
.WithTorchExtraIndex(
torchVersion switch
@@ -233,9 +233,6 @@ public class ComfyUI(
switch (torchVersion)
{
- case TorchVersion.Cuda:
- pipArgs = pipArgs.WithXFormers("==0.0.22.post4");
- break;
case TorchVersion.Mps:
pipArgs = pipArgs.AddArg("mpmath==1.3.0");
break;
diff --git a/StabilityMatrix.Core/Models/Packages/InvokeAI.cs b/StabilityMatrix.Core/Models/Packages/InvokeAI.cs
index 6502f292..625a76f9 100644
--- a/StabilityMatrix.Core/Models/Packages/InvokeAI.cs
+++ b/StabilityMatrix.Core/Models/Packages/InvokeAI.cs
@@ -32,23 +32,14 @@ public class InvokeAI : BaseGitPackage
public override PackageDifficulty InstallerSortOrder => PackageDifficulty.Nightmare;
public override IReadOnlyList ExtraLaunchCommands =>
- new[]
- {
- "invokeai-configure",
- "invokeai-merge",
- "invokeai-metadata",
- "invokeai-model-install",
- "invokeai-node-cli",
- "invokeai-ti",
- "invokeai-update",
- };
+ new[] { "invokeai-db-maintenance", "invokeai-import-images", };
public override Uri PreviewImageUri =>
new("https://raw.githubusercontent.com/invoke-ai/InvokeAI/main/docs/assets/canvas_preview.png");
public override IEnumerable AvailableSharedFolderMethods =>
- new[] { SharedFolderMethod.Symlink, SharedFolderMethod.None };
- public override SharedFolderMethod RecommendedSharedFolderMethod => SharedFolderMethod.Symlink;
+ new[] { SharedFolderMethod.None };
+ public override SharedFolderMethod RecommendedSharedFolderMethod => SharedFolderMethod.None;
public override string MainBranch => "main";
@@ -127,23 +118,11 @@ public class InvokeAI : BaseGitPackage
Options = ["--allow-origins"]
},
new LaunchOptionDefinition
- {
- Name = "Always use CPU",
- Type = LaunchOptionType.Bool,
- Options = ["--always_use_cpu"]
- },
- new LaunchOptionDefinition
{
Name = "Precision",
Type = LaunchOptionType.Bool,
Options = ["--precision auto", "--precision float16", "--precision float32"]
},
- new LaunchOptionDefinition
- {
- Name = "Aggressively free up GPU memory after each operation",
- Type = LaunchOptionType.Bool,
- Options = ["--free_gpu_mem"]
- },
LaunchOptionDefinition.Extras
];
@@ -223,9 +202,9 @@ public class InvokeAI : BaseGitPackage
await venvRunner
.PipInstall(
new PipInstallArgs(args.Any() ? args.ToArray() : Array.Empty())
- .WithTorch("==2.1.2")
- .WithTorchVision("==0.16.2")
- .WithXFormers("==0.0.23post1")
+ .WithTorch("==2.2.1")
+ .WithTorchVision("==0.17.1")
+ .WithXFormers("==0.0.25")
.WithTorchExtraIndex("cu121"),
onConsoleOutput
)
@@ -262,24 +241,6 @@ public class InvokeAI : BaseGitPackage
.ConfigureAwait(false);
await venvRunner.PipInstall("rich packaging python-dotenv", onConsoleOutput).ConfigureAwait(false);
-
- progress?.Report(new ProgressReport(-1f, "Configuring InvokeAI", isIndeterminate: true));
-
- // need to setup model links before running invokeai-configure so it can do its conversion
- await SetupModelFolders(installLocation, selectedSharedFolderMethod).ConfigureAwait(false);
-
- await RunInvokeCommand(
- installLocation,
- "invokeai-configure",
- "--yes --skip-sd-weights",
- true,
- onConsoleOutput,
- spam3: true
- )
- .ConfigureAwait(false);
-
- await VenvRunner.Process.WaitForExitAsync();
-
progress?.Report(new ProgressReport(1f, "Done!", isIndeterminate: false));
}
@@ -362,12 +323,6 @@ public class InvokeAI : BaseGitPackage
await SetupVenv(installedPackagePath).ConfigureAwait(false);
- arguments = command switch
- {
- "invokeai-configure" => "--yes --skip-sd-weights",
- _ => arguments
- };
-
VenvRunner.EnvironmentVariables = GetEnvVars(installedPackagePath);
// fix frontend build missing for people who updated to v3.6 before the fix
diff --git a/StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs b/StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs
index 181abc32..96dc5d65 100644
--- a/StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs
+++ b/StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs
@@ -124,10 +124,10 @@ public class RuinedFooocus(
await venvRunner
.PipInstall(
new PipInstallArgs()
- .WithTorch("==2.0.1")
- .WithTorchVision("==0.15.2")
- .WithXFormers("==0.0.20")
- .WithTorchExtraIndex("cu118")
+ .WithTorch("==2.1.2")
+ .WithTorchVision("==0.16.2")
+ .WithXFormers("==0.0.23.post1")
+ .WithTorchExtraIndex("cu121")
.WithParsedFromRequirementsTxt(
await requirements.ReadAllTextAsync().ConfigureAwait(false),
excludePattern: "torch"
diff --git a/StabilityMatrix.Core/Python/PyVenvRunner.cs b/StabilityMatrix.Core/Python/PyVenvRunner.cs
index 2266498b..5dfc3a03 100644
--- a/StabilityMatrix.Core/Python/PyVenvRunner.cs
+++ b/StabilityMatrix.Core/Python/PyVenvRunner.cs
@@ -214,7 +214,7 @@ public class PyVenvRunner : IDisposable, IAsyncDisposable
});
SetPyvenvCfg(PyRunner.PythonDir);
- RunDetached(args.Prepend("-m pip install"), outputAction);
+ RunDetached(args.Prepend("-m pip install").Concat("--exists-action s"), outputAction);
await Process.WaitForExitAsync().ConfigureAwait(false);
// Check return code
From ca67f73ff6e66eb4f39db0af5fc6a40b6b48106f Mon Sep 17 00:00:00 2001
From: JT
Date: Mon, 1 Apr 2024 22:15:59 -0700
Subject: [PATCH 32/34] Fix duplicate InstallerSortOrder
---
StabilityMatrix.Core/Models/Packages/SDWebForge.cs | 2 --
1 file changed, 2 deletions(-)
diff --git a/StabilityMatrix.Core/Models/Packages/SDWebForge.cs b/StabilityMatrix.Core/Models/Packages/SDWebForge.cs
index b22c5285..69a501d9 100644
--- a/StabilityMatrix.Core/Models/Packages/SDWebForge.cs
+++ b/StabilityMatrix.Core/Models/Packages/SDWebForge.cs
@@ -35,8 +35,6 @@ public class SDWebForge(
"https://github.com/lllyasviel/stable-diffusion-webui-forge/assets/19834515/ca5e05ed-bd86-4ced-8662-f41034648e8c"
);
- public override PackageDifficulty InstallerSortOrder => PackageDifficulty.ReallyRecommended;
-
public override string MainBranch => "main";
public override bool ShouldIgnoreReleases => true;
public override IPackageExtensionManager ExtensionManager => null;
From 04db64fcfb129203343dc51cd7fcdaabb7ac4782 Mon Sep 17 00:00:00 2001
From: JT
Date: Tue, 2 Apr 2024 23:07:28 -0700
Subject: [PATCH 33/34] many change - Added more metadata to the image dialog
info flyout - Added Restart button to console page - Model download location
selector now searches all subfolders - Fixed Civitai model browser not
showing images when "Show NSFW" is disabled - Fixed crash when Installed
Workflows page is opened with no Workflows folder - Fixed progress bars not
displaying properly during package installs & updates
---
CHANGELOG.md | 13 +++-
.../Assets/sitecustomize.py | 14 ++++
.../DesignData/DesignData.cs | 2 +-
.../PackageSteps/UnpackSiteCustomizeStep.cs | 21 ++++++
.../Services/INavigationService.cs | 2 +
.../Services/NavigationService.cs | 2 +
.../CheckpointBrowserCardViewModel.cs | 5 +-
.../Dialogs/NewOneClickInstallViewModel.cs | 19 ++++--
.../Dialogs/SelectModelVersionViewModel.cs | 6 +-
.../ViewModels/InstalledWorkflowsViewModel.cs | 5 ++
.../PackageInstallDetailViewModel.cs | 3 +
.../PackageInstallProgressItemViewModel.cs | 15 ++++-
.../ViewModels/RunningPackageViewModel.cs | 10 ++-
.../Views/ConsoleOutputPage.axaml | 10 ++-
.../Views/Dialogs/ImageViewerDialog.axaml | 23 ++++++-
.../Extensions/ProgressExtensions.cs | 11 ++--
StabilityMatrix.Core/Models/Api/CivitImage.cs | 14 ++--
.../PackageModification/InstallPackageStep.cs | 2 +-
.../PackageModification/UpdatePackageStep.cs | 9 ++-
.../Models/Progress/ProgressReport.cs | 66 ++++++++++++++-----
20 files changed, 205 insertions(+), 47 deletions(-)
create mode 100644 StabilityMatrix.Avalonia/Models/PackageSteps/UnpackSiteCustomizeStep.cs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 043ccb1c..fa0e8fc8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,7 +5,18 @@ 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.10.0-preview.1
+## v2.10.0-pre.2
+### Added
+- Added more metadata to the image dialog info flyout
+- Added Restart button to console page
+### Changed
+- Model download location selector now searches all subfolders
+### Fixed
+- Fixed Civitai model browser not showing images when "Show NSFW" is disabled
+- Fixed crash when Installed Workflows page is opened with no Workflows folder
+- Fixed progress bars not displaying properly during package installs & updates
+
+## v2.10.0-pre.1
### Added
- Added OpenArt.AI workflow browser for ComfyUI workflows
- Added Output Sharing toggle in Advanced Options during install flow
diff --git a/StabilityMatrix.Avalonia/Assets/sitecustomize.py b/StabilityMatrix.Avalonia/Assets/sitecustomize.py
index b6ebb4c1..d154c13a 100644
--- a/StabilityMatrix.Avalonia/Assets/sitecustomize.py
+++ b/StabilityMatrix.Avalonia/Assets/sitecustomize.py
@@ -68,6 +68,20 @@ def _patch_rich_console():
pass
except Exception as e:
print("[sitecustomize error]:", e)
+
+ try:
+ from pip._vendor.rich import console
+
+ class _Console(console.Console):
+ @property
+ def is_terminal(self) -> bool:
+ return True
+
+ console.Console = _Console
+ except ImportError:
+ pass
+ except Exception as e:
+ print("[sitecustomize error]:", e)
_patch_rich_console()
diff --git a/StabilityMatrix.Avalonia/DesignData/DesignData.cs b/StabilityMatrix.Avalonia/DesignData/DesignData.cs
index 3fc6455b..471f4a53 100644
--- a/StabilityMatrix.Avalonia/DesignData/DesignData.cs
+++ b/StabilityMatrix.Avalonia/DesignData/DesignData.cs
@@ -360,7 +360,7 @@ public static class DesignData
{
new()
{
- Nsfw = "None",
+ NsfwLevel = 1,
Url =
"https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/"
+ "78fd2a0a-42b6-42b0-9815-81cb11bb3d05/00009-2423234823.jpeg"
diff --git a/StabilityMatrix.Avalonia/Models/PackageSteps/UnpackSiteCustomizeStep.cs b/StabilityMatrix.Avalonia/Models/PackageSteps/UnpackSiteCustomizeStep.cs
new file mode 100644
index 00000000..92e5f413
--- /dev/null
+++ b/StabilityMatrix.Avalonia/Models/PackageSteps/UnpackSiteCustomizeStep.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Threading.Tasks;
+using StabilityMatrix.Core.Models.FileInterfaces;
+using StabilityMatrix.Core.Models.PackageModification;
+using StabilityMatrix.Core.Models.Progress;
+using StabilityMatrix.Core.Python;
+
+namespace StabilityMatrix.Avalonia.Models.PackageSteps;
+
+public class UnpackSiteCustomizeStep(DirectoryPath venvPath) : IPackageStep
+{
+ public async Task ExecuteAsync(IProgress? progress = null)
+ {
+ var sitePackages = venvPath.JoinDir(PyVenvRunner.RelativeSitePackagesPath);
+ var file = sitePackages.JoinFile("sitecustomize.py");
+ file.Directory?.Create();
+ await Assets.PyScriptSiteCustomize.ExtractTo(file);
+ }
+
+ public string ProgressTitle => "Unpacking prerequisites...";
+}
diff --git a/StabilityMatrix.Avalonia/Services/INavigationService.cs b/StabilityMatrix.Avalonia/Services/INavigationService.cs
index f1aa8ba4..68f7f261 100644
--- a/StabilityMatrix.Avalonia/Services/INavigationService.cs
+++ b/StabilityMatrix.Avalonia/Services/INavigationService.cs
@@ -37,4 +37,6 @@ public interface INavigationService<[SuppressMessage("ReSharper", "UnusedTypePar
void NavigateTo(ViewModelBase viewModel, NavigationTransitionInfo? transitionInfo = null);
bool GoBack();
+
+ bool CanGoBack { get; }
}
diff --git a/StabilityMatrix.Avalonia/Services/NavigationService.cs b/StabilityMatrix.Avalonia/Services/NavigationService.cs
index c95d3068..8778f7ca 100644
--- a/StabilityMatrix.Avalonia/Services/NavigationService.cs
+++ b/StabilityMatrix.Avalonia/Services/NavigationService.cs
@@ -188,4 +188,6 @@ public class NavigationService : INavigationService
_frame.GoBack();
return true;
}
+
+ public bool CanGoBack => _frame?.CanGoBack ?? false;
}
diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs
index bcb2ae62..341a3913 100644
--- a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
@@ -159,7 +160,7 @@ public partial class CheckpointBrowserCardViewModel : Base.ProgressViewModel
// Try to find a valid image
var image = images
?.Where(img => LocalModelFile.SupportedImageExtensions.Any(img.Url.Contains))
- .FirstOrDefault(image => nsfwEnabled || image.Nsfw == "None");
+ .FirstOrDefault(image => nsfwEnabled || image.NsfwLevel <= 1);
if (image != null)
{
CardImage = new Uri(image.Url);
@@ -256,7 +257,7 @@ public partial class CheckpointBrowserCardViewModel : Base.ProgressViewModel
{
var subFolder =
viewModel?.SelectedInstallLocation
- ?? Path.Combine("Models", model.Type.ConvertTo().GetStringValue());
+ ?? Path.Combine(@"Models", model.Type.ConvertTo().GetStringValue());
downloadPath = Path.Combine(settingsManager.LibraryDir, subFolder);
}
diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/NewOneClickInstallViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/NewOneClickInstallViewModel.cs
index c8592cc7..425b20e7 100644
--- a/StabilityMatrix.Avalonia/ViewModels/Dialogs/NewOneClickInstallViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/NewOneClickInstallViewModel.cs
@@ -12,6 +12,7 @@ using DynamicData;
using DynamicData.Binding;
using Microsoft.Extensions.Logging;
using StabilityMatrix.Avalonia.Extensions;
+using StabilityMatrix.Avalonia.Models.PackageSteps;
using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Core.Attributes;
@@ -107,18 +108,19 @@ public partial class NewOneClickInstallViewModel : ContentDialogViewModelBase
{
Task.Run(async () =>
{
+ var installLocation = Path.Combine(
+ settingsManager.LibraryDir,
+ "Packages",
+ selectedPackage.Name
+ );
+
var steps = new List
{
new SetPackageInstallingStep(settingsManager, selectedPackage.Name),
- new SetupPrerequisitesStep(prerequisiteHelper, pyRunner, selectedPackage)
+ new SetupPrerequisitesStep(prerequisiteHelper, pyRunner, selectedPackage),
};
// get latest version & download & install
- var installLocation = Path.Combine(
- settingsManager.LibraryDir,
- "Packages",
- selectedPackage.Name
- );
if (Directory.Exists(installLocation))
{
var installPath = new DirectoryPath(installLocation);
@@ -148,6 +150,11 @@ public partial class NewOneClickInstallViewModel : ContentDialogViewModelBase
);
steps.Add(downloadStep);
+ var unpackSiteCustomizeStep = new UnpackSiteCustomizeStep(
+ Path.Combine(installLocation, "venv")
+ );
+ steps.Add(unpackSiteCustomizeStep);
+
var installStep = new InstallPackageStep(
selectedPackage,
torchVersion,
diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs
index 9ef4c378..0b84de65 100644
--- a/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs
@@ -99,7 +99,7 @@ public partial class SelectModelVersionViewModel(
var allImages = value
?.ModelVersion
?.Images
- ?.Where(img => nsfwEnabled || img.Nsfw == "None")
+ ?.Where(img => nsfwEnabled || img.NsfwLevel <= 2)
?.Select(x => new ImageSource(x.Url))
.ToList();
@@ -316,7 +316,9 @@ public partial class SelectModelVersionViewModel(
installLocations.Add(downloadDirectory.ToString().Replace(rootModelsDirectory, "Models"));
- foreach (var directory in downloadDirectory.EnumerateDirectories())
+ foreach (
+ var directory in downloadDirectory.EnumerateDirectories(searchOption: SearchOption.AllDirectories)
+ )
{
installLocations.Add(directory.ToString().Replace(rootModelsDirectory, "Models"));
}
diff --git a/StabilityMatrix.Avalonia/ViewModels/InstalledWorkflowsViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/InstalledWorkflowsViewModel.cs
index b765c797..0bc14b2c 100644
--- a/StabilityMatrix.Avalonia/ViewModels/InstalledWorkflowsViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/InstalledWorkflowsViewModel.cs
@@ -59,6 +59,11 @@ public partial class InstalledWorkflowsViewModel(
{
workflowsCache.Clear();
+ if (!Directory.Exists(settingsManager.WorkflowDirectory))
+ {
+ Directory.CreateDirectory(settingsManager.WorkflowDirectory);
+ }
+
foreach (
var workflowPath in Directory.EnumerateFiles(
settingsManager.WorkflowDirectory,
diff --git a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs
index 4e9b7fa2..6c24efc2 100644
--- a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs
@@ -14,6 +14,7 @@ using Microsoft.Extensions.Logging;
using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.Extensions;
using StabilityMatrix.Avalonia.Languages;
+using StabilityMatrix.Avalonia.Models.PackageSteps;
using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Core.Attributes;
@@ -188,6 +189,7 @@ public partial class PackageInstallDetailViewModel(
}
var prereqStep = new SetupPrerequisitesStep(prerequisiteHelper, pyRunner, SelectedPackage);
+ var unpackSiteCustomizeStep = new UnpackSiteCustomizeStep(Path.Combine(installLocation, "venv"));
var downloadOptions = new DownloadPackageVersionOptions();
var installedVersion = new InstalledPackageVersion();
@@ -252,6 +254,7 @@ public partial class PackageInstallDetailViewModel(
setPackageInstallingStep,
prereqStep,
downloadStep,
+ unpackSiteCustomizeStep,
installStep,
setupModelFoldersStep,
addInstalledPackageStep
diff --git a/StabilityMatrix.Avalonia/ViewModels/Progress/PackageInstallProgressItemViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Progress/PackageInstallProgressItemViewModel.cs
index cd4f5f46..fb74fc17 100644
--- a/StabilityMatrix.Avalonia/ViewModels/Progress/PackageInstallProgressItemViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/Progress/PackageInstallProgressItemViewModel.cs
@@ -49,10 +49,21 @@ public class PackageInstallProgressItemViewModel : ProgressItemViewModelBase
Name = packageModificationRunner.CurrentStep?.ProgressTitle;
Failed = packageModificationRunner.Failed;
- if (string.IsNullOrWhiteSpace(e.Message) || e.Message.Contains("Downloading..."))
+ if (e.ProcessOutput == null && string.IsNullOrWhiteSpace(e.Message))
return;
- Progress.Console.PostLine(e.Message);
+ if (!string.IsNullOrWhiteSpace(e.Message) && e.Message.Contains("Downloading..."))
+ return;
+
+ if (e.ProcessOutput != null)
+ {
+ Progress.Console.Post(e.ProcessOutput.Value);
+ }
+ else
+ {
+ Progress.Console.PostLine(e.Message);
+ }
+
EventManager.Instance.OnScrollToBottomRequested();
if (
diff --git a/StabilityMatrix.Avalonia/ViewModels/RunningPackageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/RunningPackageViewModel.cs
index 38011e04..73f89a8b 100644
--- a/StabilityMatrix.Avalonia/ViewModels/RunningPackageViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/RunningPackageViewModel.cs
@@ -104,6 +104,14 @@ public partial class RunningPackageViewModel : PageViewModelBase, IDisposable, I
}
}
+ [RelayCommand]
+ private async Task Restart()
+ {
+ await Stop();
+ await Task.Delay(100);
+ LaunchPackage();
+ }
+
[RelayCommand]
private void LaunchPackage()
{
@@ -113,10 +121,10 @@ public partial class RunningPackageViewModel : PageViewModelBase, IDisposable, I
[RelayCommand]
private async Task Stop()
{
+ IsRunning = false;
await runningPackageService.StopPackage(RunningPackage.InstalledPackage.Id);
Console.PostLine($"{Environment.NewLine}Stopped process at {DateTimeOffset.Now}");
await Console.StopUpdatesAsync();
- IsRunning = false;
}
[RelayCommand]
diff --git a/StabilityMatrix.Avalonia/Views/ConsoleOutputPage.axaml b/StabilityMatrix.Avalonia/Views/ConsoleOutputPage.axaml
index 7d86b568..d44b44e6 100644
--- a/StabilityMatrix.Avalonia/Views/ConsoleOutputPage.axaml
+++ b/StabilityMatrix.Avalonia/Views/ConsoleOutputPage.axaml
@@ -34,8 +34,16 @@
Command="{Binding LaunchPackageCommand}"
VerticalAlignment="Center"
Label="{x:Static lang:Resources.Action_Launch}" />
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
? AsProcessOutputHandler(
- this IProgress? progress
- )
+ public static Action? AsProcessOutputHandler(this IProgress? progress)
{
return progress == null
? null
: output =>
{
progress.Report(
- new ProgressReport { IsIndeterminate = true, Message = output.Text }
+ new ProgressReport
+ {
+ IsIndeterminate = true,
+ Message = output.Text,
+ ProcessOutput = output
+ }
);
};
}
diff --git a/StabilityMatrix.Core/Models/Api/CivitImage.cs b/StabilityMatrix.Core/Models/Api/CivitImage.cs
index 0cab1b50..82aadce2 100644
--- a/StabilityMatrix.Core/Models/Api/CivitImage.cs
+++ b/StabilityMatrix.Core/Models/Api/CivitImage.cs
@@ -6,18 +6,18 @@ public class CivitImage
{
[JsonPropertyName("url")]
public string Url { get; set; }
-
- [JsonPropertyName("nsfw")]
- public string Nsfw { get; set; }
-
+
+ [JsonPropertyName("nsfwLevel")]
+ public int? NsfwLevel { get; set; }
+
[JsonPropertyName("width")]
public int Width { get; set; }
-
+
[JsonPropertyName("height")]
public int Height { get; set; }
-
+
[JsonPropertyName("hash")]
public string Hash { get; set; }
-
+
// TODO: "meta" ( object? )
}
diff --git a/StabilityMatrix.Core/Models/PackageModification/InstallPackageStep.cs b/StabilityMatrix.Core/Models/PackageModification/InstallPackageStep.cs
index ff0d20ae..25c6e357 100644
--- a/StabilityMatrix.Core/Models/PackageModification/InstallPackageStep.cs
+++ b/StabilityMatrix.Core/Models/PackageModification/InstallPackageStep.cs
@@ -31,7 +31,7 @@ public class InstallPackageStep : IPackageStep
{
void OnConsoleOutput(ProcessOutput output)
{
- progress?.Report(new ProgressReport { IsIndeterminate = true, Message = output.Text });
+ progress?.Report(new ProgressReport { IsIndeterminate = true, ProcessOutput = output });
}
await package
diff --git a/StabilityMatrix.Core/Models/PackageModification/UpdatePackageStep.cs b/StabilityMatrix.Core/Models/PackageModification/UpdatePackageStep.cs
index 11a8e111..446a49d7 100644
--- a/StabilityMatrix.Core/Models/PackageModification/UpdatePackageStep.cs
+++ b/StabilityMatrix.Core/Models/PackageModification/UpdatePackageStep.cs
@@ -31,7 +31,14 @@ public class UpdatePackageStep : IPackageStep
void OnConsoleOutput(ProcessOutput output)
{
- progress?.Report(new ProgressReport { IsIndeterminate = true, Message = output.Text });
+ progress?.Report(
+ new ProgressReport
+ {
+ IsIndeterminate = true,
+ Message = output.Text,
+ ProcessOutput = output
+ }
+ );
}
var updateResult = await basePackage
diff --git a/StabilityMatrix.Core/Models/Progress/ProgressReport.cs b/StabilityMatrix.Core/Models/Progress/ProgressReport.cs
index 22657d70..6ffcec6d 100644
--- a/StabilityMatrix.Core/Models/Progress/ProgressReport.cs
+++ b/StabilityMatrix.Core/Models/Progress/ProgressReport.cs
@@ -1,4 +1,6 @@
-namespace StabilityMatrix.Core.Models.Progress;
+using StabilityMatrix.Core.Processes;
+
+namespace StabilityMatrix.Core.Models.Progress;
public record struct ProgressReport
{
@@ -6,21 +8,30 @@ public record struct ProgressReport
/// Progress value as percentage between 0 and 1.
///
public double? Progress { get; init; } = 0;
+
///
/// Current progress count.
///
public ulong? Current { get; init; } = 0;
+
///
/// Total progress count.
///
public ulong? Total { get; init; } = 0;
public string? Title { get; init; }
public string? Message { get; init; }
+ public ProcessOutput? ProcessOutput { get; init; }
public bool IsIndeterminate { get; init; } = false;
- public float Percentage => (float) Math.Ceiling(Math.Clamp(Progress ?? 0, 0, 1) * 100);
+ public float Percentage => (float)Math.Ceiling(Math.Clamp(Progress ?? 0, 0, 1) * 100);
public ProgressType Type { get; init; } = ProgressType.Generic;
-
- public ProgressReport(double progress, string? title = null, string? message = null, bool isIndeterminate = false, ProgressType type = ProgressType.Generic)
+
+ public ProgressReport(
+ double progress,
+ string? title = null,
+ string? message = null,
+ bool isIndeterminate = false,
+ ProgressType type = ProgressType.Generic
+ )
{
Progress = progress;
Title = title;
@@ -28,32 +39,53 @@ public record struct ProgressReport
IsIndeterminate = isIndeterminate;
Type = type;
}
-
- public ProgressReport(ulong current, ulong total, string? title = null, string? message = null, bool isIndeterminate = false, ProgressType type = ProgressType.Generic)
+
+ public ProgressReport(
+ ulong current,
+ ulong total,
+ string? title = null,
+ string? message = null,
+ bool isIndeterminate = false,
+ ProgressType type = ProgressType.Generic
+ )
{
Current = current;
Total = total;
- Progress = (double) current / total;
+ Progress = (double)current / total;
Title = title;
Message = message;
IsIndeterminate = isIndeterminate;
Type = type;
}
-
- public ProgressReport(int current, int total, string? title = null, string? message = null, bool isIndeterminate = false, ProgressType type = ProgressType.Generic)
+
+ public ProgressReport(
+ int current,
+ int total,
+ string? title = null,
+ string? message = null,
+ bool isIndeterminate = false,
+ ProgressType type = ProgressType.Generic
+ )
{
- if (current < 0) throw new ArgumentOutOfRangeException(nameof(current), "Current progress cannot negative.");
- if (total < 0) throw new ArgumentOutOfRangeException(nameof(total), "Total progress cannot be negative.");
- Current = (ulong) current;
- Total = (ulong) total;
- Progress = (double) current / total;
+ if (current < 0)
+ throw new ArgumentOutOfRangeException(nameof(current), "Current progress cannot negative.");
+ if (total < 0)
+ throw new ArgumentOutOfRangeException(nameof(total), "Total progress cannot be negative.");
+ Current = (ulong)current;
+ Total = (ulong)total;
+ Progress = (double)current / total;
Title = title;
Message = message;
IsIndeterminate = isIndeterminate;
Type = type;
}
-
- public ProgressReport(ulong current, string? title = null, string? message = null, ProgressType type = ProgressType.Generic)
+
+ public ProgressReport(
+ ulong current,
+ string? title = null,
+ string? message = null,
+ ProgressType type = ProgressType.Generic
+ )
{
Current = current;
Title = title;
@@ -61,6 +93,6 @@ public record struct ProgressReport
IsIndeterminate = true;
Type = type;
}
-
+
// Implicit conversion from action
}
From 61abe7a1f62d71123db03866788448952dbca7ec Mon Sep 17 00:00:00 2001
From: JT
Date: Tue, 2 Apr 2024 23:09:00 -0700
Subject: [PATCH 34/34] use same nsfwlevel
---
.../ViewModels/Dialogs/SelectModelVersionViewModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs
index 0b84de65..338aa20d 100644
--- a/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs
@@ -99,7 +99,7 @@ public partial class SelectModelVersionViewModel(
var allImages = value
?.ModelVersion
?.Images
- ?.Where(img => nsfwEnabled || img.NsfwLevel <= 2)
+ ?.Where(img => nsfwEnabled || img.NsfwLevel <= 1)
?.Select(x => new ImageSource(x.Url))
.ToList();