JT
9 months ago
14 changed files with 8806 additions and 35 deletions
@ -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; } |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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> |
@ -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(); |
||||
} |
||||
} |
Loading…
Reference in new issue