Browse Source

just put the whole json in there (for now)

pull/629/head
JT 9 months ago
parent
commit
5e7b9286ac
  1. 3
      CHANGELOG.md
  2. 56
      StabilityMatrix.Avalonia/DesignData/DesignData.cs
  3. 27
      StabilityMatrix.Avalonia/Languages/Resources.Designer.cs
  4. 9
      StabilityMatrix.Avalonia/Languages/Resources.resx
  5. 10
      StabilityMatrix.Avalonia/Models/OpenArtCustomNode.cs
  6. 20
      StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CheckpointBrowserCardViewModel.cs
  7. 93
      StabilityMatrix.Avalonia/ViewModels/Dialogs/OpenArtWorkflowViewModel.cs
  8. 47
      StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
  9. 100
      StabilityMatrix.Avalonia/Views/Dialogs/OpenArtWorkflowDialog.axaml
  10. 13
      StabilityMatrix.Avalonia/Views/Dialogs/OpenArtWorkflowDialog.axaml.cs
  11. 14
      StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml
  12. 23
      StabilityMatrix.Core/Helper/Utilities.cs
  13. 6
      StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResult.cs
  14. 8420
      StabilityMatrix.Core/Models/ComfyNodeMap.cs

3
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

56
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<ControlNetCardViewModel>();
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();

27
StabilityMatrix.Avalonia/Languages/Resources.Designer.cs generated

@ -374,6 +374,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Open on OpenArt.
/// </summary>
public static string Action_OpenOnOpenArt {
get {
return ResourceManager.GetString("Action_OpenOnOpenArt", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Open Project....
/// </summary>
@ -1688,6 +1697,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Node Details.
/// </summary>
public static string Label_NodeDetails {
get {
return ResourceManager.GetString("Label_NodeDetails", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No extensions found..
/// </summary>
@ -2435,6 +2453,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Workflow Description.
/// </summary>
public static string Label_WorkflowDescription {
get {
return ResourceManager.GetString("Label_WorkflowDescription", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Workflows.
/// </summary>

9
StabilityMatrix.Avalonia/Languages/Resources.resx

@ -984,4 +984,13 @@
<data name="Label_Config" xml:space="preserve">
<value>Config</value>
</data>
<data name="Action_OpenOnOpenArt" xml:space="preserve">
<value>Open on OpenArt</value>
</data>
<data name="Label_NodeDetails" xml:space="preserve">
<value>Node Details</value>
</data>
<data name="Label_WorkflowDescription" xml:space="preserve">
<value>Workflow Description</value>
</data>
</root>

10
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<string> Children { get; set; } = [];
public bool IsInstalled { get; set; }
}

20
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<SelectModelVersionViewModel>();
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("<br/>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("<br />", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</p>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h1>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h2>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h3>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h4>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h5>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h6>", $"{Environment.NewLine}{Environment.NewLine}") ?? string.Empty;
prunedDescription = HtmlRegex().Replace(prunedDescription, string.Empty);
return prunedDescription;
}
private static async Task<FilePath> SaveCmInfo(
CivitModel model,
CivitModelVersion modelVersion,

93
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<OpenArtCustomNode> customNodes = [];
[ObservableProperty]
private string prunedDescription = string.Empty;
public override void OnLoaded()
{
CustomNodes = new ObservableCollection<OpenArtCustomNode>(ParseNodes(Workflow.NodesIndex.ToList()));
PrunedDescription = Utilities.RemoveHtml(Workflow.Description);
}
[Localizable(false)]
private List<OpenArtCustomNode> ParseNodes(List<string> nodes)
{
var indexOfFirstDot = nodes.IndexOf(".");
if (indexOfFirstDot != -1)
{
nodes = nodes[(indexOfFirstDot + 1)..];
}
var installedNodes = new List<string>();
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>();
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;
}
}

47
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<OpenArtSearchResult, string> searchResultsCache = new(x => x.Id);
private readonly SourceCache<OpenArtSearchResult, string> 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;

100
StabilityMatrix.Avalonia/Views/Dialogs/OpenArtWorkflowDialog.axaml

@ -0,0 +1,100 @@
<controls:UserControlBase xmlns="https://github.com/avaloniaui"
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:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:dialogs="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Dialogs"
xmlns:designData="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:models="clr-namespace:StabilityMatrix.Avalonia.Models"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
xmlns:avalonia="https://github.com/projektanker/icons.avalonia"
mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="650"
x:DataType="dialogs:OpenArtWorkflowViewModel"
d:DataContext="{x:Static designData:DesignData.OpenArtWorkflowViewModel}"
x:Class="StabilityMatrix.Avalonia.Views.Dialogs.OpenArtWorkflowDialog">
<Grid RowDefinitions="Auto, Auto, Auto, Auto"
ColumnDefinitions="*, 2*"
HorizontalAlignment="Stretch"
Width="600">
<TextBlock Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
FontSize="20"
TextAlignment="Left"
Margin="8,8,0,4"
ToolTip.Tip="{Binding Workflow.Name}">
<Run Text="{Binding Workflow.Name}"/>
<Run Text="- by"/>
<Run Text="{Binding Workflow.Creator.Name}"/>
</TextBlock>
<controls:BetterAdvancedImage Grid.Column="0"
Grid.Row="2"
Source="{Binding Workflow.Thumbnails[0].Url}"
Height="300"
Margin="8"
Stretch="UniformToFill"
CornerRadius="8" />
<controls:Card Grid.Row="2" Grid.Column="1"
VerticalAlignment="Top"
Margin="8">
<ScrollViewer MaxHeight="270">
<TextBlock Text="{Binding PrunedDescription}"
TextWrapping="Wrap"
Margin="4"/>
</ScrollViewer>
</controls:Card>
<Expander Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="2"
Header="{x:Static lang:Resources.Label_NodeDetails}"
ExpandDirection="Down"
Margin="8, 8">
<ScrollViewer MaxHeight="225">
<ItemsControl ItemsSource="{Binding CustomNodes}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type models:OpenArtCustomNode}">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}"
FontWeight="SemiBold"
FontSize="16" />
<avalonia:Icon Value="fa-solid fa-circle-check"
Foreground="Lime"
VerticalAlignment="Center"
Margin="4"
IsVisible="{Binding IsInstalled}"/>
</StackPanel>
<ItemsControl Margin="0,4"
ItemsSource="{Binding Children}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type system:String}">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding ., StringFormat={} - {0}}"
Margin="4,0,0,0" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Expander>
</Grid>
</controls:UserControlBase>

13
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();
}
}

14
StabilityMatrix.Avalonia/Views/OpenArtBrowserPage.axaml

@ -66,6 +66,11 @@
<input:StandardUICommand
x:Key="OpenModelCommand"
Command="{Binding OpenModelCommand}" />
<input:StandardUICommand
x:Key="OpenWorkflowCommand"
Command="{Binding OpenWorkflowCommand}" />
<converters:KiloFormatterStringConverter x:Key="KiloFormatterConverter" />
<DataTemplate x:Key="OpenArtWorkflowTemplate" DataType="{x:Type openArt:OpenArtSearchResult}">
<Border
@ -90,10 +95,9 @@
Padding="0"
BorderThickness="0"
VerticalContentAlignment="Top"
CornerRadius="8">
<!-- Command="{Binding ShowVersionDialogCommand}" -->
<!-- CommandParameter="{Binding CivitModel}" -->
<!-- IsEnabled="{Binding !IsImporting}"> -->
CornerRadius="8"
Command="{StaticResource OpenWorkflowCommand}"
CommandParameter="{Binding }">
<Grid RowDefinitions="*, Auto">
<controls:BetterAdvancedImage
Grid.Row="0"
@ -221,7 +225,7 @@
<MenuFlyout>
<MenuItem Command="{StaticResource OpenModelCommand}"
CommandParameter="{Binding }"
Header="{x:Static lang:Resources.Action_OpenOnCivitAi}">
Header="{x:Static lang:Resources.Action_OpenOnOpenArt}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="Open" />
</MenuItem.Icon>

23
StabilityMatrix.Core/Helper/Utilities.cs

@ -1,8 +1,9 @@
using System.Reflection;
using System.Text.RegularExpressions;
namespace StabilityMatrix.Core.Helper;
public static class Utilities
public static partial class Utilities
{
public static string GetAppVersion()
{
@ -63,4 +64,24 @@ public static class Utilities
return stream;
}
public static string RemoveHtml(string? stringWithHtml)
{
var pruned =
stringWithHtml
?.Replace("<br/>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("<br />", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</p>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h1>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h2>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h3>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h4>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h5>", $"{Environment.NewLine}{Environment.NewLine}")
.Replace("</h6>", $"{Environment.NewLine}{Environment.NewLine}") ?? string.Empty;
pruned = HtmlRegex().Replace(pruned, string.Empty);
return pruned;
}
[GeneratedRegex("<[^>]+>")]
private static partial Regex HtmlRegex();
}

6
StabilityMatrix.Core/Models/Api/OpenArt/OpenArtSearchResult.cs

@ -10,9 +10,6 @@ public class OpenArtSearchResult
[JsonPropertyName("creator")]
public OpenArtCreator Creator { get; set; }
[JsonPropertyName("updated_at")]
public DateTimeOffset UpdatedAt { get; set; }
[JsonPropertyName("stats")]
public OpenArtStats Stats { get; set; }
@ -25,9 +22,6 @@ public class OpenArtSearchResult
[JsonPropertyName("description")]
public string Description { get; set; }
[JsonPropertyName("created_at")]
public DateTimeOffset CreatedAt { get; set; }
[JsonPropertyName("categories")]
public IEnumerable<string> Categories { get; set; }

8420
StabilityMatrix.Core/Models/ComfyNodeMap.cs

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save